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 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::<String>("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::<String>("color").map(|x| x.as_str()) {
let color = match matches.get_one::<String>("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<dyn Error>> {
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::<Vec<char>>()
.chunks(wrap)
.map(|c| c.iter().collect::<String>())
.collect::<Vec<String>>();
for line in &encoded {
println!("{line}");
}
.for_each(|line| println!("{line}"));
}
fn get_contents(file: &str) -> String {
fn get_contents(file: &str) -> Result<String, Box<dyn Error>> {
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)
}

View File

@ -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::<String>("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::<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() {
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<dyn Error
} else {
contents = contents.replace('\n', "");
}
let decoded = decode(&contents)?.to_vec();
let decoded = decode(&contents)?.clone();
let output = String::from_utf8(decoded)?;
println!("{}", output.trim_end());
Ok(())
}
fn encode_base64(contents: &str, wrap: usize) {
let encoded = encode(contents.as_bytes())
encode(contents.as_bytes())
.chars()
.collect::<Vec<char>>()
.chunks(wrap)
.map(|c| c.iter().collect::<String>())
.collect::<Vec<String>>();
for line in &encoded {
println!("{line}");
}
.for_each(|line| println!("{line}"));
}
fn get_contents(file: &str) -> Result<String, Box<dyn Error>> {

View File

@ -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::<String>("color").map(|x| x.as_str()) {
let color = match matches.get_one::<String>("color").map(String::as_str) {
Some("always") => ColorChoice::Always,
Some("ansi") => ColorChoice::AlwaysAnsi,
Some("auto") => {
@ -143,22 +142,9 @@ fn head(
) -> Result<(), Box<dyn Error>> {
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 {

View File

@ -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},

View File

@ -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 - dont print anything.")

View File

@ -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))?,

View File

@ -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<dyn Error>> {
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<dyn Error>> {
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" => {