zed icon indicating copy to clipboard operation
zed copied to clipboard

Better default locale in the terminal

Open shish opened this issue 1 year ago • 1 comments

Better default locale in the terminal

  • 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]
  • Try taking LANG from the user's environment before falling back to en_US.UTF-8

I'm leaving the comment in place because while I think this PR makes things much better for non-en_US users[1], I have a hunch that it could still be made even more better[2] :)

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

[1] ie, I myself am running a system where en_GB is the system-level default, and I no longer get a ton of "unknown locale: en_US" errors when I'm running things inside zed's terminal

[2] Perhaps the "correct" behaviour is to inherit LANG and all of the LC_* variables? I don't know, I'm not a locale expert, I'm just British

shish avatar Oct 09 '24 23:10 shish

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'.

cla-bot[bot] avatar Oct 09 '24 23:10 cla-bot[bot]

@cla-bot check

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

shish avatar Oct 10 '24 03:10 shish

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

cla-bot[bot] avatar Oct 10 '24 03:10 cla-bot[bot]

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). https://github.com/zed-industries/zed/pull/13691#discussion_r1669973591

someone13574 avatar Oct 10 '24 03:10 someone13574

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 :)

shish avatar Oct 10 '24 06:10 shish

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: https://github.com/zed-industries/zed/pull/13691#discussion_r1669973591

mrnugget avatar Oct 10 '24 11:10 mrnugget

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.

someone13574 avatar Oct 10 '24 12:10 someone13574

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 avatar Oct 10 '24 13:10 shish

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] https://github.com/zed-industries/zed/blob/9bc4e3b4ae4c248ef0342529caa23bef4593e19b/crates/project/src/terminals.rs#L119-L127

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

shish avatar Oct 10 '24 13:10 shish

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] https://github.com/zed-industries/zed/blob/596d8b2fe394421f9078fa91834b69fdb47ce251/crates/project/src/project.rs#L736

shish avatar Oct 10 '24 14:10 shish

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?

mrnugget avatar Oct 11 '24 08:10 mrnugget

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)

shish avatar Oct 11 '24 13:10 shish

Let's give it a shot!

mrnugget avatar Oct 11 '24 16:10 mrnugget

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?

josser avatar Oct 25 '24 15:10 josser

@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

shish avatar Oct 26 '24 23:10 shish