uncurses/ansi/palette.rs
1//! Linux-console palette sequences.
2//!
3//! ## Category
4//!
5//! This module encodes the compact OSC `P`/`R` palette controls used by the Linux
6//! text console: setting one of 16 palette entries and resetting all entries.
7//!
8//! ## OSC framing
9//!
10//! Palette writes use `ESC ] P n rrggbb BEL`, where `n` is a single hexadecimal
11//! palette index. Reset is the fixed byte string `ESC ] R BEL`.
12//!
13//! ## Mode interaction
14//!
15//! These sequences do not depend on ANSI or DEC modes and are specific to
16//! terminals that implement this palette protocol.
17
18use std::io::{self, Write};
19
20/// Set a 16-color palette entry with `ESC ] P <index-hex> <rrggbb> BEL`.
21///
22/// `index` must be `0..=15`; values outside that range emit nothing. RGB channels are formatted as two lowercase hexadecimal digits each.
23pub fn write_set_palette<W: Write>(w: &mut W, index: u8, r: u8, g: u8, b: u8) -> io::Result<()> {
24 if index > 15 {
25 return Ok(());
26 }
27 write!(w, "\x1b]P{index:x}{r:02x}{g:02x}{b:02x}\x07")
28}
29
30/// Reset the Linux-console palette: exact bytes `ESC ] R BEL` (`b"\x1b]R\x07"`).
31pub const RESET_PALETTE: &[u8] = b"\x1b]R\x07";
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn test_set_palette() {
39 let mut buf = Vec::new();
40 write_set_palette(&mut buf, 1, 0xff, 0x00, 0x80).unwrap();
41 assert_eq!(buf, b"\x1b]P1ff0080\x07");
42 }
43
44 #[test]
45 fn test_out_of_range() {
46 let mut buf = Vec::new();
47 write_set_palette(&mut buf, 16, 0, 0, 0).unwrap();
48 assert!(buf.is_empty());
49 }
50}