summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2021-11-10 00:50:30 +0100
committerPhilipp Gesang <phg@phi-gamma.net>2021-11-10 01:20:12 +0100
commitf906287746e7e1a837c541c5f4f6668409000187 (patch)
tree38cfa2c361881c2e1fa41aeb3f64957fac32e8fb /src
parent0e300d324bd6feea899afb4d182677f42ab1b121 (diff)
downloadvtcol-f906287746e7e1a837c541c5f4f6668409000187.tar.gz
rework error handling
anyhow!() ftw.
Diffstat (limited to 'src')
-rw-r--r--src/vtcol.rs155
1 files changed, 102 insertions, 53 deletions
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<Job>
{
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<Fd>
}
}
-fn get_console_fd() -> Option<Fd>
+fn get_console_fd() -> Result<Fd>
{
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()
}