diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-17 03:26:33 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-17 03:26:33 +0300 |
| commit | 8d2af4e046c2a95dfc54aafd6f88da12389d76e8 (patch) | |
| tree | 5643a1ec2f04b150d465817f2896ada4f2fbc46b /src/pane/osc.rs | |
| parent | 6f9ac7c108e22510e1b27e3242477fac660fa4cb (diff) | |
perf: adopt libghostty integration improvements
refs #276
Diffstat (limited to 'src/pane/osc.rs')
| -rw-r--r-- | src/pane/osc.rs | 123 |
1 files changed, 17 insertions, 106 deletions
diff --git a/src/pane/osc.rs b/src/pane/osc.rs index f7cf9eb9..22e76ff1 100644 --- a/src/pane/osc.rs +++ b/src/pane/osc.rs @@ -396,84 +396,13 @@ impl Osc52Forwarder { } } -/// Reconstructs cwd-reporting OSC sequences from child output. Shell -/// integrations commonly use OSC 7 (`file://...`), while Windows Terminal -/// documents OSC 9;9 for the same practical purpose. -#[derive(Debug, Default)] -pub(super) struct CwdOscTracker { - state: Osc52ForwarderState, - body: Vec<u8>, - pending: Vec<PathBuf>, -} - -impl CwdOscTracker { - pub(super) fn observe(&mut self, bytes: &[u8]) { - for &byte in bytes { - match self.state { - Osc52ForwarderState::Ground => { - if byte == 0x1b { - self.state = Osc52ForwarderState::Escape; - } - } - Osc52ForwarderState::Escape => { - if byte == b']' { - self.body.clear(); - self.state = Osc52ForwarderState::OscBody; - } else if byte == 0x1b { - self.state = Osc52ForwarderState::Escape; - } else { - self.state = Osc52ForwarderState::Ground; - } - } - Osc52ForwarderState::OscBody => match byte { - 0x07 => { - self.finalize(); - self.state = Osc52ForwarderState::Ground; - } - 0x1b => self.state = Osc52ForwarderState::OscEscape, - _ => self.body.push(byte), - }, - Osc52ForwarderState::OscEscape => { - if byte == b'\\' { - self.finalize(); - self.state = Osc52ForwarderState::Ground; - } else { - self.body.push(0x1b); - self.body.push(byte); - self.state = Osc52ForwarderState::OscBody; - } - } - } - - if self.body.len() > 4096 { - self.body.clear(); - self.state = Osc52ForwarderState::Ground; - } - } - } - - fn finalize(&mut self) { - if let Some(cwd) = parse_cwd_osc(&self.body) { - self.pending.push(cwd); - } - self.body.clear(); - } - - pub(super) fn drain_latest(&mut self) -> Option<PathBuf> { - self.pending.drain(..).next_back() +pub(super) fn parse_reported_cwd(value: &[u8]) -> Option<PathBuf> { + let value = std::str::from_utf8(value).ok()?.trim(); + if value.starts_with("file://") { + return parse_file_uri_cwd(value); } -} - -fn parse_cwd_osc(body: &[u8]) -> Option<PathBuf> { - let body = std::str::from_utf8(body).ok()?; - if let Some(uri) = body.strip_prefix("7;") { - return parse_file_uri_cwd(uri); - } - if let Some(path) = body.strip_prefix("9;9;") { - let path = path.trim().trim_matches('"'); - return (!path.is_empty()).then(|| PathBuf::from(path)); - } - None + let path = value.trim_matches('"'); + (!path.is_empty()).then(|| PathBuf::from(path)) } /// Maximum retained string length for agent OSC title and progress payloads. @@ -1077,46 +1006,28 @@ mod tests { } #[test] - fn cwd_osc_tracker_detects_split_osc7_sequence() { - let mut tracker = CwdOscTracker::default(); - - tracker.observe(b"\x1b]7;file:///tmp/herdr%20repo"); - assert_eq!(tracker.drain_latest(), None); - tracker.observe(b"\x07"); - + fn reported_cwd_parses_file_uri_and_bare_paths() { assert_eq!( - tracker.drain_latest(), + parse_reported_cwd(b"file:///tmp/herdr%20repo"), Some(std::path::PathBuf::from("/tmp/herdr repo")) ); - } - - #[test] - fn cwd_osc_tracker_detects_windows_terminal_cwd_sequence() { - let mut tracker = CwdOscTracker::default(); - - tracker.observe(b"\x1b]9;9;C:\\Users\\herdr\\src\\herdr\x1b\\"); - assert_eq!( - tracker.drain_latest(), + parse_reported_cwd(b"C:\\Users\\herdr\\src\\herdr"), Some(std::path::PathBuf::from("C:\\Users\\herdr\\src\\herdr")) ); - } - - // The quoted form is what Windows Terminal's documented shell integration - // snippet emits. Herdr's own injected prompt integration deliberately - // emits the path unquoted; see WINDOWS_POWERSHELL_SHELL_INTEGRATION_COMMAND. - #[test] - fn cwd_osc_tracker_detects_quoted_powershell_prompt_cwd_sequence() { - let mut tracker = CwdOscTracker::default(); - - tracker.observe(b"PS C:\\my proj> \x1b]9;9;\"C:\\my proj\"\x1b\\"); - assert_eq!( - tracker.drain_latest(), + parse_reported_cwd(b"\"C:\\my proj\""), Some(std::path::PathBuf::from("C:\\my proj")) ); } + #[test] + fn reported_cwd_rejects_invalid_or_empty_values() { + assert_eq!(parse_reported_cwd(b""), None); + assert_eq!(parse_reported_cwd(b"\xff"), None); + assert_eq!(parse_reported_cwd(b"file://remote/tmp"), None); + } + // ----------------------------------------------------------------------- // AgentOscStateTracker tests // ----------------------------------------------------------------------- |
