mirror of
https://github.com/uutils/coreutils
synced 2024-07-23 19:04:18 +00:00
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
This commit is contained in:
parent
5e2e2e8ab6
commit
545fe7d887
|
@ -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" }
|
||||
|
|
|
@ -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<usize> {
|
|||
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<String>,
|
||||
tabstops: Vec<usize>,
|
||||
|
@ -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));
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
2
tests/fixtures/unexpand/with_spaces.txt
vendored
Normal file
2
tests/fixtures/unexpand/with_spaces.txt
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
abc d e f g \t\t A
|
||||
|
Loading…
Reference in a new issue