diff --git a/src/cmd/base32/mod.rs b/src/cmd/base32/mod.rs index 4b02c42..d27daf9 100644 --- a/src/cmd/base32/mod.rs +++ b/src/cmd/base32/mod.rs @@ -2,9 +2,9 @@ use super::Cmd; use clap::{value_parser, Arg, ArgAction, Command}; use data_encoding::BASE32; use std::{ + error::Error, fs, io::{self, Read, Write}, - process, }; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -70,11 +70,11 @@ impl Cmd for Base32 { return Err(io::Error::new(io::ErrorKind::Other, "No input").into()); }; let files: Vec<_> = match matches.get_many::("INPUT") { - Some(c) => c.map(|x| x.clone()).collect(), + Some(c) => c.cloned().collect(), None => vec![String::from("-")], }; let len = files.len(); - let color = match matches.get_one::("color").map(|x| x.as_str()) { + let color = match matches.get_one::("color").map(String::as_str) { Some("always") => ColorChoice::Always, Some("ansi") => ColorChoice::AlwaysAnsi, Some("auto") => { @@ -98,9 +98,9 @@ impl Cmd for Base32 { } else if index > 0 { println!(); } - let contents = get_contents(&file); + let contents = get_contents(&file)?; if matches.get_flag("DECODE") { - decode_base32(contents, matches.get_flag("IGNORE")); + decode_base32(contents, matches.get_flag("IGNORE"))?; } else { encode_base32( &contents, @@ -121,60 +121,34 @@ impl Cmd for Base32 { } } -fn decode_base32(mut contents: String, ignore: bool) { +fn decode_base32(mut contents: String, ignore: bool) -> Result<(), Box> { if ignore { contents.retain(|c| !c.is_whitespace()); } else { contents = contents.replace('\n', ""); } - let decoded = match BASE32.decode(contents.as_bytes()) { - Ok(c) => c, - Err(e) => { - eprintln!("base32: {e}"); - process::exit(1); - } - }; - let output = match String::from_utf8(decoded) { - Ok(c) => c, - Err(e) => { - eprintln!("base32: {e}"); - process::exit(1); - } - }; + let decoded = BASE32.decode(contents.as_bytes())?; + let output = String::from_utf8(decoded)?; println!("{}", output.trim_end()); + Ok(()) } fn encode_base32(contents: &str, wrap: usize) { - let encoded = BASE32 + BASE32 .encode(contents.as_bytes()) .chars() .collect::>() .chunks(wrap) .map(|c| c.iter().collect::()) - .collect::>(); - for line in &encoded { - println!("{line}"); - } + .for_each(|line| println!("{line}")); } -fn get_contents(file: &str) -> String { +fn get_contents(file: &str) -> Result> { let mut contents = String::new(); if file == "-" { - match io::stdin().read_to_string(&mut contents) { - Ok(_) => true, - Err(e) => { - eprintln!("base32: {e}"); - process::exit(1); - } - }; + io::stdin().read_to_string(&mut contents)?; } else { - contents = match fs::read_to_string(file) { - Ok(c) => c, - Err(e) => { - eprintln!("base32: {e}"); - process::exit(1); - } - }; + contents = fs::read_to_string(file)?; } - contents + Ok(contents) } diff --git a/src/cmd/base64/mod.rs b/src/cmd/base64/mod.rs index eb66578..e77236b 100644 --- a/src/cmd/base64/mod.rs +++ b/src/cmd/base64/mod.rs @@ -4,8 +4,9 @@ use clap::{value_parser, Arg, ArgAction, ArgMatches, Command}; use std::{ error::Error, fs, - io::{self, Read}, + io::{self, Read, Write}, }; +use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; #[derive(Debug)] pub struct Base64 { @@ -47,6 +48,10 @@ impl Cmd for Base64 { .long("wrap") .default_value("76") .value_parser(value_parser!(usize)), + Arg::new("color") + .short('c') + .long("color") + .value_parser(["always", "ansi", "auto", "never"]), Arg::new("VERBOSE") .help("Display a header naming each file") .short('v') @@ -65,16 +70,31 @@ impl Cmd for Base64 { return Err(Box::new(io::Error::new(io::ErrorKind::Other, "No input"))); }; let files: Vec<_> = match matches.get_many::("INPUT") { - Some(c) => c.map(|x| x.clone()).collect(), + Some(c) => c.cloned().collect(), None => vec![String::from("-")], }; let len = files.len(); + let color = match matches.get_one::("color").map(String::as_str) { + Some("always") => ColorChoice::Always, + Some("ansi") => ColorChoice::AlwaysAnsi, + Some("auto") => { + if atty::is(atty::Stream::Stdout) { + ColorChoice::Auto + } else { + ColorChoice::Never + } + } + _ => ColorChoice::Never, + }; for (index, file) in files.into_iter().enumerate() { if { len > 1 || matches.get_flag("VERBOSE") } && !matches.get_flag("QUIET") { + let mut stdout = StandardStream::stdout(color); + stdout.set_color(ColorSpec::new().set_fg(Some(Color::Green)))?; match index { - 0 => println!("===> {file} <==="), - _ => println!("\n===> {file} <==="), - }; + 0 => writeln!(stdout, "===> {file} <==="), + _ => writeln!(stdout, "\n===> {file} <==="), + }?; + stdout.reset()?; } else if index > 0 { println!(); } @@ -105,22 +125,19 @@ fn decode_base64(mut contents: String, ignore: bool) -> Result<(), Box>() .chunks(wrap) .map(|c| c.iter().collect::()) - .collect::>(); - for line in &encoded { - println!("{line}"); - } + .for_each(|line| println!("{line}")); } fn get_contents(file: &str) -> Result> { diff --git a/src/cmd/head/mod.rs b/src/cmd/head/mod.rs index 8075bff..8e7cc7e 100644 --- a/src/cmd/head/mod.rs +++ b/src/cmd/head/mod.rs @@ -6,7 +6,6 @@ use std::{ error::Error, fs, io::{self, stdin, Read, Write}, - process, }; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -108,7 +107,7 @@ impl Cmd for Head { }; let header = !matches.get_flag("QUIET") && { files.len() > 1 || matches.get_flag("HEADER") }; - let color = match matches.get_one::("color").map(|x| x.as_str()) { + let color = match matches.get_one::("color").map(String::as_str) { Some("always") => ColorChoice::Always, Some("ansi") => ColorChoice::AlwaysAnsi, Some("auto") => { @@ -143,22 +142,9 @@ fn head( ) -> Result<(), Box> { let mut contents = String::new(); if file == "-" { - match stdin().read_to_string(&mut contents) { - Ok(_) => true, - Err(e) => { - eprintln!("head: {e}"); - process::exit(1); - } - }; + stdin().read_to_string(&mut contents)?; } else { - let buf = fs::read_to_string(file); - contents = match buf { - Ok(c) => c, - Err(e) => { - eprintln!("head: {e}"); - process::exit(1); - } - }; + contents = fs::read_to_string(file)?; } if header { let mut stdout = StandardStream::stdout(color); @@ -167,7 +153,7 @@ fn head( stdout.reset()?; } if bytes { - for (index, char) in contents.chars().into_iter().enumerate() { + for (index, char) in contents.chars().enumerate() { if index < count { print!("{char}"); } else { @@ -177,7 +163,7 @@ fn head( } println!(); } else { - for (index, line) in contents.lines().into_iter().enumerate() { + for (index, line) in contents.lines().enumerate() { if index < count { println!("{line}"); } else { diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 57aab0d..7a63dba 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -46,6 +46,7 @@ pub use { echo::{Echo, ECHO}, factor::{Factor, FACTOR}, head::{Head, HEAD}, + mountpoint::{Mountpoint, MOUNTPOINT}, nologin::{Nologin, NOLOGIN}, r#false::{False, FALSE}, r#true::{True, TRUE}, diff --git a/src/cmd/mountpoint/mod.rs b/src/cmd/mountpoint/mod.rs index 5a15116..c20600f 100644 --- a/src/cmd/mountpoint/mod.rs +++ b/src/cmd/mountpoint/mod.rs @@ -31,6 +31,7 @@ impl Cmd for Mountpoint { .help("Show the major/minor numbers of the given blockdevice on standard output.") .short('x') .long("devno") + .conflicts_with("fs-devno") .action(ArgAction::SetTrue), Arg::new("quiet") .help("Be quiet - don’t print anything.") diff --git a/src/cmd/shitbox/mod.rs b/src/cmd/shitbox/mod.rs index 4bcef2a..85078bd 100644 --- a/src/cmd/shitbox/mod.rs +++ b/src/cmd/shitbox/mod.rs @@ -1,6 +1,6 @@ use super::{ - Cmd, BASE_32, BASE_64, BOOTSTRAP, DIRNAME, ECHO, FACTOR, FALSE, HEAD, HOSTNAME, NOLOGIN, SLEEP, - TRUE, + Cmd, BASE_32, BASE_64, BOOTSTRAP, DIRNAME, ECHO, FACTOR, FALSE, HEAD, HOSTNAME, MOUNTPOINT, + NOLOGIN, SLEEP, TRUE, }; use clap::Command; use std::{ @@ -41,6 +41,7 @@ impl Cmd for Shitbox { FALSE.cli(), FACTOR.cli(), HEAD.cli(), + MOUNTPOINT.cli(), NOLOGIN.cli(), HOSTNAME.cli(), SLEEP.cli(), @@ -61,6 +62,7 @@ impl Cmd for Shitbox { Some(("factor", matches)) => FACTOR.run(Some(matches))?, Some(("false", _matches)) => FALSE.run(None)?, Some(("head", matches)) => HEAD.run(Some(matches))?, + Some(("mountpoint", matches)) => MOUNTPOINT.run(Some(matches))?, Some(("nologin", _matches)) => NOLOGIN.run(None)?, Some(("hostname", matches)) => HOSTNAME.run(Some(matches))?, Some(("sleep", matches)) => SLEEP.run(Some(matches))?, diff --git a/src/lib.rs b/src/lib.rs index 953ebb3..128a433 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ use std::{env, error::Error, path::PathBuf, string::ToString}; pub mod cmd; pub use cmd::{ Cmd, Commands, BASE_32, BASE_64, BOOTSTRAP, DIRNAME, ECHO, FACTOR, FALSE, HEAD, HOSTNAME, - NOLOGIN, SHITBOX, SLEEP, TRUE, + MOUNTPOINT, NOLOGIN, SHITBOX, SLEEP, TRUE, }; pub mod math; @@ -41,8 +41,20 @@ pub fn run() -> Result<(), Box> { cmd::COMMANDS .set(Commands { items: vec![ - &BASE_32, &BASE_64, &BOOTSTRAP, &DIRNAME, &ECHO, &FALSE, &FACTOR, &HEAD, - &HOSTNAME, &NOLOGIN, &TRUE, &SLEEP, &SHITBOX, + &BASE_32, + &BASE_64, + &BOOTSTRAP, + &DIRNAME, + &ECHO, + &FALSE, + &FACTOR, + &HEAD, + &HOSTNAME, + &MOUNTPOINT, + &NOLOGIN, + &TRUE, + &SLEEP, + &SHITBOX, ], }) .expect("Cannot register commands"); @@ -59,6 +71,7 @@ pub fn run() -> Result<(), Box> { HEAD.run(Some(&HEAD.cli().get_matches()))?; } "hostname" => HOSTNAME.run(Some(&HOSTNAME.cli().get_matches()))?, + "mountpoint" => MOUNTPOINT.run(Some(&MOUNTPOINT.cli().get_matches()))?, "nologin" => NOLOGIN.run(None)?, "true" => TRUE.run(None)?, "shitbox" => {