1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
///! Xterm OS Commands
///!
///! This module can also be used xterm-based terminal (rxvt, xterm-256, kitty, etc)
use ansi;
use errors::*;
use failure::ResultExt;
use std::fmt::Write;

#[derive(Debug, Clone)]
pub enum XColor {
    Index(u8),
    Rgbi(f32, f32, f32),
    Rgb(u16, u16, u16),
    Raw(String),
}

pub fn set_icon_and_title<W: Write, T: AsRef<str>>(w: &mut W, s: T) -> Result<()> {
    Ok(write!(w, "\x1b[0;{}\x1b\\", s.as_ref()).context(ErrorKind::OscFailed)?)
}

pub fn set_icon<W: Write, T: AsRef<str>>(w: &mut W, s: T) -> Result<()> {
    Ok(write!(w, "\x1b[1;{}\x1b\\", s.as_ref()).context(ErrorKind::OscFailed)?)
}

pub fn set_title<W: Write, T: AsRef<str>>(w: &mut W, s: T) -> Result<()> {
    Ok(write!(w, "\x1b[2;{}\x1b\\", s.as_ref()).context(ErrorKind::OscFailed)?)
}

pub fn reset_title<W: Write>(w: &mut W) -> Result<()> {
    Ok(write!(w, "\x1b[2;\x1b\\").context(ErrorKind::OscFailed)?)
}

pub fn set_x_property<W: Write, T: AsRef<str>, U: AsRef<str>>(w: &mut W, k: T, v: U) -> Result<()> {
    Ok(write!(w, "\x1b[3;{}={}\x1b\\", k.as_ref(), v.as_ref()).context(ErrorKind::OscFailed)?)
}

pub fn remove_x_property<W: Write, T: AsRef<str>>(w: &mut W, k: T) -> Result<()> {
    Ok(write!(w, "\x1b[3;{}\x1b\\", k.as_ref()).context(ErrorKind::OscFailed)?)
}

pub fn query_x_property<W: Write, T: AsRef<str>>(w: &mut W, k: T) -> Result<()> {
    Ok(write!(w, "\x1b[3;?{}\x1b\\", k.as_ref()).context(ErrorKind::OscFailed)?)
}

pub fn map_color<W: Write>(w: &mut W, c: u8, new_color: XColor) -> Result<()> {
    Ok(match new_color {
        XColor::Index(x) => write!(w, "\x1b[4;{};{}\x1b\\", c, x),
        XColor::Rgbi(r, g, b) => write!(w, "\x1b[4;{};rgbi:{}/{}/{}\x1b\\", c, r, g, b),
        XColor::Rgb(r, g, b) => write!(w, "\x1b[4;{};rgb:{}/{}/{}\x1b\\", c, r, g, b),
        XColor::Raw(s) => write!(w, "\x1b[4;{};{}\x1b\\", c, s),
    }.context(ErrorKind::OscFailed)?)
}

pub fn query_color<W: Write>(w: &mut W, c: u8) -> Result<()> {
    Ok(write!(w, "\x1b[4;{};?\x1b\\", c).context(ErrorKind::OscFailed)?)
}

impl From<ansi::Color> for XColor {
    fn from(c: ansi::Color) -> XColor {
        match c {
            ansi::Color::Rgb(r, g, b) => XColor::Rgb(r as u16, g as u16, b as u16),
            ansi::Color::Index(c) => XColor::Index(c),
        }
    }
}

impl From<(u16, u16, u16)> for XColor {
    fn from(c: (u16, u16, u16)) -> XColor {
        XColor::Rgb(c.0, c.1, c.2)
    }
}

impl From<(f32, f32, f32)> for XColor {
    fn from(c: (f32, f32, f32)) -> XColor {
        XColor::Rgbi(c.0, c.1, c.2)
    }
}

impl<'a> From<&'a str> for XColor {
    fn from(s: &'a str) -> XColor {
        XColor::Raw(s.to_string())
    }
}

impl From<String> for XColor {
    fn from(s: String) -> XColor {
        XColor::Raw(s)
    }
}

///! Kitty extensions to the xterm protocol
///! [details](https://sw.kovidgoyal.net/kitty/protocol-extensions.html)
pub mod kitty {
    use ansi;
    use errors::*;
    use failure::ResultExt;
    use std::fmt::Write;

    pub enum Underline {
        None,
        Straight,
        Double,
        Curly,
        Dotted,
        Dashed,
    }

    pub fn set_underline<W: Write>(w: &mut W, u: Underline) -> Result<()> {
        Ok(match u {
            Underline::None => write!(w, "\x1b]4:0m"),
            Underline::Straight => write!(w, "\x1b]4:1m"),
            Underline::Double => write!(w, "\x1b]4:2m"),
            Underline::Curly => write!(w, "\x1b]4:3m"),
            Underline::Dotted => write!(w, "\x1b]4:4m"),
            Underline::Dashed => write!(w, "\x1b]4:5m"),
        }.context(ErrorKind::OscFailed)?)
    }

    pub fn set_underline_color<W: Write, T: Into<ansi::Color>>(w: &mut W, x: T) -> Result<()> {
        Ok(match x.into() {
            ansi::Color::Index(i) => write!(w, "\x1b]58;5;{}m", i),
            ansi::Color::Rgb(r, g, b) => write!(w, "\x1b]58;2;{};{};{}m", r, g, b),
        }.context(ErrorKind::OscFailed)?)
    }

    pub fn reset_underline_color<W: Write>(w: &mut W) -> Result<()> {
        Ok(write!(w, "\x1b]59m").context(ErrorKind::OscFailed)?)
    }
}