Resolves the 13 rows still partial in docs/rewrite/notes/review-rv4- codex.md (details in final-Z5.md): - Escaped config strings are decoded to raw bytes at every OS boundary: Flatpak cwd/argv to D-Bus, screen-file paths, the default config template, GHOSTTY_RESOURCES_DIR/TERMINFO/shell integration/ bindtextdomain consumers, custom shader loading, list-themes hyperlinks. - osbytes escapes literal U+FDD0 on non-Unix too (bijective everywhere); the GTK paste dialog only decodes text that was actually encoded. - shadertoy: whole-array uses of iChannelTime rebuild a plain float[4] from the std140-padded members (naga-validated, MSL offsets checked). - libghostty-vt: the OSC parser holds caller-allocated storage inline and command payloads borrow from it, so ghostty_osc_end performs no global allocations (verified from Rust and C). - crash: aarch64 Linux minidump context fixed; macOS fatal signals record siginfo, registers and a fault-safe stack walk. - tripwire: selectionString map allocation-failure cleanup test ported. - libghostty-vt emits the versioned soname libghostty-vt.so.0 at build time (no patchelf needed at install). Test Plan: - cargo test --workspace (3342 passed) - just check-macos; just check-macos x86_64-apple-darwin; just check-windows; just check-wasm - cargo check --target aarch64-unknown-linux-gnu -p ghostty-crash
60 lines
1.6 KiB
Rust
60 lines
1.6 KiB
Rust
//! OSC 777 (ZIG/src/terminal/osc/parsers/rxvt_extension.zig).
|
|
use crate::osc::{ByteStorage, Command, Parser, State};
|
|
|
|
/// Parse OSC 777
|
|
pub fn parse<S: ByteStorage>(
|
|
parser: &mut Parser<S>,
|
|
_terminator_ch: Option<u8>,
|
|
) -> Option<Command<'_>> {
|
|
parser.data()?;
|
|
let (k, t) = {
|
|
let data = parser.payload();
|
|
let Some(k) = data.iter().position(|&b| b == b';') else {
|
|
parser.state = State::Invalid;
|
|
return None;
|
|
};
|
|
let ext = &data[..k];
|
|
if ext != b"notify" {
|
|
log::warn!("unknown rxvt extension: {}", String::from_utf8_lossy(ext));
|
|
parser.state = State::Invalid;
|
|
return None;
|
|
}
|
|
let Some(t) = data[k + 1..]
|
|
.iter()
|
|
.position(|&b| b == b';')
|
|
.map(|i| i + k + 1)
|
|
else {
|
|
log::warn!("rxvt notify extension is missing the title");
|
|
parser.state = State::Invalid;
|
|
return None;
|
|
};
|
|
(k, t)
|
|
};
|
|
let data = parser.payload();
|
|
Some(Command::ShowDesktopNotification {
|
|
title: data[k + 1..t].into(),
|
|
body: data[t + 1..].into(),
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
#![allow(clippy::unwrap_used)]
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn osc_777_show_desktop_notification_with_title() {
|
|
let mut p = Parser::init(false);
|
|
for c in b"777;notify;Title;Body" {
|
|
p.next(*c);
|
|
}
|
|
assert_eq!(
|
|
p.end(Some(0x1b)).unwrap(),
|
|
Command::ShowDesktopNotification {
|
|
title: b"Title".to_vec().into(),
|
|
body: b"Body".to_vec().into()
|
|
}
|
|
);
|
|
}
|
|
}
|