aboutsummaryrefslogtreecommitdiff
path: root/src/pane/osc.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:28:05 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:29:28 +0300
commit4a3302d19a2baa3a33e910e0088c24e780905b90 (patch)
treedcaf76fae1c82102d933c9225b17ca7ac5d3a847 /src/pane/osc.rs
parent550e9f8cc085f428429f5cf2da0bb2dba897e8b8 (diff)
chore: update vendored libghostty-vt
refs #276
Diffstat (limited to 'src/pane/osc.rs')
-rw-r--r--src/pane/osc.rs90
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();