Added color to base64 file header; Ran clippy lints and fixed all but

missing docs;
This commit is contained in:
Nathan Fisher 2023-01-04 15:14:16 -05:00
parent 36835dd322
commit 6b6cc314e8
7 changed files with 70 additions and 76 deletions

View File

@ -2,9 +2,9 @@ use super::Cmd;
use clap::{value_parser, Arg, ArgAction, Command}; use clap::{value_parser, Arg, ArgAction, Command};
use data_encoding::BASE32; use data_encoding::BASE32;
use std::{ use std::{
error::Error,
fs, fs,
io::{self, Read, Write}, io::{self, Read, Write},
process,
}; };
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; 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()); return Err(io::Error::new(io::ErrorKind::Other, "No input").into());
}; };
let files: Vec<_> = match matches.get_many::<String>("INPUT") { let files: Vec<_> = match matches.get_many::<String>("INPUT") {
Some(c) => c.map(|x| x.clone()).collect(), Some(c) => c.cloned().collect(),
None => vec![String::from("-")], None => vec![String::from("-")],
}; };
let len = files.len(); let len = files.len();
let color = match matches.get_one::<String>("color").map(|x| x.as_str()) { let color = match matches.get_one::<String>("color").map(String::as_str) {
Some("always") => ColorChoice::Always, Some("always") => ColorChoice::Always,
Some("ansi") => ColorChoice::AlwaysAnsi, Some("ansi") => ColorChoice::AlwaysAnsi,
Some("auto") => { Some("auto") => {
@ -98,9 +98,9 @@ impl Cmd for Base32 {
} else if index > 0 { } else if index > 0 {
println!(); println!();
} }
let contents = get_contents(&file); let contents = get_contents(&file)?;
if matches.get_flag("DECODE") { if matches.get_flag("DECODE") {
decode_base32(contents, matches.get_flag("IGNORE")); decode_base32(contents, matches.get_flag("IGNORE"))?;
} else { } else {
encode_base32( encode_base32(
&contents, &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<dyn Error>> {
if ignore { if ignore {
contents.retain(|c| !c.is_whitespace()); contents.retain(|c| !c.is_whitespace());
} else { } else {
contents = contents.replace('\n', ""); contents = contents.replace('\n', "");
} }
let decoded = match BASE32.decode(contents.as_bytes()) { let decoded = BASE32.decode(contents.as_bytes())?;
Ok(c) => c, let output = String::from_utf8(decoded)?;
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);
}
};
println!("{}", output.trim_end()); println!("{}", output.trim_end());
Ok(())
} }
fn encode_base32(contents: &str, wrap: usize) { fn encode_base32(contents: &str, wrap: usize) {
let encoded = BASE32 BASE32
.encode(contents.as_bytes()) .encode(contents.as_bytes())
.chars() .chars()
.collect::<Vec<char>>() .collect::<Vec<char>>()
.chunks(wrap) .chunks(wrap)
.map(|c| c.iter().collect::<String>()) .map(|c| c.iter().collect::<String>())
.collect::<Vec<String>>(); .for_each(|line| println!("{line}"));
for line in &encoded {
println!("{line}");
}
} }
fn get_contents(file: &str) -> String { fn get_contents(file: &str) -> Result<String, Box<dyn Error>> {
let mut contents = String::new(); let mut contents = String::new();
if file == "-" { if file == "-" {
match io::stdin().read_to_string(&mut contents) { io::stdin().read_to_string(&mut contents)?;
Ok(_) => true,
Err(e) => {
eprintln!("base32: {e}");
process::exit(1);
}
};
} else { } else {
contents = match fs::read_to_string(file) { contents = fs::read_to_string(file)?;
Ok(c) => c,
Err(e) => {
eprintln!("base32: {e}");
process::exit(1);
}
};
} }
contents Ok(contents)
} }

View File

@ -4,8 +4,9 @@ use clap::{value_parser, Arg, ArgAction, ArgMatches, Command};
use std::{ use std::{
error::Error, error::Error,
fs, fs,
io::{self, Read}, io::{self, Read, Write},
}; };
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
#[derive(Debug)] #[derive(Debug)]
pub struct Base64 { pub struct Base64 {
@ -47,6 +48,10 @@ impl Cmd for Base64 {
.long("wrap") .long("wrap")
.default_value("76") .default_value("76")
.value_parser(value_parser!(usize)), .value_parser(value_parser!(usize)),
Arg::new("color")
.short('c')
.long("color")
.value_parser(["always", "ansi", "auto", "never"]),
Arg::new("VERBOSE") Arg::new("VERBOSE")
.help("Display a header naming each file") .help("Display a header naming each file")
.short('v') .short('v')
@ -65,16 +70,31 @@ impl Cmd for Base64 {
return Err(Box::new(io::Error::new(io::ErrorKind::Other, "No input"))); return Err(Box::new(io::Error::new(io::ErrorKind::Other, "No input")));
}; };
let files: Vec<_> = match matches.get_many::<String>("INPUT") { let files: Vec<_> = match matches.get_many::<String>("INPUT") {
Some(c) => c.map(|x| x.clone()).collect(), Some(c) => c.cloned().collect(),
None => vec![String::from("-")], None => vec![String::from("-")],
}; };
let len = files.len(); let len = files.len();
let color = match matches.get_one::<String>("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() { for (index, file) in files.into_iter().enumerate() {
if { len > 1 || matches.get_flag("VERBOSE") } && !matches.get_flag("QUIET") { 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 { match index {
0 => println!("===> {file} <==="), 0 => writeln!(stdout, "===> {file} <==="),
_ => println!("\n===> {file} <==="), _ => writeln!(stdout, "\n===> {file} <==="),
}; }?;
stdout.reset()?;
} else if index > 0 { } else if index > 0 {
println!(); println!();
} }
@ -105,22 +125,19 @@ fn decode_base64(mut contents: String, ignore: bool) -> Result<(), Box<dyn Error
} else { } else {
contents = contents.replace('\n', ""); contents = contents.replace('\n', "");
} }
let decoded = decode(&contents)?.to_vec(); let decoded = decode(&contents)?.clone();
let output = String::from_utf8(decoded)?; let output = String::from_utf8(decoded)?;
println!("{}", output.trim_end()); println!("{}", output.trim_end());
Ok(()) Ok(())
} }
fn encode_base64(contents: &str, wrap: usize) { fn encode_base64(contents: &str, wrap: usize) {
let encoded = encode(contents.as_bytes()) encode(contents.as_bytes())
.chars() .chars()
.collect::<Vec<char>>() .collect::<Vec<char>>()
.chunks(wrap) .chunks(wrap)
.map(|c| c.iter().collect::<String>()) .map(|c| c.iter().collect::<String>())
.collect::<Vec<String>>(); .for_each(|line| println!("{line}"));
for line in &encoded {
println!("{line}");
}
} }
fn get_contents(file: &str) -> Result<String, Box<dyn Error>> { fn get_contents(file: &str) -> Result<String, Box<dyn Error>> {

View File

@ -6,7 +6,6 @@ use std::{
error::Error, error::Error,
fs, fs,
io::{self, stdin, Read, Write}, io::{self, stdin, Read, Write},
process,
}; };
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
@ -108,7 +107,7 @@ impl Cmd for Head {
}; };
let header = let header =
!matches.get_flag("QUIET") && { files.len() > 1 || matches.get_flag("HEADER") }; !matches.get_flag("QUIET") && { files.len() > 1 || matches.get_flag("HEADER") };
let color = match matches.get_one::<String>("color").map(|x| x.as_str()) { let color = match matches.get_one::<String>("color").map(String::as_str) {
Some("always") => ColorChoice::Always, Some("always") => ColorChoice::Always,
Some("ansi") => ColorChoice::AlwaysAnsi, Some("ansi") => ColorChoice::AlwaysAnsi,
Some("auto") => { Some("auto") => {
@ -143,22 +142,9 @@ fn head(
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let mut contents = String::new(); let mut contents = String::new();
if file == "-" { if file == "-" {
match stdin().read_to_string(&mut contents) { stdin().read_to_string(&mut contents)?;
Ok(_) => true,
Err(e) => {
eprintln!("head: {e}");
process::exit(1);
}
};
} else { } else {
let buf = fs::read_to_string(file); contents = fs::read_to_string(file)?;
contents = match buf {
Ok(c) => c,
Err(e) => {
eprintln!("head: {e}");
process::exit(1);
}
};
} }
if header { if header {
let mut stdout = StandardStream::stdout(color); let mut stdout = StandardStream::stdout(color);
@ -167,7 +153,7 @@ fn head(
stdout.reset()?; stdout.reset()?;
} }
if bytes { if bytes {
for (index, char) in contents.chars().into_iter().enumerate() { for (index, char) in contents.chars().enumerate() {
if index < count { if index < count {
print!("{char}"); print!("{char}");
} else { } else {
@ -177,7 +163,7 @@ fn head(
} }
println!(); println!();
} else { } else {
for (index, line) in contents.lines().into_iter().enumerate() { for (index, line) in contents.lines().enumerate() {
if index < count { if index < count {
println!("{line}"); println!("{line}");
} else { } else {

View File

@ -46,6 +46,7 @@ pub use {
echo::{Echo, ECHO}, echo::{Echo, ECHO},
factor::{Factor, FACTOR}, factor::{Factor, FACTOR},
head::{Head, HEAD}, head::{Head, HEAD},
mountpoint::{Mountpoint, MOUNTPOINT},
nologin::{Nologin, NOLOGIN}, nologin::{Nologin, NOLOGIN},
r#false::{False, FALSE}, r#false::{False, FALSE},
r#true::{True, TRUE}, r#true::{True, TRUE},

View File

@ -31,6 +31,7 @@ impl Cmd for Mountpoint {
.help("Show the major/minor numbers of the given blockdevice on standard output.") .help("Show the major/minor numbers of the given blockdevice on standard output.")
.short('x') .short('x')
.long("devno") .long("devno")
.conflicts_with("fs-devno")
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
Arg::new("quiet") Arg::new("quiet")
.help("Be quiet - dont print anything.") .help("Be quiet - dont print anything.")

View File

@ -1,6 +1,6 @@
use super::{ use super::{
Cmd, BASE_32, BASE_64, BOOTSTRAP, DIRNAME, ECHO, FACTOR, FALSE, HEAD, HOSTNAME, NOLOGIN, SLEEP, Cmd, BASE_32, BASE_64, BOOTSTRAP, DIRNAME, ECHO, FACTOR, FALSE, HEAD, HOSTNAME, MOUNTPOINT,
TRUE, NOLOGIN, SLEEP, TRUE,
}; };
use clap::Command; use clap::Command;
use std::{ use std::{
@ -41,6 +41,7 @@ impl Cmd for Shitbox {
FALSE.cli(), FALSE.cli(),
FACTOR.cli(), FACTOR.cli(),
HEAD.cli(), HEAD.cli(),
MOUNTPOINT.cli(),
NOLOGIN.cli(), NOLOGIN.cli(),
HOSTNAME.cli(), HOSTNAME.cli(),
SLEEP.cli(), SLEEP.cli(),
@ -61,6 +62,7 @@ impl Cmd for Shitbox {
Some(("factor", matches)) => FACTOR.run(Some(matches))?, Some(("factor", matches)) => FACTOR.run(Some(matches))?,
Some(("false", _matches)) => FALSE.run(None)?, Some(("false", _matches)) => FALSE.run(None)?,
Some(("head", matches)) => HEAD.run(Some(matches))?, Some(("head", matches)) => HEAD.run(Some(matches))?,
Some(("mountpoint", matches)) => MOUNTPOINT.run(Some(matches))?,
Some(("nologin", _matches)) => NOLOGIN.run(None)?, Some(("nologin", _matches)) => NOLOGIN.run(None)?,
Some(("hostname", matches)) => HOSTNAME.run(Some(matches))?, Some(("hostname", matches)) => HOSTNAME.run(Some(matches))?,
Some(("sleep", matches)) => SLEEP.run(Some(matches))?, Some(("sleep", matches)) => SLEEP.run(Some(matches))?,

View File

@ -4,7 +4,7 @@ use std::{env, error::Error, path::PathBuf, string::ToString};
pub mod cmd; pub mod cmd;
pub use cmd::{ pub use cmd::{
Cmd, Commands, BASE_32, BASE_64, BOOTSTRAP, DIRNAME, ECHO, FACTOR, FALSE, HEAD, HOSTNAME, 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; pub mod math;
@ -41,8 +41,20 @@ pub fn run() -> Result<(), Box<dyn Error>> {
cmd::COMMANDS cmd::COMMANDS
.set(Commands { .set(Commands {
items: vec![ items: vec![
&BASE_32, &BASE_64, &BOOTSTRAP, &DIRNAME, &ECHO, &FALSE, &FACTOR, &HEAD, &BASE_32,
&HOSTNAME, &NOLOGIN, &TRUE, &SLEEP, &SHITBOX, &BASE_64,
&BOOTSTRAP,
&DIRNAME,
&ECHO,
&FALSE,
&FACTOR,
&HEAD,
&HOSTNAME,
&MOUNTPOINT,
&NOLOGIN,
&TRUE,
&SLEEP,
&SHITBOX,
], ],
}) })
.expect("Cannot register commands"); .expect("Cannot register commands");
@ -59,6 +71,7 @@ pub fn run() -> Result<(), Box<dyn Error>> {
HEAD.run(Some(&HEAD.cli().get_matches()))?; HEAD.run(Some(&HEAD.cli().get_matches()))?;
} }
"hostname" => HOSTNAME.run(Some(&HOSTNAME.cli().get_matches()))?, "hostname" => HOSTNAME.run(Some(&HOSTNAME.cli().get_matches()))?,
"mountpoint" => MOUNTPOINT.run(Some(&MOUNTPOINT.cli().get_matches()))?,
"nologin" => NOLOGIN.run(None)?, "nologin" => NOLOGIN.run(None)?,
"true" => TRUE.run(None)?, "true" => TRUE.run(None)?,
"shitbox" => { "shitbox" => {