summaryrefslogtreecommitdiff
path: root/src/vtcol.rs
diff options
context:
space:
mode:
authorPhilipp Gesang <phg@phi-gamma.net>2021-12-12 12:12:23 +0100
committerPhilipp Gesang <phg@phi-gamma.net>2021-12-12 12:21:02 +0100
commitb32495bd359fa25b9cd4d52e72da1e24630a0663 (patch)
treebf705e538b461d012107cf4dba53a002ecc124e5 /src/vtcol.rs
parent33d3f2b30d77f242ed0a6a228a9f183778504640 (diff)
downloadvtcol-b32495bd359fa25b9cd4d52e72da1e24630a0663.tar.gz
bin: allow specifying the console on the command line
As in: $ vtcol --console /dev/tty6 colors get solarized $ vtcol --console /dev/tty6 colors set phosphor $ vtcol --console /dev/tty6 colors get phosphor That simplifies testing so much I wonder why the heck I needed this long to finally implement it.
Diffstat (limited to 'src/vtcol.rs')
-rw-r--r--src/vtcol.rs180
1 files changed, 117 insertions, 63 deletions
diff --git a/src/vtcol.rs b/src/vtcol.rs
index dcc7820..89cc162 100644
--- a/src/vtcol.rs
+++ b/src/vtcol.rs
@@ -18,9 +18,18 @@ macro_rules! vrb {
)}
}
+/** Helper for choosing the console. Defaults to the current one if
+none is explicitly supplied. */
+#[inline]
+fn open_console(path: Option<&str>) -> io::Result<Console>
+{
+ path.map(Console::from_path).unwrap_or_else(|| Console::current())
+}
+
+/** Trait for subcommands to implement. */
trait Run
{
- fn run(self) -> Result<()>;
+ fn run(self, console: Option<String>) -> Result<()>;
}
#[derive(Debug)]
@@ -38,13 +47,14 @@ enum LedJob
impl Run for LedJob
{
- fn run(self) -> Result<()>
+ fn run(self, console: Option<String>) -> Result<()>
{
match self {
- Self::Get(raw) => Self::get(raw),
- Self::Revert => Self::revert(),
- Self::Set(st) => Self::set(st),
- Self::SetIndividual(c, n, s) => Self::set_individual(c, n, s),
+ Self::Get(raw) => Self::get(console, raw),
+ Self::Revert => Self::revert(console),
+ Self::Set(st) => Self::set(console, st),
+ Self::SetIndividual(c, n, s) =>
+ Self::set_individual(console, c, n, s),
}
}
} /* [impl Run for LedJob] */
@@ -52,9 +62,9 @@ impl Run for LedJob
impl LedJob
{
/** Get the keyboard LED state. */
- fn get(raw: bool) -> Result<()>
+ fn get(con: Option<String>, raw: bool) -> Result<()>
{
- let fd = Console::current()?;
+ let fd = open_console(con.as_deref())?;
vrb!("console fd: {}", fd);
let leds = KbLedState::get(&fd)?;
@@ -69,9 +79,9 @@ impl LedJob
}
/** Set the keyboard LED state. */
- fn set(st: KbLedState) -> Result<()>
+ fn set(con: Option<String>, st: KbLedState) -> Result<()>
{
- let fd = Console::current()?;
+ let fd = open_console(con.as_deref())?;
vrb!("console fd: {}", fd);
st.set(&fd)?;
@@ -82,12 +92,13 @@ impl LedJob
/** Set the state of the given LEDs using the current state as base. */
fn set_individual(
+ con: Option<String>,
cap: Option<bool>,
num: Option<bool>,
scr: Option<bool>,
) -> Result<()>
{
- let fd = Console::current()?;
+ let fd = open_console(con.as_deref())?;
vrb!("console fd: {}", fd);
let mut st = KbLedState::get(&fd)?;
@@ -103,9 +114,9 @@ impl LedJob
}
/** Revert the keyboard LED state. */
- fn revert() -> Result<()>
+ fn revert(con: Option<String>) -> Result<()>
{
- let fd = Console::current()?;
+ let fd = open_console(con.as_deref())?;
vrb!("console fd: {}", fd);
KbLedState::revert(&fd)?;
@@ -134,16 +145,16 @@ enum ColorJob
impl Run for ColorJob
{
- fn run(self) -> Result<()>
+ fn run(self, console: Option<String>) -> Result<()>
{
match self {
Self::Dump(scm) => Self::dump(scm),
Self::List => Self::list(),
- Self::Set(scm) => Self::set(scm),
- Self::Get(b64) => Self::get(b64),
- Self::Toggle(one, two) => Self::toggle(one, two),
+ Self::Set(scm) => Self::set(console, scm),
+ Self::Get(b64) => Self::get(console, b64),
+ Self::Toggle(one, two) => Self::toggle(console, one, two),
Self::Fade(from, to, ms, hz, clear) =>
- Self::fade(from, to, ms, hz, clear),
+ Self::fade(console, from, to, ms, hz, clear),
}
}
} /* [impl Run for ColorJob] */
@@ -192,22 +203,22 @@ impl ColorJob
}
}
- fn set(scheme: Scheme) -> Result<()>
+ fn set(con: Option<String>, scheme: Scheme) -> Result<()>
{
- let con = Console::current()?;
- vrb!("console fd: {}", con);
+ let fd = open_console(con.as_deref())?;
+ vrb!("console fd: {}", fd);
- con.apply_scheme(&scheme)?;
- con.clear()?;
+ fd.apply_scheme(&scheme)?;
+ fd.clear()?;
vrb!("successfully enabled scheme {:?}", scheme);
/* It’s fine to leak the fd, the kernel will clean up anyways. */
Ok(())
}
- fn get(b64: bool) -> Result<()>
+ fn get(con: Option<String>, b64: bool) -> Result<()>
{
- let fd = Console::current()?;
+ let fd = open_console(con.as_deref())?;
vrb!("console fd: {}", fd);
let scm = fd.current_scheme()?;
@@ -224,15 +235,18 @@ impl ColorJob
/** Toggle between two schemes. Defaults to ``one`` in case neither scheme
is active.
*/
- fn toggle(one: Scheme, two: Scheme) -> Result<()>
+ fn toggle(con: Option<String>, one: Scheme, two: Scheme) -> Result<()>
{
- let fd = Console::current()?;
- vrb!("console fd: {}", fd);
+ let pal = {
+ let fd = open_console(con.as_deref())?;
+ vrb!("console fd: {}", fd);
+ fd.current_palette()?
+ };
- if fd.current_palette()? == Palette::try_from(&one)? {
- Self::set(two)
+ if pal == Palette::try_from(&one)? {
+ Self::set(con, two)
} else {
- Self::set(one)
+ Self::set(con, one)
}
}
@@ -240,6 +254,7 @@ impl ColorJob
If ``from`` is ``None``, the current palette is used as starting point. */
fn fade(
+ con: Option<String>,
from: Option<Scheme>,
to: Scheme,
dur: Duration,
@@ -247,7 +262,7 @@ impl ColorJob
clear: bool,
) -> Result<()>
{
- let fd = Console::current()?;
+ let fd = open_console(con.as_deref())?;
vrb!("console fd: {}", fd);
let from = if let Some(from) = from {
@@ -266,7 +281,7 @@ impl ColorJob
/** Subcommand and runtime parameters. */
#[derive(Debug)]
-enum Job
+enum Subcmd
{
/** Console palette ops. */
Colors(ColorJob),
@@ -274,6 +289,9 @@ enum Job
Leds(LedJob),
}
+#[derive(Debug)]
+struct Job(Option<String>, Subcmd);
+
impl<'a> Job
{
pub fn from_argv() -> Result<Job>
@@ -292,6 +310,17 @@ impl<'a> Job
.help("enable extra diagnostics")
.takes_value(false),
)
+ .arg(
+ Arg::with_name("console")
+ .set(ArgSettings::Global)
+ .short("C")
+ .long("console")
+ .help(
+ "path to the console device to operate on [default: \
+ current console]",
+ )
+ .takes_value(true),
+ )
.subcommand(
SubCommand::with_name("colors")
.about("operations on the console palette")
@@ -508,25 +537,37 @@ impl<'a> Job
VERBOSITY.store(true, Ordering::SeqCst);
}
+ let con = matches.value_of("console").map(String::from);
+
match matches.subcommand() {
("colors", Some(subm)) =>
match subm.subcommand() {
("dump", Some(subm)) => {
if let Some(b64) = subm.value_of("base64") {
let scheme = Scheme::from_base64(b64)?;
- return Ok(Self::Colors(ColorJob::Dump(scheme)));
+ return Ok(Self(
+ con,
+ Subcmd::Colors(ColorJob::Dump(scheme)),
+ ));
}
if let Some(name) = subm.value_of("scheme") {
let scm = Scheme::from(name);
- return Ok(Self::Colors(ColorJob::Dump(scm)));
+ return Ok(Self(
+ con,
+ Subcmd::Colors(ColorJob::Dump(scm)),
+ ));
}
Err(anyhow!("dump requires an argument"))
},
- ("list", _) => Ok(Self::Colors(ColorJob::List)),
+ ("list", _) =>
+ Ok(Self(con, Subcmd::Colors(ColorJob::List))),
("set", Some(subm)) => {
if let Some(b64) = subm.value_of("base64") {
let scheme = Scheme::from_base64(&b64)?;
- return Ok(Self::Colors(ColorJob::Set(scheme)));
+ return Ok(Self(
+ con,
+ Subcmd::Colors(ColorJob::Set(scheme)),
+ ));
}
let scheme = match subm.value_of("scheme") {
Some("-") => Self::read_scheme_from_stdin(),
@@ -547,20 +588,26 @@ impl<'a> Job
},
},
};
- Ok(Self::Colors(ColorJob::Set(scheme)))
+ Ok(Self(con, Subcmd::Colors(ColorJob::Set(scheme))))
},
("get", Some(subm)) =>
- Ok(Self::Colors(ColorJob::Get(
- subm.is_present("base64"),
- ))),
+ Ok(Self(
+ con,
+ Subcmd::Colors(ColorJob::Get(
+ subm.is_present("base64"),
+ )),
+ )),
("toggle", Some(subm)) => {
match (subm.value_of("one"), subm.value_of("two")) {
(Some(one), Some(two)) => {
vrb!("toggle schemes [{}] and [{}]", one, two);
- Ok(Self::Colors(ColorJob::Toggle(
- Scheme::from(one),
- Scheme::from(two),
- )))
+ Ok(Self(
+ con,
+ Subcmd::Colors(ColorJob::Toggle(
+ Scheme::from(one),
+ Scheme::from(two),
+ )),
+ ))
},
_ =>
Err(anyhow!(
@@ -590,13 +637,16 @@ impl<'a> Job
"please supply color scheme to fade to"
)),
(from, Some(to)) =>
- Ok(Self::Colors(ColorJob::Fade(
- from.map(Scheme::from),
- Scheme::from(to),
- dur,
- hz,
- clear,
- ))),
+ Ok(Self(
+ con,
+ Subcmd::Colors(ColorJob::Fade(
+ from.map(Scheme::from),
+ Scheme::from(to),
+ dur,
+ hz,
+ clear,
+ )),
+ )),
}
},
(junk, _) =>
@@ -612,21 +662,27 @@ impl<'a> Job
match subm.subcommand() {
("get", Some(subm)) => {
let raw = subm.is_present("u8");
- Ok(Self::Leds(LedJob::Get(raw)))
+ Ok(Self(con, Subcmd::Leds(LedJob::Get(raw))))
},
("set", Some(subm)) => {
if subm.is_present("revert") {
- return Ok(Self::Leds(LedJob::Revert));
+ return Ok(Self(con, Subcmd::Leds(LedJob::Revert)));
}
if let Some(st) = subm.value_of("u8") {
let st: u8 = st.parse()?;
let st = KbLedState::try_from(st)?;
- return Ok(Self::Leds(LedJob::Set(st)));
+ return Ok(Self(
+ con,
+ Subcmd::Leds(LedJob::Set(st)),
+ ));
}
let cap = subm.value_of("caps").map(|a| a == "on");
let num = subm.value_of("num").map(|a| a == "on");
let scr = subm.value_of("scroll").map(|a| a == "on");
- Ok(Self::Leds(LedJob::SetIndividual(cap, num, scr)))
+ Ok(Self(
+ con,
+ Subcmd::Leds(LedJob::SetIndividual(cap, num, scr)),
+ ))
},
(junk, _) =>
Err(anyhow!(
@@ -652,20 +708,18 @@ impl<'a> Job
vrb!("vtcol>");
Scheme::from_stdin()
}
-} /* [impl Job] */
-impl Run for Job
-{
fn run(self) -> Result<()>
{
- match self {
- Self::Colors(cols) => cols.run()?,
- Self::Leds(leds) => leds.run()?,
+ let Job(con, cmd) = self;
+ match cmd {
+ Subcmd::Colors(cols) => cols.run(con)?,
+ Subcmd::Leds(leds) => leds.run(con)?,
}
Ok(())
}
-} /* [impl Run for Job] */
+} /* [impl Job] */
fn main() -> Result<()>
{