Compare commits

...

2 commits

Author SHA1 Message Date
bf4e7b00d7 fix: only read from stdin if it's not a terminal #17
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m14s
2024-05-13 17:01:38 +02:00
f93e5f6c4c fix: parse first then add numbers from stdin #16
All checks were successful
cargo devel CI / cargo CI (push) Successful in 1m15s
2024-05-13 16:55:39 +02:00
2 changed files with 53 additions and 25 deletions

View file

@ -68,10 +68,21 @@ pub struct FormatOptions {
#[arg(short = 'z', long)] #[arg(short = 'z', long)]
/// format to base32 /// format to base32
base32: bool, base32: bool,
#[clap(value_parser=numf_parser::<NumberType>, required=true)] #[clap(value_parser=numf_parser::<NumberType>, required=false)]
/// at least one number that should be formatted /// at least one number that should be formatted
/// ///
/// supports either base 10 or base 16 inputs (with 0xaaaa) /// Any of the [Formats](Format::format) are supported, but the prefixes are needed for formats
/// other than decimal.
///
/// Formats:
///
/// - '0x' - Hexadecimal
/// - '0b' - Binary
/// - '0o' - Octal
/// - '0s' - Base64
/// - '032s' - Base32
///
/// The numbers may be left empty at first, if numbers are provided with the stdin.
numbers: Vec<NumberType>, numbers: Vec<NumberType>,
} }
@ -142,6 +153,11 @@ impl FormatOptions {
pub fn set_prefix(&mut self, value: bool) { pub fn set_prefix(&mut self, value: bool) {
self.prefix = value; self.prefix = value;
} }
/// manually add a number
pub fn push_number(&mut self, value: NumberType) {
self.numbers.push(value)
}
} }
impl Default for FormatOptions { impl Default for FormatOptions {

View file

@ -3,41 +3,53 @@
//! This binary should just take any amount of numbers and print them out formatted to some other //! This binary should just take any amount of numbers and print them out formatted to some other
//! system. //! system.
use std::io::Read; use std::io::{IsTerminal, Read};
use std::process::exit; use std::process::exit;
use clap::Parser; use clap::{CommandFactory, Parser};
mod format; mod format;
use format::*; use format::*;
use numf::format::numf_parser;
fn main() { fn main() {
// try to read from stdin first, appending the numbers we read to the FormatOptions // try to read from stdin first, appending the numbers we read to the FormatOptions
let mut args: Vec<String> = std::env::args_os() let mut options = FormatOptions::parse();
.map(|x| x.into_string().unwrap())
.collect();
let mut stdin_nums = Vec::new(); let mut stdin_nums = Vec::new();
match std::io::stdin().lock().read_to_end(&mut stdin_nums) { let stdin = std::io::stdin();
Ok(_) => { if !stdin.is_terminal() {
let whole: String = match String::from_utf8(stdin_nums) { match stdin.lock().read_to_end(&mut stdin_nums) {
Ok(r) => r, Ok(_) => {
Err(e) => { let whole: String = match String::from_utf8(stdin_nums) {
eprintln!("stdin for this program only accepts text: {e:#?}"); Ok(r) => r,
exit(1); Err(e) => {
eprintln!("stdin for this program only accepts text: {e:#?}");
exit(1);
}
};
let split = whole.split_whitespace();
for s in split {
let number = match numf_parser(s) {
Ok(n) => n,
Err(e) => {
eprintln!("could not parse number from stdin: {e:#?}");
exit(2);
}
};
options.push_number(number)
} }
};
let split = whole.split_whitespace();
for s in split {
args.push(s.to_string());
} }
} Err(e) => {
Err(e) => { eprintln!("could not read from stdin: {e:#?}");
eprintln!("could not read from stdin: {e:#?}"); exit(2);
exit(2); }
} };
}; }
let options = FormatOptions::parse_from(args); if options.numbers().is_empty() {
format!("{}", FormatOptions::command().render_usage());
exit(1);
}
let mut out: Vec<String> = Vec::new(); let mut out: Vec<String> = Vec::new();