Head - allow head -1 type arguments

This commit is contained in:
Nathan Fisher 2022-12-29 23:20:55 -05:00
parent 2995e4a3cb
commit 2510f80303
2 changed files with 42 additions and 10 deletions

View File

@ -32,6 +32,7 @@ impl Bootstrap {
.help("Install completions for all supported shells") .help("Install completions for all supported shells")
.short('a') .short('a')
.long("all") .long("all")
.conflicts_with_all(["bash", "fish", "nu", "pwsh", "zsh"])
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
Arg::new("bash") Arg::new("bash")
.help("Bash shell completions") .help("Bash shell completions")
@ -88,6 +89,7 @@ impl Bootstrap {
.help("Install completions for all supported shells") .help("Install completions for all supported shells")
.short('a') .short('a')
.long("all") .long("all")
.exclusive(true)
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
Arg::new("bash") Arg::new("bash")
.help("Bash shell completions") .help("Bash shell completions")

View File

@ -5,7 +5,7 @@ use std::{
error::Error, error::Error,
fs, fs,
io::{self, stdin, Read}, io::{self, stdin, Read},
process, process, env,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -31,9 +31,8 @@ impl Cmd for Head {
.about("Display first lines of a file") .about("Display first lines of a file")
.long_about( .long_about(
"Print the first 10 lines of each FILE to standard output.\n\ "Print the first 10 lines of each FILE to standard output.\n\
With more than one FILE, precede each with a header giving the file name.\n\ With more than one FILE, precede each with a header giving the file name.\n\n\
With no FILE, or when FILE is -, read standard input.\n\ With no FILE, or when FILE is -, read standard input."
Mandatory arguments to long options are mandatory for short options too."
) )
.args([ .args([
Arg::new("FILES") Arg::new("FILES")
@ -58,18 +57,52 @@ impl Cmd for Head {
.help("Count n number of lines (or bytes if -c is specified).") .help("Count n number of lines (or bytes if -c is specified).")
.short('n') .short('n')
.long("lines") .long("lines")
.default_value("10")
.allow_negative_numbers(false) .allow_negative_numbers(false)
.value_parser(value_parser!(usize)) .conflicts_with("num")
.value_parser(value_parser!(usize)),
Arg::new("num")
.short('1')
.short_aliases(['2', '3', '4', '5', '6', '7', '8', '9'])
.hide(true)
.action(ArgAction::Append)
]) ])
} }
fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box<dyn Error>> { fn run(&self, matches: Option<&ArgMatches>) -> Result<(), Box<dyn Error>> {
let args: Vec<_> = env::args().collect();
let idx = match crate::progname() {
Some(s) if s.as_str() == "head" => 1,
_ => 2,
};
let mut lines = 10;
if args.len() > idx {
let arg1 = &args[idx];
if arg1.starts_with('-') && arg1.len() > 1 {
let lines: usize = arg1[1..].parse()?;
let files: Vec<_> = if args.len() > idx + 1 {
args[idx + 1..].iter().map(|x| x.as_str()).collect()
} else {
vec!["-"]
};
for file in &files {
head(
&file,
lines,
false,
false,
);
}
return Ok(());
}
}
let matches = if let Some(m) = matches { let matches = if let Some(m) = matches {
m m
} else { } else {
return Err(io::Error::new(io::ErrorKind::Other, "No input").into()); return Err(io::Error::new(io::ErrorKind::Other, "No input").into());
}; };
if let Some(l) = matches.get_one("LINES") {
lines = *l;
}
let files = match matches.get_many::<String>("FILES") { let files = match matches.get_many::<String>("FILES") {
Some(c) => c.map(std::string::ToString::to_string).collect(), Some(c) => c.map(std::string::ToString::to_string).collect(),
None => vec!["-".to_string()], None => vec!["-".to_string()],
@ -82,10 +115,7 @@ impl Cmd for Head {
} }
head( head(
&file, &file,
match matches.get_one("LINES") { lines,
Some(c) => *c,
None => 10,
},
header, header,
matches.get_flag("BYTES"), matches.get_flag("BYTES"),
); );