From 545fe7d887d5e162610474e07922169f7b78fd2b Mon Sep 17 00:00:00 2001 From: Yagiz Degirmenci <62724709+ycd@users.noreply.github.com> Date: Tue, 23 Mar 2021 11:42:05 +0300 Subject: [PATCH] feat(unexpand): move from getopts to clap (#1883) * feat: move unexpand to clap * chore: allow muliple files * test: add test fixture, test reading from a file * test: fix typo on file name, add test for multiple inputs * chore: use 'success()' instead of asserting * chore: delete unused variables * chore: use help instead of long_help, break long line --- src/uu/unexpand/Cargo.toml | 2 +- src/uu/unexpand/src/unexpand.rs | 119 +++++++++++------------- tests/by-util/test_unexpand.rs | 19 ++++ tests/fixtures/unexpand/with_spaces.txt | 2 + 4 files changed, 76 insertions(+), 66 deletions(-) create mode 100644 tests/fixtures/unexpand/with_spaces.txt diff --git a/src/uu/unexpand/Cargo.toml b/src/uu/unexpand/Cargo.toml index ec6967e21..d66d335bf 100644 --- a/src/uu/unexpand/Cargo.toml +++ b/src/uu/unexpand/Cargo.toml @@ -15,7 +15,7 @@ edition = "2018" path = "src/unexpand.rs" [dependencies] -getopts = "0.2.18" +clap = "2.33" unicode-width = "0.1.5" uucore = { version=">=0.0.7", package="uucore", path="../../uucore" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } diff --git a/src/uu/unexpand/src/unexpand.rs b/src/uu/unexpand/src/unexpand.rs index 59a2dc6a0..5b08c33cf 100644 --- a/src/uu/unexpand/src/unexpand.rs +++ b/src/uu/unexpand/src/unexpand.rs @@ -11,7 +11,7 @@ #[macro_use] extern crate uucore; - +use clap::{App, Arg}; use std::fs::File; use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Stdout, Write}; use std::str::from_utf8; @@ -19,6 +19,9 @@ use unicode_width::UnicodeWidthChar; static NAME: &str = "unexpand"; static VERSION: &str = env!("CARGO_PKG_VERSION"); +static USAGE: &str = "unexpand [OPTION]... [FILE]..."; +static SUMMARY: &str = "Convert blanks in each FILE to tabs, writing to standard output.\n + With no FILE, or when FILE is -, read standard input."; const DEFAULT_TABSTOP: usize = 8; @@ -46,6 +49,14 @@ fn tabstops_parse(s: String) -> Vec { nums } +mod options { + pub const FILE: &str = "file"; + pub const ALL: &str = "all"; + pub const FIRST_ONLY: &str = "first-only"; + pub const TABS: &str = "tabs"; + pub const NO_UTF8: &str = "no-utf8"; +} + struct Options { files: Vec, tabstops: Vec, @@ -54,20 +65,19 @@ struct Options { } impl Options { - fn new(matches: getopts::Matches) -> Options { - let tabstops = match matches.opt_str("t") { + fn new(matches: clap::ArgMatches) -> Options { + let tabstops = match matches.value_of(options::TABS) { None => vec![DEFAULT_TABSTOP], - Some(s) => tabstops_parse(s), + Some(s) => tabstops_parse(s.to_string()), }; - let aflag = (matches.opt_present("all") || matches.opt_present("tabs")) - && !matches.opt_present("first-only"); - let uflag = !matches.opt_present("U"); + let aflag = (matches.is_present(options::ALL) || matches.is_present(options::TABS)) + && !matches.is_present(options::FIRST_ONLY); + let uflag = !matches.is_present(options::NO_UTF8); - let files = if matches.free.is_empty() { - vec!["-".to_owned()] - } else { - matches.free + let files = match matches.value_of(options::FILE) { + Some(v) => vec![v.to_string()], + None => vec!["-".to_owned()], }; Options { @@ -82,60 +92,39 @@ impl Options { pub fn uumain(args: impl uucore::Args) -> i32 { let args = args.collect_str(); - let mut opts = getopts::Options::new(); - - opts.optflag( - "a", - "all", - "convert all blanks, instead of just initial blanks", - ); - opts.optflag( - "", - "first-only", - "convert only leading sequences of blanks (overrides -a)", - ); - opts.optopt( - "t", - "tabs", - "have tabs N characters apart instead of 8 (enables -a)", - "N", - ); - opts.optopt( - "t", - "tabs", - "use comma separated LIST of tab positions (enables -a)", - "LIST", - ); - opts.optflag( - "U", - "no-utf8", - "interpret input file as 8-bit ASCII rather than UTF-8", - ); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f), - }; - - if matches.opt_present("help") { - println!("{} {}\n", NAME, VERSION); - println!("Usage: {} [OPTION]... [FILE]...\n", NAME); - println!( - "{}", - opts.usage( - "Convert blanks in each FILE to tabs, writing to standard output.\n\ - With no FILE, or when FILE is -, read standard input." - ) - ); - return 0; - } - - if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = App::new(executable!()) + .name(NAME) + .version(VERSION) + .usage(USAGE) + .about(SUMMARY) + .arg(Arg::with_name(options::FILE).hidden(true).multiple(true)) + .arg( + Arg::with_name(options::ALL) + .short("a") + .long(options::ALL) + .help("convert all blanks, instead of just initial blanks") + .takes_value(false), + ) + .arg( + Arg::with_name(options::FIRST_ONLY) + .long(options::FIRST_ONLY) + .help("convert only leading sequences of blanks (overrides -a)") + .takes_value(false), + ) + .arg( + Arg::with_name(options::TABS) + .short("t") + .long(options::TABS) + .long_help("use comma separated LIST of tab positions or have tabs N characters apart instead of 8 (enables -a)") + .takes_value(true) + ) + .arg( + Arg::with_name(options::NO_UTF8) + .short("U") + .long(options::NO_UTF8) + .takes_value(false) + .help("interpret input file as 8-bit ASCII rather than UTF-8")) + .get_matches_from(args); unexpand(Options::new(matches)); diff --git a/tests/by-util/test_unexpand.rs b/tests/by-util/test_unexpand.rs index 93cc42d90..e8b880287 100644 --- a/tests/by-util/test_unexpand.rs +++ b/tests/by-util/test_unexpand.rs @@ -136,3 +136,22 @@ fn unexpand_spaces_after_fields() { .run() .stdout_is("\t\tA B C D\t\t A\t\n"); } + +#[test] +fn unexpand_read_from_file() { + new_ucmd!() + .arg("with_spaces.txt") + .arg("-t4") + .run() + .success(); +} + +#[test] +fn unexpand_read_from_two_file() { + new_ucmd!() + .arg("with_spaces.txt") + .arg("with_spaces.txt") + .arg("-t4") + .run() + .success(); +} diff --git a/tests/fixtures/unexpand/with_spaces.txt b/tests/fixtures/unexpand/with_spaces.txt new file mode 100644 index 000000000..3f39671a1 --- /dev/null +++ b/tests/fixtures/unexpand/with_spaces.txt @@ -0,0 +1,2 @@ + abc d e f g \t\t A + \ No newline at end of file