diff --git a/Cargo.lock b/Cargo.lock index 083804189d..0a5d85d3b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3251,6 +3251,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "num-bigint" version = "0.4.3" @@ -3812,6 +3821,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "procinfo" +version = "0.1.0" +source = "git+https://github.com/zed-industries/wezterm?rev=40a7dbf93542fbe4178c2e4b4bd438126a6432b9#40a7dbf93542fbe4178c2e4b4bd438126a6432b9" +dependencies = [ + "libc", + "log", + "ntapi", + "winapi 0.3.9", +] + [[package]] name = "project" version = "0.1.0" @@ -5358,6 +5378,7 @@ dependencies = [ "libc", "mio-extras", "ordered-float", + "procinfo", "project", "settings", "shellexpand", diff --git a/crates/terminal/Cargo.toml b/crates/terminal/Cargo.toml index 732a03ed1e..5910a2897c 100644 --- a/crates/terminal/Cargo.toml +++ b/crates/terminal/Cargo.toml @@ -8,7 +8,8 @@ path = "src/terminal.rs" doctest = false [dependencies] -alacritty_terminal = { git = "https://github.com/zed-industries/alacritty", rev = "4e1f0c6177975a040b37f942dfb0e723e46a9971"} +alacritty_terminal = { git = "https://github.com/zed-industries/alacritty", rev = "4e1f0c6177975a040b37f942dfb0e723e46a9971" } +procinfo = { git = "https://github.com/zed-industries/wezterm", rev = "40a7dbf93542fbe4178c2e4b4bd438126a6432b9", default-features = false } editor = { path = "../editor" } util = { path = "../util" } gpui = { path = "../gpui" } diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index f542477b4c..42ec061290 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -34,11 +34,14 @@ use mappings::mouse::{ }; use modal::deploy_modal; +use procinfo::LocalProcessInfo; use settings::{AlternateScroll, Settings, Shell, TerminalBlink}; + use std::{ collections::{HashMap, VecDeque}, fmt::Display, ops::{Deref, RangeInclusive, Sub}, + os::unix::prelude::AsRawFd, path::PathBuf, sync::Arc, time::{Duration, Instant}, @@ -347,19 +350,8 @@ impl TerminalBuilder { } }; - let shell_txt = { - match shell { - Some(Shell::System) | None => { - let mut buf = [0; 1024]; - let pw = alacritty_unix::get_pw_entry(&mut buf).unwrap(); - pw.shell.to_string() - } - Some(Shell::Program(program)) => program, - Some(Shell::WithArguments { program, args }) => { - format!("{} {}", program, args.join(" ")) - } - } - }; + let fd = pty.file().as_raw_fd(); + let shell_pid = pty.child().id(); //And connect them together let event_loop = EventLoop::new( @@ -378,8 +370,6 @@ impl TerminalBuilder { pty_tx: Notifier(pty_tx), term, events: VecDeque::with_capacity(10), //Should never get this high. - title: shell_txt.clone(), - default_title: shell_txt, last_content: Default::default(), cur_size: initial_size, last_mouse: None, @@ -387,6 +377,10 @@ impl TerminalBuilder { last_synced: Instant::now(), sync_task: None, selection_head: None, + shell_fd: fd as u32, + shell_pid, + foreground_process_info: None, + breadcrumb_text: String::new(), }; Ok(TerminalBuilder { @@ -495,8 +489,6 @@ pub struct Terminal { pty_tx: Notifier, term: Arc>>, events: VecDeque, - default_title: String, - title: String, last_mouse: Option<(Point, AlacDirection)>, pub matches: Vec>, cur_size: TerminalSize, @@ -504,18 +496,20 @@ pub struct Terminal { last_synced: Instant, sync_task: Option>, selection_head: Option, + breadcrumb_text: String, + shell_pid: u32, + shell_fd: u32, + foreground_process_info: Option, } impl Terminal { fn process_event(&mut self, event: &AlacTermEvent, cx: &mut ModelContext) { match event { AlacTermEvent::Title(title) => { - self.title = title.to_string(); - cx.emit(Event::TitleChanged); + self.breadcrumb_text = title.to_string(); } AlacTermEvent::ResetTitle => { - self.title = self.default_title.clone(); - cx.emit(Event::TitleChanged); + self.breadcrumb_text = String::new(); } AlacTermEvent::ClipboardStore(_, data) => { cx.write_to_clipboard(ClipboardItem::new(data.to_string())) @@ -705,11 +699,24 @@ impl Terminal { return; }; - //Note that this ordering matters for event processing + //Note that the ordering of events matters for event processing while let Some(e) = self.events.pop_front() { self.process_terminal_event(&e, &mut terminal, cx) } + if let Some(process_info) = self.compute_process_info() { + let should_emit_title_changed = self + .foreground_process_info + .as_ref() + .map(|old_info| { + process_info.cwd != old_info.cwd || process_info.name != old_info.name + }) + .unwrap_or(true); + if should_emit_title_changed { + cx.emit(Event::TitleChanged) + } + self.foreground_process_info = Some(process_info.clone()); + } self.last_content = Self::make_content(&terminal); self.last_synced = Instant::now(); } @@ -953,6 +960,14 @@ impl Terminal { make_search_matches(&term, &searcher).collect() }) } + + fn compute_process_info(&self) -> Option { + let mut pid = unsafe { libc::tcgetpgrp(self.shell_fd as i32) }; + if pid < 0 { + pid = self.shell_pid as i32; + } + LocalProcessInfo::with_root_pid(pid as u32) + } } impl Drop for Terminal { diff --git a/crates/terminal/src/terminal_container_view.rs b/crates/terminal/src/terminal_container_view.rs index bb93d41ebb..6e3d85f5f7 100644 --- a/crates/terminal/src/terminal_container_view.rs +++ b/crates/terminal/src/terminal_container_view.rs @@ -238,9 +238,23 @@ impl Item for TerminalContainer { cx: &gpui::AppContext, ) -> ElementBox { let title = match &self.content { - TerminalContainerContent::Connected(connected) => { - connected.read(cx).handle().read(cx).title.to_string() - } + TerminalContainerContent::Connected(connected) => connected + .read(cx) + .handle() + .read(cx) + .foreground_process_info + .as_ref() + .map(|fpi| { + format!( + "{} - {}", + fpi.cwd + .file_name() + .map(|name| name.to_string_lossy().to_string()) + .unwrap_or_default(), + fpi.name, + ) + }) + .unwrap_or_else(|| "Terminal".to_string()), TerminalContainerContent::Error(_) => "Terminal".to_string(), };