diff options
Diffstat (limited to 'src/cli.rs')
-rw-r--r-- | src/cli.rs | 105 |
1 files changed, 18 insertions, 87 deletions
@@ -1,36 +1,14 @@ -use std::{ - env, - io::{BufRead, BufReader, Write}, -}; +use std::env; use crate::{Error, Input, Result}; -const HELP: &str = r#"Usage: cat [OPTION]... [FILE]... -Concatenate FILE(s) to standard output. - -With no FILE, or when FILE is -, read standard input. - - -A, --show-all equivalent to -vET - -b, --number-nonblank number nonempty output lines, overrides -n - -e equivalent to -vE - -E, --show-ends display $ at end of each line - -n, --number number all output lines - -s, --squeeze-blank suppress repeated empty output lines - -t equivalent to -vT - -T, --show-tabs display TAB characters as ^I - -u (ignored) - -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB - --help display this help and exit - --version output version information and exit - -Examples: - cat f - g Output f's contents, then standard input, then g's contents. - cat Copy standard input to standard output."#; +// NOTE: I assumed I should keep this "DIY". I would most likely use some "de facto" external +// libraries like `clap`, `serde`, ect. #[derive(Debug, Default)] pub struct Cli { - files: Vec<Input>, - opts: Opts, + pub files: Vec<Input>, + pub opts: Opts, } impl Cli { @@ -46,87 +24,40 @@ impl Cli { }; Ok(cli) }) - } - - pub fn run(mut self) -> Result<()> { - if self.opts.help { - println!("{}", HELP); - std::process::exit(0); - } - if self.opts.version { - println!("cat (ported to Rust) {}", env!("CARGO_PKG_VERSION")); - std::process::exit(0); - } - - if self.files.is_empty() { - self.files.push(Input::Stdin); - } - - let stdout = std::io::stdout(); - let mut writer = stdout.lock(); - - for file in self.files.into_iter() { - let reader = BufReader::new(file.reader()?); - - let mut nonblank_line_nr = 0; - - for (index, res) in reader.lines().enumerate() { - let mut line = res?; - - if line.is_empty() && self.opts.squeeze_blank { - continue; - } - - if self.opts.show_ends { - line.push('$'); - } - - if self.opts.show_tabs { - line = line.replace('\t', "^I"); - } - - if self.opts.number_nonblank { - if !line.is_empty() { - nonblank_line_nr += 1; - write!(writer, "{:>6} ", nonblank_line_nr)?; - } - } else if self.opts.number { - write!(writer, "{:>6} ", index + 1)?; + .map(|mut cli| { + if cli.files.is_empty() { + cli.files.push(Input::Stdin); } - - writeln!(writer, "{}", line)?; - } - } - - Ok(()) + cli + }) } } #[derive(Debug, Default)] pub struct Opts { /// number nonempty output lines, overrides -n - number_nonblank: bool, + pub number_nonblank: bool, /// display $ at end of each line - show_ends: bool, + pub show_ends: bool, /// number all output lines - number: bool, + pub number: bool, /// suppress repeated empty output lines - squeeze_blank: bool, + pub squeeze_blank: bool, /// display TAB characters as ^I - show_tabs: bool, + pub show_tabs: bool, /// use ^ and M- notation, except for LFD and TAB - show_nonprinting: bool, + pub show_nonprinting: bool, /// display help and exit - help: bool, + pub help: bool, /// output version information and exit - version: bool, + pub version: bool, } impl Opts { |