From 3925f2c7f5927c07a5db305eaed9087631d85b0d Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Wed, 10 Nov 2021 23:01:38 +0100 Subject: implement subcommand get (GIO_CMAP) Get the currently active color palette using ioctl(GIO_CMAP) and attempt to match it against the builtin schemes. --- src/vtcol.rs | 125 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 36 deletions(-) diff --git a/src/vtcol.rs b/src/vtcol.rs index a007185..17f0489 100644 --- a/src/vtcol.rs +++ b/src/vtcol.rs @@ -109,6 +109,7 @@ enum Scheme Default, SolarizedDark, SolarizedLight, + Palette(Palette), Custom(Option), } @@ -117,11 +118,12 @@ impl<'a> fmt::Display for Scheme fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Scheme::Default => write!(f, "default"), - Scheme::SolarizedDark => write!(f, "solarized_dark"), - Scheme::SolarizedLight => write!(f, "solarized_light"), - Scheme::Custom(None) => write!(f, ""), - Scheme::Custom(Some(fname)) => write!(f, "{}", fname.display()), + Self::Default => write!(f, "default"), + Self::SolarizedDark => write!(f, "solarized_dark"), + Self::SolarizedLight => write!(f, "solarized_light"), + Self::Custom(None) => write!(f, ""), + Self::Custom(Some(fname)) => write!(f, "{}", fname.display()), + Self::Palette(pal) => write!(f, "palette: {}", pal), } } } /* [impl fmt::String for Scheme] */ @@ -151,6 +153,25 @@ impl From<&str> for Scheme } } +/** Try to match the palette against one of the predefined schemes. */ +impl From for Scheme +{ + fn from(pal: Palette) -> Scheme + { + if pal == Palette::from(&DEFAULT_COLORS) { + return Self::Default; + } + if pal == Palette::from(&SOLARIZED_COLORS_DARK) { + return Self::SolarizedDark; + } + if pal == Palette::from(&SOLARIZED_COLORS_LIGHT) { + return Self::SolarizedLight; + } + + Self::Palette(pal) + } +} + /* struct Job -- Runtime parameters. */ #[derive(Debug)] @@ -160,8 +181,10 @@ enum Job List, /** Dump a scheme. */ Dump(Scheme), - /** The color scheme to switch to. */ + /** Switch to color scheme. */ Set(Scheme), + /** Get currently active scheme. */ + Get, } impl<'a> Job @@ -205,6 +228,9 @@ impl<'a> Job .takes_value(true), ), ) + .subcommand( + SubCommand::with_name("get").about("get current color scheme"), + ) .arg( Arg::with_name("verbose") .short("v") @@ -249,6 +275,7 @@ impl<'a> Job }; Ok(Self::Set(scheme)) }, + ("get", _) => Ok(Self::Get), (junk, _) => Err(anyhow!( "invalid subcommand [{}]; try “{} --help”", @@ -277,6 +304,7 @@ impl<'a> Job Scheme::Custom(None) => Self::dump_palette(Palette::from_stdin()), Scheme::Custom(Some(fname)) => Self::dump_palette(Palette::from_file(&fname)), + Scheme::Palette(pal) => Self::dump_palette(pal), } } @@ -294,6 +322,7 @@ impl<'a> Job Self::Dump(scm) => Self::dump(scm), Self::List => Self::schemes(), Self::Set(scm) => Self::set_scheme(scm)?, + Self::Get => Self::get_scheme()?, } Ok(()) @@ -301,17 +330,11 @@ impl<'a> Job fn set_scheme(scheme: Scheme) -> Result<()> { - let pal: Palette = match scheme { - Scheme::Default => Palette::from(&DEFAULT_COLORS), - Scheme::SolarizedDark => Palette::from(&SOLARIZED_COLORS_DARK), - Scheme::SolarizedLight => Palette::from(&SOLARIZED_COLORS_LIGHT), - Scheme::Custom(None) => Palette::from_stdin(), - Scheme::Custom(Some(ref fname)) => Palette::from_file(fname), - }; + let pal = Palette::from(&scheme); vrb!("Using palette:"); vrb!("{}", pal); let fd = get_console_fd()?; - vrb!("fd: {}", fd); + vrb!("console fd: {}", fd); ioctl_pio_cmap(fd, &pal)?; @@ -320,6 +343,20 @@ impl<'a> Job /* It’s fine to leak the fd, the kernel will clean up anyways. */ Ok(()) } + + fn get_scheme() -> Result<()> + { + let fd = get_console_fd()?; + vrb!("console fd: {}", fd); + + let pal = ioctl_gio_cmap(fd)?; + let scm = Scheme::from(pal); + + vrb!("active scheme:"); + println!("{}", scm); + + Ok(()) + } } /* [impl Job] */ /* Rust appears to come with two wrappers for ``ioctl(2)``, but neither can be utilized for our @@ -393,6 +430,7 @@ fn rgb_of_hex_triplet(def: &str) -> (u8, u8, u8) (r, g, b) } +#[derive(Eq, PartialEq, Clone)] pub struct Palette([u8; PALETTE_BYTES]); impl Palette @@ -400,28 +438,6 @@ impl Palette /** Construct an all-zero ``Palette``. */ pub fn new() -> Self { Self([0u8; PALETTE_BYTES]) } - /* [Palette::new] */ - - /** Obtain a ``Palette`` from a ``RawPalette``. */ - pub fn from(colors: &RawPalette) -> Self - { - let mut idx: usize = 0; - let mut pal: [u8; PALETTE_BYTES] = [0; PALETTE_BYTES]; - - for def in colors.iter() { - let (r, g, b) = rgb_of_hex_triplet(*def); - pal[idx] = r; - pal[idx + 1] = g; - pal[idx + 2] = b; - //println!(">> {} -> {:X} {:X} {:X}", def, r, g, b); - idx += 3; - } - - Self(pal) - } - - /* [Palette::from] */ - pub fn dummy() -> Self { Self::from(&DUMMY_COLORS) } pub fn from_buffered_reader(reader: &mut dyn std::io::BufRead) -> Self @@ -555,6 +571,43 @@ impl fmt::Debug for Palette } } /* [impl fmt::Debug for Palette] */ +/** Obtain a ``Palette`` from a ``Scheme``. */ +impl From<&Scheme> for Palette +{ + fn from(scm: &Scheme) -> Self + { + match scm { + Scheme::Default => Self::from(&DEFAULT_COLORS), + Scheme::SolarizedDark => Self::from(&SOLARIZED_COLORS_DARK), + Scheme::SolarizedLight => Self::from(&SOLARIZED_COLORS_LIGHT), + Scheme::Custom(None) => Self::from_stdin(), + Scheme::Custom(Some(ref fname)) => Self::from_file(fname), + Scheme::Palette(pal) => pal.clone(), + } + } +} + +/** Obtain a ``Palette`` from a ``RawPalette``. */ +impl From<&RawPalette<'_>> for Palette +{ + fn from(colors: &RawPalette<'_>) -> Self + { + let mut idx: usize = 0; + let mut pal: [u8; PALETTE_BYTES] = [0; PALETTE_BYTES]; + + for def in colors.iter() { + let (r, g, b) = rgb_of_hex_triplet(*def); + pal[idx] = r; + pal[idx + 1] = g; + pal[idx + 2] = b; + //println!(">> {} -> {:X} {:X} {:X}", def, r, g, b); + idx += 3; + } + + Self(pal) + } +} + fn fd_of_path(path: &std::path::Path) -> Option { let p = std::ffi::CString::new(path.to_str().unwrap()).unwrap(); -- cgit v1.2.3