uncurses/ansi/finalterm.rs
1//! Shell-integration prompt and command markers using OSC 133.
2//!
3//! ## Category
4//!
5//! OSC 133 marks prompt start, command input start, command execution, and
6//! command completion. Terminals can use these markers to segment scrollback.
7//!
8//! ## OSC framing
9//!
10//! Writers use 7-bit OSC with BEL termination: `ESC ] 133 ; <mark> [;data] BEL`.
11//! [`write_finalterm`] is the generic form; the other functions encode the
12//! standard `A`, `B`, `C`, and `D` markers.
13//!
14//! ## Mode interaction
15//!
16//! These markers are not controlled by a DECSET mode. They are passive metadata
17//! embedded in the output stream.
18
19use std::io::{self, Write};
20
21/// Emit a generic OSC 133 marker, `ESC ] 133 [;<param>...] BEL`.
22///
23/// Each string in `params` is appended as one semicolon-prefixed field. Use this for marker forms not covered by the specialized helpers.
24pub fn write_finalterm<W: Write>(w: &mut W, params: &[&str]) -> io::Result<()> {
25 w.write_all(b"\x1b]133")?;
26 for p in params {
27 w.write_all(b";")?;
28 w.write_all(p.as_bytes())?;
29 }
30 w.write_all(b"\x07")
31}
32
33/// Mark the start of a prompt with exact bytes `ESC ] 133 ; A BEL`.
34pub fn write_prompt_start<W: Write>(w: &mut W) -> io::Result<()> {
35 w.write_all(b"\x1b]133;A\x07")
36}
37
38/// Mark the end of the prompt and start of command input with exact bytes `ESC ] 133 ; B BEL`.
39pub fn write_command_start<W: Write>(w: &mut W) -> io::Result<()> {
40 w.write_all(b"\x1b]133;B\x07")
41}
42
43/// Mark the moment command execution begins with exact bytes `ESC ] 133 ; C BEL`.
44pub fn write_command_executed<W: Write>(w: &mut W) -> io::Result<()> {
45 w.write_all(b"\x1b]133;C\x07")
46}
47
48/// Mark command completion with `ESC ] 133 ; D [;exit-code] BEL`.
49///
50/// When `exit_code` is `None`, the exit-code field is omitted; otherwise the decimal code is appended after a semicolon.
51pub fn write_command_finished<W: Write>(w: &mut W, exit_code: Option<i32>) -> io::Result<()> {
52 match exit_code {
53 Some(code) => write!(w, "\x1b]133;D;{code}\x07"),
54 None => w.write_all(b"\x1b]133;D\x07"),
55 }
56}