Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terminal: Improve default locale handling #18967

Merged
merged 1 commit into from
Oct 11, 2024
Merged

Conversation

shish
Copy link
Contributor

@shish shish commented Oct 9, 2024

terminal: Improve default locale handling

  • Use LANG instead of LC_ALL (LC_ALL is the highest priority which will override any other end-user settings; when that isn't set things fall back to separate LC_* variables; and when those aren't set things fall back to LANG). [0]
  • Only set LANG for our child if necessary (if it already exists in the parent, then the child will inherit that, no need for us to do anything)

[0] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02

Tested cases:

  • unset LANG ; cargo run: locale inside zed's terminal is set to en_US.UTF-8
  • export LANG=en_GB.UTF-8 ; cargo run: locale inside zed's terminal is set to en_GB.UTF-8

Release Notes:

  • Use the system locale in the terminal instead of forcing en_US.UTF-8

Copy link

cla-bot bot commented Oct 9, 2024

We require contributors to sign our Contributor License Agreement, and we don't have @shish on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.

@shish
Copy link
Contributor Author

shish commented Oct 10, 2024

@cla-bot check

(although zed.dev appears to be melting - 90% "internal server error" responses at every step of the CLA signing process...)

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Oct 10, 2024
Copy link

cla-bot bot commented Oct 10, 2024

The cla-bot has been summoned, and re-checked this pull request!

@someone13574
Copy link
Contributor

someone13574 commented Oct 10, 2024

