Skip to main content

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}