1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

tsort: move from getopts to clap (#1867)

This commit is contained in:
Yagiz Degirmenci 2021-03-22 20:16:28 +03:00 committed by GitHub
parent f593cf53b2
commit d86ee34bc6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 33 deletions

View file

@ -15,7 +15,7 @@ edition = "2018"
path = "src/tsort.rs"
[dependencies]
getopts = "0.2.18"
clap= "2.33"
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -9,49 +9,35 @@
#[macro_use]
extern crate uucore;
use clap::{App, Arg};
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::{stdin, BufRead, BufReader, Read};
use std::path::Path;
static NAME: &str = "tsort";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static SUMMARY: &str = "Topological sort the strings in FILE.
Strings are defined as any sequence of tokens separated by whitespace (tab, space, or newline).
If FILE is not passed in, stdin is used instead.";
static USAGE: &str = "tsort [OPTIONS] FILE";
mod options {
pub const FILE: &str = "file";
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args.collect_str();
let mut opts = getopts::Options::new();
let matches = App::new(executable!())
.version(VERSION)
.usage(USAGE)
.about(SUMMARY)
.arg(Arg::with_name(options::FILE).hidden(true))
.get_matches_from(args);
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("h") {
println!("{} {}", NAME, VERSION);
println!();
println!("Usage:");
println!(" {} [OPTIONS] FILE", NAME);
println!();
println!("{}", opts.usage("Topological sort the strings in FILE. Strings are defined as any sequence of tokens separated by whitespace (tab, space, or newline). If FILE is not passed in, stdin is used instead."));
return 0;
}
if matches.opt_present("V") {
println!("{} {}", NAME, VERSION);
return 0;
}
let files = matches.free.clone();
let input = if files.len() > 1 {
crash!(1, "{}, extra operand '{}'", NAME, matches.free[1]);
} else if files.is_empty() {
"-".to_owned()
} else {
files[0].clone()
let input = match matches.value_of(options::FILE) {
Some(v) => v,
None => "-",
};
let mut stdin_buf;

View file

@ -15,3 +15,36 @@ fn test_sort_self_loop() {
.succeeds()
.stdout_only("first\nsecond\n");
}
#[test]
fn test_no_such_file() {
let result = new_ucmd!().arg("invalid_file_txt").run();
assert_eq!(true, result.stderr.contains("No such file or directory"));
}
#[test]
fn test_version_flag() {
let version_short = new_ucmd!().arg("-V").run();
let version_long = new_ucmd!().arg("--version").run();
assert_eq!(version_short.stdout, version_long.stdout);
}
#[test]
fn test_help_flag() {
let help_short = new_ucmd!().arg("-h").run();
let help_long = new_ucmd!().arg("--help").run();
assert_eq!(help_short.stdout, help_long.stdout);
}
#[test]
fn test_multiple_arguments() {
let result = new_ucmd!()
.arg("call_graph.txt")
.arg("invalid_file.txt")
.run();
assert_eq!(true, result.stderr.contains("error: Found argument 'invalid_file.txt' which wasn't expected, or isn't valid in this context"))
}