mirror of
https://github.com/uutils/coreutils
synced 2024-12-13 23:02:38 +00:00
base32: move from getopts to clap
Note, I needed to change the error messages in one of the tests because getopt and clap have different error messages when not providing a default value
This commit is contained in:
parent
c3d7358df6
commit
5578ba6eed
5 changed files with 182 additions and 56 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "advapi32-sys"
|
||||
version = "0.2.0"
|
||||
|
@ -1653,6 +1655,7 @@ dependencies = [
|
|||
name = "uu_base32"
|
||||
version = "0.0.6"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"uucore",
|
||||
"uucore_procs",
|
||||
]
|
||||
|
|
|
@ -15,6 +15,7 @@ edition = "2018"
|
|||
path = "src/base32.rs"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33"
|
||||
uucore = { version=">=0.0.8", package="uucore", path="../../uucore", features = ["encoding"] }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use uucore::encoding::Format;
|
|||
|
||||
mod base_common;
|
||||
|
||||
static SYNTAX: &str = "[OPTION]... [FILE]";
|
||||
static SUMMARY: &str = "Base32 encode or decode FILE, or standard input, to standard output.";
|
||||
static LONG_HELP: &str = "
|
||||
With no FILE, or when FILE is -, read standard input.
|
||||
|
@ -24,11 +23,5 @@ static LONG_HELP: &str = "
|
|||
";
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||
base_common::execute(
|
||||
args.collect_str(),
|
||||
SYNTAX,
|
||||
SUMMARY,
|
||||
LONG_HELP,
|
||||
Format::Base32,
|
||||
)
|
||||
base_common::execute(args.collect_str(), SUMMARY, LONG_HELP, Format::Base32)
|
||||
}
|
||||
|
|
|
@ -11,60 +11,172 @@ use std::fs::File;
|
|||
use std::io::{stdin, stdout, BufReader, Read, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use uucore::encoding::{wrap_print, Data, Format};
|
||||
|
||||
pub fn execute(
|
||||
args: Vec<String>,
|
||||
syntax: &str,
|
||||
summary: &str,
|
||||
long_help: &str,
|
||||
format: Format,
|
||||
) -> i32 {
|
||||
let matches = app!(syntax, summary, long_help)
|
||||
.optflag("d", "decode", "decode data")
|
||||
.optflag(
|
||||
"i",
|
||||
"ignore-garbage",
|
||||
"when decoding, ignore non-alphabetic characters",
|
||||
)
|
||||
.optopt(
|
||||
"w",
|
||||
"wrap",
|
||||
"wrap encoded lines after COLS character (default 76, 0 to disable wrapping)",
|
||||
"COLS",
|
||||
)
|
||||
.parse(args);
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
let line_wrap = matches.opt_str("wrap").map(|s| match s.parse() {
|
||||
Ok(n) => n,
|
||||
Err(e) => {
|
||||
crash!(1, "invalid wrap size: ‘{}’: {}", s, e);
|
||||
pub mod options {
|
||||
pub static DECODE: &str = "decode";
|
||||
pub static WRAP: &str = "wrap";
|
||||
pub static IGNORE_GARBAGE: &str = "ignore-garbage";
|
||||
pub static FILE: &str = "file";
|
||||
}
|
||||
|
||||
struct Config {
|
||||
decode: bool,
|
||||
ignore_garbage: bool,
|
||||
wrap_cols: Option<usize>,
|
||||
to_read: Option<String>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
fn from(options: clap::ArgMatches) -> Config {
|
||||
let file: Option<String> = match options.values_of(options::FILE) {
|
||||
Some(mut values) => {
|
||||
if values.len() != 1 {
|
||||
crash!(3, "extra operand ‘{}’", values.nth(0).unwrap())
|
||||
}
|
||||
let name = values.nth(0).unwrap();
|
||||
if !Path::exists(Path::new(name)) {
|
||||
crash!(2, "{}: No such file or directory", name);
|
||||
}
|
||||
|
||||
if name == "-" {
|
||||
None // stdin
|
||||
} else {
|
||||
Some(name.to_owned())
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
let cols = match options.value_of(options::WRAP) {
|
||||
Some(num) => match num.parse::<usize>() {
|
||||
Ok(n) => Some(n),
|
||||
Err(e) => {
|
||||
crash!(1, "invalid wrap size: ‘{}’: {}", num, e);
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
Config {
|
||||
decode: options.is_present(options::DECODE),
|
||||
ignore_garbage: options.is_present(options::IGNORE_GARBAGE),
|
||||
wrap_cols: cols,
|
||||
to_read: file,
|
||||
}
|
||||
});
|
||||
let ignore_garbage = matches.opt_present("ignore-garbage");
|
||||
let decode = matches.opt_present("decode");
|
||||
|
||||
if matches.free.len() > 1 {
|
||||
show_usage_error!("extra operand ‘{}’", matches.free[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if matches.free.is_empty() || &matches.free[0][..] == "-" {
|
||||
let stdin_raw = stdin();
|
||||
handle_input(
|
||||
&mut stdin_raw.lock(),
|
||||
format,
|
||||
line_wrap,
|
||||
ignore_garbage,
|
||||
decode,
|
||||
);
|
||||
} else {
|
||||
let path = Path::new(matches.free[0].as_str());
|
||||
let file_buf = safe_unwrap!(File::open(&path));
|
||||
let mut input = BufReader::new(file_buf);
|
||||
handle_input(&mut input, format, line_wrap, ignore_garbage, decode);
|
||||
fn get_usage() -> String {
|
||||
format!("{0} [OPTION]... [FILE]", executable!())
|
||||
}
|
||||
|
||||
pub fn execute(args: Vec<String>, _summary: &str, long_help: &str, format: Format) -> i32 {
|
||||
let usage = get_usage();
|
||||
let app = App::new(executable!())
|
||||
.version(VERSION)
|
||||
.usage(&usage[..])
|
||||
.about(long_help)
|
||||
// Format arguments.
|
||||
.arg(
|
||||
Arg::with_name(options::DECODE)
|
||||
.short("d")
|
||||
.long(options::DECODE)
|
||||
.help("decode data"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(options::IGNORE_GARBAGE)
|
||||
.short("i")
|
||||
.long(options::IGNORE_GARBAGE)
|
||||
.help("when decoding, ignore non-alphabetic characters"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name(options::WRAP)
|
||||
.short("w")
|
||||
.long(options::WRAP)
|
||||
.takes_value(true)
|
||||
.help(
|
||||
"wrap encoded lines after COLS character (default 76, 0 to disable wrapping)",
|
||||
),
|
||||
)
|
||||
// "multiple" arguments are used to check whether there is more than one
|
||||
// file passed in.
|
||||
.arg(Arg::with_name(options::FILE).index(1).multiple(true));
|
||||
|
||||
let config: Config = Config::from(app.get_matches_from(args));
|
||||
match config.to_read {
|
||||
// Read from file.
|
||||
Some(name) => {
|
||||
let file_buf = safe_unwrap!(File::open(Path::new(&name)));
|
||||
let mut input = BufReader::new(file_buf);
|
||||
handle_input(
|
||||
&mut input,
|
||||
format,
|
||||
config.wrap_cols,
|
||||
config.ignore_garbage,
|
||||
config.decode,
|
||||
);
|
||||
}
|
||||
// stdin
|
||||
None => {
|
||||
handle_input(
|
||||
&mut stdin().lock(),
|
||||
format,
|
||||
config.wrap_cols,
|
||||
config.ignore_garbage,
|
||||
config.decode,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// let matches = app!(syntax, summary, long_help)
|
||||
// .optflag("d", "decode", "decode data")
|
||||
// .optflag(
|
||||
// "i",
|
||||
// "ignore-garbage",
|
||||
// "when decoding, ignore non-alphabetic characters",
|
||||
// )
|
||||
// .optopt(
|
||||
// "w",
|
||||
// "wrap",
|
||||
// "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)",
|
||||
// "COLS",
|
||||
// )
|
||||
// .parse(args);
|
||||
|
||||
// let line_wrap = matches.opt_str("wrap").map(|s| match s.parse() {
|
||||
// Ok(n) => n,
|
||||
// Err(e) => {
|
||||
// crash!(1, "invalid wrap size: ‘{}’: {}", s, e);
|
||||
// }
|
||||
// });
|
||||
// let ignore_garbage = matches.opt_present("ignore-garbage");
|
||||
// let decode = matches.opt_present("decode");
|
||||
|
||||
// if matches.free.len() > 1 {
|
||||
// show_usage_error!("extra operand ‘{}’", matches.free[0]);
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
// if matches.free.is_empty() || &matches.free[0][..] == "-" {
|
||||
// let stdin_raw = stdin();
|
||||
// handle_input(
|
||||
// &mut stdin_raw.lock(),
|
||||
// format,
|
||||
// line_wrap,
|
||||
// ignore_garbage,
|
||||
// decode,
|
||||
// );
|
||||
// } else {
|
||||
// let path = Path::new(matches.free[0].as_str());
|
||||
// let file_buf = safe_unwrap!(File::open(&path));
|
||||
// let mut input = BufReader::new(file_buf);
|
||||
//
|
||||
// };
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
|
|
|
@ -71,8 +71,7 @@ fn test_wrap() {
|
|||
fn test_wrap_no_arg() {
|
||||
for wrap_param in vec!["-w", "--wrap"] {
|
||||
new_ucmd!().arg(wrap_param).fails().stderr_only(format!(
|
||||
"base32: error: Argument to option '{}' missing\n",
|
||||
if wrap_param == "-w" { "w" } else { "wrap" }
|
||||
"error: The argument '--wrap <wrap>\' requires a value but none was supplied\n\nUSAGE:\n base32 [OPTION]... [FILE]\n\nFor more information try --help"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -87,3 +86,21 @@ fn test_wrap_bad_arg() {
|
|||
.stderr_only("base32: error: invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_base32_extra_operand() {
|
||||
// Expect a failure when multiple files are specified.
|
||||
new_ucmd!()
|
||||
.arg("a.txt")
|
||||
.arg("a.txt")
|
||||
.fails()
|
||||
.stderr_only("base32: error: extra operand ‘a.txt’");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_base32_file_not_found() {
|
||||
new_ucmd!()
|
||||
.arg("a.txt")
|
||||
.fails()
|
||||
.stderr_only("base32: error: a.txt: No such file or directory");
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue