Skip to main content

katui_present/
select.rs

1//! Backend selection: capabilities in, graphics backend out.
2
3use katui_proto::probe::Capabilities;
4
5/// The graphics backend a presenter strategy drives.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Backend {
8    /// The kitty graphics protocol: images, placements, animation.
9    Kitty,
10    /// Sixel: paletted bands, one image per changed tile.
11    Sixel,
12    /// Half and quarter block glyphs over SGR truecolor, the floor every
13    /// color terminal understands.
14    Blocks,
15}
16
17/// Pick the best backend the terminal offers. Kitty wins when present,
18/// sixel comes second outside multiplexers, which place sixel images
19/// themselves, and blocks carry everything else. Needs-aware choices
20/// (alpha, z-order, frame budget) are the presenter strategies' concern.
21#[must_use]
22pub fn select(caps: &Capabilities) -> Backend {
23    if caps.kitty {
24        Backend::Kitty
25    } else if caps.sixel && !caps.multiplexed() {
26        Backend::Sixel
27    } else {
28        Backend::Blocks
29    }
30}
31
32impl Backend {
33    /// The backend's canonical lowercase name, the one string form every
34    /// consumer prints.
35    #[must_use]
36    pub const fn name(self) -> &'static str {
37        match self {
38            Self::Kitty => "kitty",
39            Self::Sixel => "sixel",
40            Self::Blocks => "blocks",
41        }
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::{Backend, select};
48    use katui_proto::probe::{Capabilities, ProbeSource};
49
50    fn caps(kitty: bool, sixel: bool) -> Capabilities {
51        Capabilities {
52            kitty,
53            animation: false,
54            sixel,
55            truecolor: true,
56            identity: None,
57            cell: None,
58            text_area: None,
59            relative_placements: false,
60            local_files: false,
61            id_space: katui_proto::kitty::IdSpace::default(),
62            trust: ProbeSource::Probed,
63        }
64    }
65
66    #[test]
67    fn kitty_outranks_everything() {
68        assert_eq!(select(&caps(true, true)), Backend::Kitty);
69        assert_eq!(select(&caps(true, false)), Backend::Kitty);
70    }
71
72    #[test]
73    fn sixel_comes_second() {
74        assert_eq!(select(&caps(false, true)), Backend::Sixel);
75    }
76
77    #[test]
78    fn blocks_carry_the_rest() {
79        assert_eq!(select(&caps(false, false)), Backend::Blocks);
80    }
81}