Heads up that macOS has some "special" locale requirements. Not sure that that applies to this change or not (I don't think it should if you are just changing which variable is set). #13691 (comment)

@shish
Copy link
Contributor Author

shish commented Oct 10, 2024

I don't have a mac device to test with, but reading the code and the specs, I think this new code should still work there :)

Though reading that thread makes me wonder what's up - that thread seems to imply that the env hashmap should already contain variables inherited from the parent, and only in some specific circumstances (macos + launched from .app) those are missing -- but in my testing (run on linux via cargo run), the env hashmap is always empty, and variables like LANG need to be copied from the parent manually using env::var() (as this PR does)...

Regardless, while I'm not certain what the best fix is, I am pretty confident that this PR is a good step forwards compared to the status quo :)

@mrnugget
Copy link
Member

Hey! Thanks for opening this. I'm not as deep in this topic as you are, so I was wondering whether you think your PR here clashes with what we discussed here: #13691 (comment)

@someone13574
Copy link
Contributor

Hey! Thanks for opening this. I'm not as deep in this topic as you are, so I was wondering whether you think your PR here clashes with what we discussed here: #13691 (comment)

Already mentioned above.

@shish
Copy link
Contributor Author

shish commented Oct 10, 2024

So digging into this even further, I think we're both not-quite-optimal and I had misunderstood what the env hashmap is (looks like it is a list of overrides to be applied on top of the inherited environment, not a complete environment itself)

My gut says that if you launch zed from a terminal, and then launch a terminal inside zed, then the inner terminal should have the same environment as the outside terminal (minus a few zed-specific additions such as ZED_TERM=true) - and if the outer terminal has some kind of locale settings, we should leave those as-is.

For the MacOS case of "sometimes there is no locale set, which breaks things", we probably do want to ensure some kind of fallback locale is set (but using the low-priority LANG instead of the high-priority LC_ALL, so that the user would be able to override it)

So my current code as-is would cover all cases correctly, but not optimally (with the current code, if the user has locale settings, then we copy-paste them into the override list -- it'd be better to leave the override list empty if an override isn't needed)

@shish shish changed the title Better default locale in the terminal [terminal] Better default locale handling Oct 10, 2024
@shish
Copy link
Contributor Author

shish commented Oct 10, 2024

Actually there are even more layers in this rabbit hole -- looks like the env supplied to this function is supposed to contain the complete parent environment (If I'm reading [0] correctly), not only overrides... but that env is empty for some reason.

[0]

// Start with the environment that we might have inherited from the Zed CLI.
let mut env = self
.environment
.read(cx)
.get_cli_environment()
.unwrap_or_default();
// Then extend it with the explicit env variables from the settings, so they take
// precedence.
env.extend(settings.env.clone());

So... the correct-est behaviour would be to fix that inheritance process, and then only set LANG if it doesn't exist inside env already

@maxdeviant maxdeviant changed the title [terminal] Better default locale handling terminal: Improve default locale handling Oct 10, 2024
@shish shish force-pushed the pr18967 branch 2 times, most recently from 745fa15 to 817fb55 Compare October 10, 2024 14:08
@shish
Copy link
Contributor Author

shish commented Oct 10, 2024

Looking into "reasons why the zed CLI might report an empty environment", I believe my case is a related-but-separate bug (cargo run in the root results in env being set to an empty HashMap, when the comment says "Start with the environment that we might have inherited from the Zed CLI") - however there are other cases where the environment is intentionally None[0], so we do need to handle that in any case.

[0]

let environment = ProjectEnvironment::new(&worktree_store, None, cx);

@mrnugget
Copy link
Member

Already mentioned above.

Man, I swear I didn't see the two comments above mine 🤦 Sorry about that!

Looking into "reasons why the zed CLI might report an empty environment", I believe my case is a related-but-separate bug (cargo run in the root results in env being set to an empty HashMap, when the comment says "Start with the environment that we might have inherited from the Zed CLI")

It's not a bug. When you run cargo run, the zed binary is launched with its stdout/stdin being a TTY, in which case the zed process itself inherits the environment of the parent process. And every process launched by Zed inherits the Zed environment. No manual intervention necessary.

When you run the Zed CLI — also called zed, but actually an alias for cli, which is in the cli crate — that spawns the Zed process. If that's the first time it spawns it, environment is inherited. But every other invocation doesn't spawn a new process, so no automatic Unix env inheritance, which means we have to manually add the environment, which is the code you linked to.

(I actually wrote even more about this whole environment stuff here: https://github.com/zed-industries/zed/blob/main/docs/src/environment.md)

Now, all that being said, if you think this change is good and @someone13574 also thinks it makes sense — let's try it?

* Use `LANG` instead of `LC_ALL` (`LC_ALL` is the highest priority which will override any other end-user settings; when that isn't set things fall back to separate `LC_*` variables; and when those aren't set things fall back to `LANG`). [0]
* Only set `LANG` for our child if necessary (if it already exists in the parent, then the child will inherit that, no need for us to do anything)

[0] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02

Tested cases:

- `unset LANG ; cargo run`: locale inside zed's terminal is set to  `en_US.UTF-8`
- `export LANG=en_GB.UTF-8 ; cargo run`: locale inside zed's terminal is set to `en_GB.UTF-8`

Release Notes:

- Use the system locale in the terminal instead of forcing `en_US.UTF-8`
@shish
Copy link
Contributor Author

shish commented Oct 11, 2024

Thank you for the explanation, that has connected some dots :)

With that deeper understanding, and my misleading part-of-a-comment removed, I think this is good to go

(the only way I can think of to be more-correct would be to look up the OS locale using platform-specific APIs and use that in place of hard-coded en_US.UTF-8 - but that's a lot more work (plus risk of platform-specific bugs) for a lot smaller benefit)

@mrnugget mrnugget merged commit 5cf0217 into zed-industries:main Oct 11, 2024
10 checks passed
@mrnugget
Copy link
Member

Let's give it a shot!

@shish shish deleted the pr18967 branch October 12, 2024 00:36
noaccOS pushed a commit to noaccOS/zed that referenced this pull request Oct 19, 2024
terminal: Improve default locale handling

* Use `LANG` instead of `LC_ALL` (`LC_ALL` is the highest priority which
will override any other end-user settings; when that isn't set things
fall back to separate `LC_*` variables; and when those aren't set things
fall back to `LANG`). [0]
* Only set `LANG` for our child if necessary (if it already exists in
the parent, then the child will inherit that, no need for us to do
anything)

[0]
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02

Tested cases:

- `unset LANG ; cargo run`: locale inside zed's terminal is set to
`en_US.UTF-8`
- `export LANG=en_GB.UTF-8 ; cargo run`: locale inside zed's terminal is
set to `en_GB.UTF-8`

Release Notes:

- Use the system locale in the terminal instead of forcing `en_US.UTF-8`
@josser
Copy link

josser commented Oct 25, 2024

Looks like it's not working.
In terminal.app I have:
echo $LANG
uk_UA.UTF-8
echo $LC_ALL
uk_UA.UTF-8

But in zed terminal still:
en_US.UTF-8
in both cases.
Or I didn't understand what was fixed?

@shish
Copy link
Contributor Author

shish commented Oct 26, 2024

@josser are you launching zed by clicking the .app? My understanding is that when you do that, zed gets launched with no locale environment variables at all, and "hard-code en_US in all situations whether it's needed or not" was a workaround for that problem. However that then caused problems for me because I'm on linux, where the environment variables are set, but were being ignored.

This PR fixes my problem (ie, it pays attention to the environment variables, when they exist) - however the original problem of "macos launches GUI apps without environment variables, so we need to guess or hardcode something as a fallback" remains

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed The user has signed the Contributor License Agreement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants