From f906287746e7e1a837c541c5f4f6668409000187 Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Wed, 10 Nov 2021 00:50:30 +0100 Subject: rework error handling anyhow!() ftw. --- src/vtcol.rs | 155 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 102 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/vtcol.rs b/src/vtcol.rs index e0ff6cb..6a51b49 100644 --- a/src/vtcol.rs +++ b/src/vtcol.rs @@ -1,4 +1,6 @@ +use anyhow::{anyhow, Result}; use std::{fmt, + io::Error, path::{Path, PathBuf}, sync::atomic::{AtomicBool, Ordering}}; @@ -119,18 +121,23 @@ impl<'a> fmt::Display for Scheme /* struct Job -- Runtime parameters. */ #[derive(Debug)] -struct Job +enum Job { - scheme: Scheme, /* The color scheme to switch to. */ + /** List available schemes. */ + List, + /** Dump a scheme. */ + Dump(Scheme), + /** The color scheme to switch to. */ + Set(Scheme), } impl<'a> Job { - pub fn from_argv() -> Job + pub fn from_argv() -> Result { use clap::{App, Arg}; - let matches = App::new(clap::crate_name!()) + let app = App::new(clap::crate_name!()) .version(clap::crate_version!()) .author(clap::crate_authors!()) .about(clap::crate_description!()) @@ -171,35 +178,34 @@ impl<'a> Job .long("list") .help("list available color schemes") .takes_value(false), - ) - .get_matches(); + ); - if matches.is_present("v") { + let matches = app.get_matches(); + + if matches.is_present("verbose") { VERBOSITY.store(true, Ordering::SeqCst); } - if matches.is_present("l") { - Job::schemes(); - std::process::exit(0); + if matches.is_present("list") { + return Ok(Self::List); }; if let Some(name) = matches.value_of("dump") { - let scm = Job::pick_scheme(name); - Job::dump(scm); - std::process::exit(0); + let scm = Self::pick_scheme(name); + return Ok(Self::Dump(scm)); } let scheme = match matches.value_of("file") { - Some("-") => Job::scheme_from_stdin(), + Some("-") => Self::scheme_from_stdin(), Some(fname) => Scheme::Custom(Some(PathBuf::from(fname))), None => match matches.value_of("scheme") { - Some("-") | None => Job::scheme_from_stdin(), - Some(name) => Job::pick_scheme(name), + Some("-") | None => Self::scheme_from_stdin(), + Some(name) => Self::pick_scheme(name), }, }; - Job { scheme } + Ok(Self::Set(scheme)) } fn pick_scheme(name: &str) -> Scheme @@ -226,22 +232,56 @@ impl<'a> Job { vrb!("Dumping color scheme {}", scm); match scm { - Scheme::Default => Job::dump_scheme(&DEFAULT_COLORS), - Scheme::SolarizedDark => Job::dump_scheme(&SOLARIZED_COLORS_DARK), - Scheme::SolarizedLight => Job::dump_scheme(&SOLARIZED_COLORS_LIGHT), - Scheme::Custom(None) => Job::dump_palette(Palette::from_stdin()), + Scheme::Default => Self::dump_scheme(&DEFAULT_COLORS), + Scheme::SolarizedDark => Self::dump_scheme(&SOLARIZED_COLORS_DARK), + Scheme::SolarizedLight => + Self::dump_scheme(&SOLARIZED_COLORS_LIGHT), + Scheme::Custom(None) => Self::dump_palette(Palette::from_stdin()), Scheme::Custom(Some(fname)) => - Job::dump_palette(Palette::from_file(&fname)), + Self::dump_palette(Palette::from_file(&fname)), } } fn dump_scheme(colors: &[&str; PALETTE_SIZE]) { let pal: Palette = Palette::new(colors); - pal.dump() + pal.dump(); } fn dump_palette(pal: Palette) { pal.dump() } + + fn run(self) -> Result<()> + { + match self { + Self::Dump(scm) => Self::dump(scm), + Self::List => Self::schemes(), + Self::Set(scm) => Self::set_scheme(scm)?, + } + + Ok(()) + } + + fn set_scheme(scheme: Scheme) -> Result<()> + { + let pal: Palette = match scheme { + Scheme::Default => Palette::new(&DEFAULT_COLORS), + Scheme::SolarizedDark => Palette::new(&SOLARIZED_COLORS_DARK), + Scheme::SolarizedLight => Palette::new(&SOLARIZED_COLORS_LIGHT), + Scheme::Custom(None) => Palette::from_stdin(), + Scheme::Custom(Some(ref fname)) => Palette::from_file(fname), + }; + vrb!("Using palette:"); + vrb!("{}", pal); + let fd = get_console_fd()?; + vrb!("fd: {}", fd); + + ioctl_pio_cmap(fd, &pal)?; + + clear_term(fd)?; + vrb!("successfully enabled scheme {:?}", scheme); + /* It’s fine to leak the fd, the kernel will clean up anyways. */ + Ok(()) + } } /* [impl Job] */ /* Rust appears to come with two wrappers for ``ioctl(2)``, but neither can be utilized for our @@ -519,54 +559,63 @@ fn fd_of_path(path: &std::path::Path) -> Option } } -fn get_console_fd() -> Option +fn get_console_fd() -> Result { for path in CONSOLE_PATHS.iter() { vrb!("trying path: {:?}", path); let path = std::path::Path::new(path); if let Some(fd) = fd_of_path(path) { vrb!(" * Success!"); - return Some(fd); + return Ok(fd); } } - vrb!("could not retrieve fd for any of the search paths"); - None + Err(anyhow!("could not retrieve fd for any of the search paths")) } -fn write_to_term(fd: Fd, buf: &str) +fn write_to_term(fd: Fd, buf: &str) -> Result<()> { let len = buf.len() as libc::size_t; - let raw = std::ffi::CString::new(buf.as_bytes()).unwrap(); - unsafe { libc::write(fd, raw.as_ptr() as *const libc::c_void, len) }; + + if unsafe { libc::write(fd, buf.as_ptr() as *const libc::c_void, len) } + != len as isize + { + Err(anyhow!( + "failed to write {} B to fd {}: {}", + len, + fd, + Error::last_os_error() + )) + } else { + Ok(()) + } +} + +fn clear_term(fd: Fd) -> Result<()> +{ + let clear = "\x1b[2J"; + let cursor = "\x1b[1;1H"; + write_to_term(fd, clear)?; + write_to_term(fd, cursor)?; + + Ok(()) } -fn clear_term(fd: Fd) +fn ioctl_pio_cmap(fd: Fd, pal: &Palette) -> Result<()> { - let clear: &str = "\x1b[2J"; - let cursor: &str = "\x1b[1;1H"; - write_to_term(fd, clear); - write_to_term(fd, cursor); + if unsafe { ioctl(fd, PIO_CMAP, std::mem::transmute(pal)) } < 0 { + Err(anyhow!( + "PIO_CMAP, ioctl failed to insert new palette: {}", + Error::last_os_error() + )) + } else { + Ok(()) + } } -fn main() +fn main() -> Result<()> { - let job = Job::from_argv(); + let job = Job::from_argv()?; vrb!("job parms: {:?}", job); - let mut pal: Palette = match job.scheme { - Scheme::Default => Palette::new(&DEFAULT_COLORS), - Scheme::SolarizedDark => Palette::new(&SOLARIZED_COLORS_DARK), - Scheme::SolarizedLight => Palette::new(&SOLARIZED_COLORS_LIGHT), - Scheme::Custom(None) => Palette::from_stdin(), - Scheme::Custom(Some(ref fname)) => Palette::from_file(fname), - }; - vrb!("Using palette:"); - vrb!("{}", pal); - let fd = get_console_fd().unwrap(); - vrb!("fd: {}", fd); - if unsafe { ioctl(fd, PIO_CMAP, std::mem::transmute(&mut pal)) } < 0 { - panic!("PIO_CMAP, ioctl failed to insert new palette") - } - clear_term(fd); - vrb!("terminated from job {:?}", job); + job.run() } -- cgit v1.2.3