zed: Clear the FORCE_CLI_MODE environment variable after reading (#46475)

Josh Robson Chase created

This prevents child processes (e.g. shells) from inheriting it. This
generally isn't an issue, since zed is the only thing that cares about
it, but if you're trying to run zed *from* zed, you would first need to
unset it manually.

Release Notes:

- N/A

Change summary

crates/cli/src/cli.rs  |  3 +++
crates/zed/src/main.rs | 10 ++++++++--
2 files changed, 11 insertions(+), 2 deletions(-)

Detailed changes

crates/cli/src/cli.rs 🔗

@@ -34,4 +34,7 @@ pub enum CliResponse {
 
 /// When Zed started not as an *.app but as a binary (e.g. local development),
 /// there's a possibility to tell it to behave "regularly".
+///
+/// Note that in the main zed binary, this variable is unset after it's read for the first time,
+/// therefore it should always be accessed through the `FORCE_CLI_MODE` static.
 pub const FORCE_CLI_MODE_ENV_VAR_NAME: &str = "ZED_FORCE_CLI_MODE";

crates/zed/src/main.rs 🔗

@@ -48,7 +48,7 @@ use std::{
     path::{Path, PathBuf},
     process,
     rc::Rc,
-    sync::{Arc, OnceLock},
+    sync::{Arc, LazyLock, OnceLock},
     time::Instant,
 };
 use theme::{ActiveTheme, GlobalTheme, ThemeRegistry};
@@ -1577,8 +1577,14 @@ fn init_paths() -> HashMap<io::ErrorKind, Vec<&'static Path>> {
     })
 }
 
+pub(crate) static FORCE_CLI_MODE: LazyLock<bool> = LazyLock::new(|| {
+    let env_var = std::env::var(FORCE_CLI_MODE_ENV_VAR_NAME).ok().is_some();
+    unsafe { std::env::remove_var(FORCE_CLI_MODE_ENV_VAR_NAME) };
+    env_var
+});
+
 fn stdout_is_a_pty() -> bool {
-    std::env::var(FORCE_CLI_MODE_ENV_VAR_NAME).ok().is_none() && io::stdout().is_terminal()
+    !*FORCE_CLI_MODE && io::stdout().is_terminal()
 }
 
 #[derive(Parser, Debug)]