project: Properly set up the terminal env in remote shells (#46149)

Lukas Wirth created

Closes https://github.com/zed-industries/zed/issues/35698

Release Notes:

- Fixed default zed terminal environment vars not being set in remote
terminal shells

Change summary

.rules                          |  2 +-
crates/project/Cargo.toml       |  2 +-
crates/project/src/terminals.rs |  6 +++---
crates/terminal/src/terminal.rs | 19 ++++++++++++++-----
4 files changed, 19 insertions(+), 10 deletions(-)

Detailed changes

.rules 🔗

@@ -136,4 +136,4 @@ Other entities can then register a callback to handle these events by doing `cx.
 ## Build guidelines
 
 - Use `./script/clippy` instead of `cargo clippy`
-- Always use `-q` when invoking `cargo`
+- Always invoke `cargo` commands with the `-q` flag

crates/project/Cargo.toml 🔗

@@ -65,6 +65,7 @@ postage.workspace = true
 prettier.workspace = true
 rand.workspace = true
 regex.workspace = true
+release_channel.workspace = true
 remote.workspace = true
 rpc.workspace = true
 schemars.workspace = true
@@ -110,7 +111,6 @@ language = { workspace = true, features = ["test-support"] }
 lsp = { workspace = true, features = ["test-support"] }
 prettier = { workspace = true, features = ["test-support"] }
 pretty_assertions.workspace = true
-release_channel.workspace = true
 rpc = { workspace = true, features = ["test-support"] }
 settings = { workspace = true, features = ["test-support"] }
 snippet_provider = { workspace = true, features = ["test-support"] }

crates/project/src/terminals.rs 🔗

@@ -14,7 +14,8 @@ use std::{
 };
 use task::{Shell, ShellBuilder, ShellKind, SpawnInTerminal};
 use terminal::{
-    TaskState, TaskStatus, Terminal, TerminalBuilder, terminal_settings::TerminalSettings,
+    TaskState, TaskStatus, Terminal, TerminalBuilder, insert_zed_terminal_env,
+    terminal_settings::TerminalSettings,
 };
 use util::{command::new_std_command, get_default_system_shell, maybe, rel_path::RelPath};
 
@@ -568,8 +569,7 @@ fn create_remote_shell(
     remote_client: Entity<RemoteClient>,
     cx: &mut App,
 ) -> Result<(Shell, HashMap<String, String>)> {
-    // Set default terminfo that does not break the highlighting via ssh.
-    env.insert("TERM".to_string(), "xterm-256color".to_string());
+    insert_zed_terminal_env(&mut env, &release_channel::AppVersion::global(cx));
 
     let (program, args) = match spawn_command {
         Some((program, args)) => (Some(program.clone()), args),

crates/terminal/src/terminal.rs 🔗

@@ -113,6 +113,19 @@ const DEBUG_TERMINAL_HEIGHT: Pixels = px(30.);
 const DEBUG_CELL_WIDTH: Pixels = px(5.);
 const DEBUG_LINE_HEIGHT: Pixels = px(5.);
 
+/// Inserts Zed-specific environment variables for terminal sessions.
+/// Used by both local terminals and remote terminals (via SSH).
+pub fn insert_zed_terminal_env(
+    env: &mut HashMap<String, String>,
+    version: &impl std::fmt::Display,
+) {
+    env.insert("ZED_TERM".to_string(), "true".to_string());
+    env.insert("TERM_PROGRAM".to_string(), "zed".to_string());
+    env.insert("TERM".to_string(), "xterm-256color".to_string());
+    env.insert("COLORTERM".to_string(), "truecolor".to_string());
+    env.insert("TERM_PROGRAM_VERSION".to_string(), version.to_string());
+}
+
 ///Upward flowing events, for changing the title and such
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum Event {
@@ -435,11 +448,7 @@ impl TerminalBuilder {
                     .or_insert_with(|| "en_US.UTF-8".to_string());
             }
 
-            env.insert("ZED_TERM".to_string(), "true".to_string());
-            env.insert("TERM_PROGRAM".to_string(), "zed".to_string());
-            env.insert("TERM".to_string(), "xterm-256color".to_string());
-            env.insert("COLORTERM".to_string(), "truecolor".to_string());
-            env.insert("TERM_PROGRAM_VERSION".to_string(), version.to_string());
+            insert_zed_terminal_env(&mut env, &version);
 
             #[derive(Default)]
             struct ShellParams {