summaryrefslogtreecommitdiffstats
path: root/src/cli.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cli.rs')
-rw-r--r--src/cli.rs105
1 files changed, 18 insertions, 87 deletions
diff --git a/src/cli.rs b/src/cli.rs
index bab0b84..12f1cfc 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -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 {