diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-16 23:28:05 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-16 23:29:28 +0300 |
| commit | 4a3302d19a2baa3a33e910e0088c24e780905b90 (patch) | |
| tree | dcaf76fae1c82102d933c9225b17ca7ac5d3a847 /src/pane/osc.rs | |
| parent | 550e9f8cc085f428429f5cf2da0bb2dba897e8b8 (diff) | |
chore: update vendored libghostty-vt
refs #276
Diffstat (limited to 'src/pane/osc.rs')
| -rw-r--r-- | src/pane/osc.rs | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/src/pane/osc.rs b/src/pane/osc.rs index 838515e0..f7cf9eb9 100644 --- a/src/pane/osc.rs +++ b/src/pane/osc.rs @@ -144,10 +144,9 @@ impl DefaultColorOscTracker { } fn is_default_color_set_osc(body: &[u8]) -> bool { - matches!( - parse_default_color_event(body), - Some(DefaultColorEvent::Set(_)) - ) + parse_default_color_events(body) + .iter() + .any(|event| matches!(event, DefaultColorEvent::Set(_))) } #[derive(Debug, Default)] @@ -233,27 +232,43 @@ impl DefaultColorEventTracker { } fn finalize(&mut self, end_offset: usize) { - if let Some(event) = parse_default_color_event(&self.body) { - self.pending - .push(DefaultColorTrackedEvent { end_offset, event }); - } + self.pending.extend( + parse_default_color_events(&self.body) + .into_iter() + .map(|event| DefaultColorTrackedEvent { end_offset, event }), + ); self.body.clear(); } + pub(super) fn in_progress_event(&self) -> Option<DefaultColorEvent> { + if !matches!( + self.state, + DefaultColorOscTrackerState::OscBody | DefaultColorOscTrackerState::OscEscape + ) { + return None; + } + let mut events = parse_default_color_events(&self.body); + (events.len() == 1).then(|| events.remove(0)) + } + pub(super) fn drain_pending(&mut self) -> Vec<DefaultColorTrackedEvent> { std::mem::take(&mut self.pending) } } -fn parse_default_color_event(body: &[u8]) -> Option<DefaultColorEvent> { - match body { +fn parse_default_color_events(body: &[u8]) -> Vec<DefaultColorEvent> { + let single = match body { b"10;?" => Some(DefaultColorEvent::Query(DefaultColorQuery::Foreground)), b"11;?" => Some(DefaultColorEvent::Query(DefaultColorQuery::Background)), b"12;?" => Some(DefaultColorEvent::Query(DefaultColorQuery::Cursor)), b"110" | b"110;" => Some(DefaultColorEvent::Reset(DefaultColorQuery::Foreground)), b"111" | b"111;" => Some(DefaultColorEvent::Reset(DefaultColorQuery::Background)), - _ => parse_palette_color_query(body).or_else(|| parse_default_color_set_event(body)), + _ => parse_palette_color_query(body), + }; + if let Some(event) = single { + return vec![event]; } + parse_default_color_set_events(body) } fn parse_palette_color_query(body: &[u8]) -> Option<DefaultColorEvent> { @@ -270,15 +285,33 @@ fn parse_palette_color_query(body: &[u8]) -> Option<DefaultColorEvent> { .map(DefaultColorEvent::PaletteQuery) } -fn parse_default_color_set_event(body: &[u8]) -> Option<DefaultColorEvent> { - let separator = body.iter().position(|byte| *byte == b';')?; - let query = match &body[..separator] { - b"10" => DefaultColorQuery::Foreground, - b"11" => DefaultColorQuery::Background, - _ => return None, +fn parse_default_color_set_events(body: &[u8]) -> Vec<DefaultColorEvent> { + let Some(separator) = body.iter().position(|byte| *byte == b';') else { + return Vec::new(); + }; + let start = match &body[..separator] { + b"10" => 10, + b"11" => 11, + b"12" => 12, + _ => return Vec::new(), }; - let value = &body[separator + 1..]; - (!value.is_empty() && value != b"?").then_some(DefaultColorEvent::Set(query)) + body[separator + 1..] + .split(|byte| *byte == b';') + .filter(|value| !value.is_empty()) + .enumerate() + .filter_map(|(offset, value)| { + if value == b"?" { + return None; + } + let query = match start + offset { + 10 => DefaultColorQuery::Foreground, + 11 => DefaultColorQuery::Background, + 12 => DefaultColorQuery::Cursor, + _ => return None, + }; + Some(DefaultColorEvent::Set(query)) + }) + .collect() } /// 256 KiB of base64 ≈ 192 KiB of text — enough for real source-file copies @@ -1359,6 +1392,25 @@ mod tests { } #[test] + fn default_color_event_tracker_tracks_each_multi_value_set() { + let mut tracker = DefaultColorEventTracker::default(); + + tracker.observe( + b"\x1b]10;rgb:11/22/33;rgb:44/55/66\x1b\\\x1b]10;?;rgb:77/88/99\x1b\\\x1b]10;;rgb:aa/bb/cc\x1b\\", + ); + + assert_eq!( + tracked_default_color_events(tracker.drain_pending()), + vec![ + DefaultColorEvent::Set(DefaultColorQuery::Foreground), + DefaultColorEvent::Set(DefaultColorQuery::Background), + DefaultColorEvent::Set(DefaultColorQuery::Background), + DefaultColorEvent::Set(DefaultColorQuery::Foreground), + ] + ); + } + + #[test] fn default_color_event_tracker_handles_split_default_color_queries() { let mut tracker = DefaultColorEventTracker::default(); |
