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

csplit: move from getopts to clap (#1995)

This commit is contained in:
Sivachandran 2021-04-03 01:44:56 +05:30 committed by GitHub
parent 18c2083c61
commit 9151410d08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 91 additions and 50 deletions

View file

@ -15,7 +15,7 @@ edition = "2018"
path = "src/csplit.rs" path = "src/csplit.rs"
[dependencies] [dependencies]
getopts = "0.2.17" clap = "2.33"
thiserror = "1.0" thiserror = "1.0"
regex = "1.0.0" regex = "1.0.0"
glob = "0.2.11" glob = "0.2.11"

View file

@ -2,7 +2,7 @@
#[macro_use] #[macro_use]
extern crate uucore; extern crate uucore;
use getopts::Matches; use clap::{App, Arg, ArgMatches};
use regex::Regex; use regex::Regex;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::io::{self, BufReader}; use std::io::{self, BufReader};
@ -18,17 +18,25 @@ mod splitname;
use crate::csplit_error::CsplitError; use crate::csplit_error::CsplitError;
use crate::splitname::SplitName; use crate::splitname::SplitName;
static SYNTAX: &str = "[OPTION]... FILE PATTERN..."; static VERSION: &str = env!("CARGO_PKG_VERSION");
static SUMMARY: &str = "split a file into sections determined by context lines"; static SUMMARY: &str = "split a file into sections determined by context lines";
static LONG_HELP: &str = "Output pieces of FILE separated by PATTERN(s) to files 'xx00', 'xx01', ..., and output byte counts of each piece to standard output."; static LONG_HELP: &str = "Output pieces of FILE separated by PATTERN(s) to files 'xx00', 'xx01', ..., and output byte counts of each piece to standard output.";
static SUFFIX_FORMAT_OPT: &str = "suffix-format"; mod options {
static SUPPRESS_MATCHED_OPT: &str = "suppress-matched"; pub const SUFFIX_FORMAT: &str = "suffix-format";
static DIGITS_OPT: &str = "digits"; pub const SUPPRESS_MATCHED: &str = "suppress-matched";
static PREFIX_OPT: &str = "prefix"; pub const DIGITS: &str = "digits";
static KEEP_FILES_OPT: &str = "keep-files"; pub const PREFIX: &str = "prefix";
static QUIET_OPT: &str = "quiet"; pub const KEEP_FILES: &str = "keep-files";
static ELIDE_EMPTY_FILES_OPT: &str = "elide-empty-files"; pub const QUIET: &str = "quiet";
pub const ELIDE_EMPTY_FILES: &str = "elide-empty-files";
pub const FILE: &str = "file";
pub const PATTERN: &str = "pattern";
}
fn get_usage() -> String {
format!("{0} [OPTION]... FILE PATTERN...", executable!())
}
/// Command line options for csplit. /// Command line options for csplit.
pub struct CsplitOptions { pub struct CsplitOptions {
@ -40,19 +48,19 @@ pub struct CsplitOptions {
} }
impl CsplitOptions { impl CsplitOptions {
fn new(matches: &Matches) -> CsplitOptions { fn new(matches: &ArgMatches) -> CsplitOptions {
let keep_files = matches.opt_present(KEEP_FILES_OPT); let keep_files = matches.is_present(options::KEEP_FILES);
let quiet = matches.opt_present(QUIET_OPT); let quiet = matches.is_present(options::QUIET);
let elide_empty_files = matches.opt_present(ELIDE_EMPTY_FILES_OPT); let elide_empty_files = matches.is_present(options::ELIDE_EMPTY_FILES);
let suppress_matched = matches.opt_present(SUPPRESS_MATCHED_OPT); let suppress_matched = matches.is_present(options::SUPPRESS_MATCHED);
CsplitOptions { CsplitOptions {
split_name: crash_if_err!( split_name: crash_if_err!(
1, 1,
SplitName::new( SplitName::new(
matches.opt_str(PREFIX_OPT), matches.value_of(options::PREFIX).map(str::to_string),
matches.opt_str(SUFFIX_FORMAT_OPT), matches.value_of(options::SUFFIX_FORMAT).map(str::to_string),
matches.opt_str(DIGITS_OPT) matches.value_of(options::DIGITS).map(str::to_string)
) )
), ),
keep_files, keep_files,
@ -702,45 +710,78 @@ mod tests {
} }
pub fn uumain(args: impl uucore::Args) -> i32 { pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let args = args.collect_str(); let args = args.collect_str();
let matches = app!(SYNTAX, SUMMARY, LONG_HELP) let matches = App::new(executable!())
.optopt( .version(VERSION)
"b", .about(SUMMARY)
SUFFIX_FORMAT_OPT, .usage(&usage[..])
"use sprintf FORMAT instead of %02d", .arg(
"FORMAT", Arg::with_name(options::SUFFIX_FORMAT)
.short("b")
.long(options::SUFFIX_FORMAT)
.value_name("FORMAT")
.help("use sprintf FORMAT instead of %02d"),
) )
.optopt("f", PREFIX_OPT, "use PREFIX instead of 'xx'", "PREFIX") .arg(
.optflag("k", KEEP_FILES_OPT, "do not remove output files on errors") Arg::with_name(options::PREFIX)
.optflag( .short("f")
"", .long(options::PREFIX)
SUPPRESS_MATCHED_OPT, .value_name("PREFIX")
"suppress the lines matching PATTERN", .help("use PREFIX instead of 'xx'"),
) )
.optopt( .arg(
"n", Arg::with_name(options::KEEP_FILES)
DIGITS_OPT, .short("k")
"use specified number of digits instead of 2", .long(options::KEEP_FILES)
"DIGITS", .help("do not remove output files on errors"),
) )
.optflag("s", QUIET_OPT, "do not print counts of output file sizes") .arg(
.optflag("z", ELIDE_EMPTY_FILES_OPT, "remove empty output files") Arg::with_name(options::SUPPRESS_MATCHED)
.parse(args); .long(options::SUPPRESS_MATCHED)
.help("suppress the lines matching PATTERN"),
)
.arg(
Arg::with_name(options::DIGITS)
.short("n")
.long(options::DIGITS)
.value_name("DIGITS")
.help("use specified number of digits instead of 2"),
)
.arg(
Arg::with_name(options::QUIET)
.short("s")
.long(options::QUIET)
.visible_alias("silent")
.help("do not print counts of output file sizes"),
)
.arg(
Arg::with_name(options::ELIDE_EMPTY_FILES)
.short("z")
.long(options::ELIDE_EMPTY_FILES)
.help("remove empty output files"),
)
.arg(Arg::with_name(options::FILE).hidden(true).required(true))
.arg(
Arg::with_name(options::PATTERN)
.hidden(true)
.multiple(true)
.required(true),
)
.after_help(LONG_HELP)
.get_matches_from(args);
// check for mandatory arguments
if matches.free.is_empty() {
show_error!("missing operand");
exit!(1);
}
if matches.free.len() == 1 {
show_error!("missing operand after '{}'", matches.free[0]);
exit!(1);
}
// get the patterns to split on
let patterns = return_if_err!(1, patterns::get_patterns(&matches.free[1..]));
// get the file to split // get the file to split
let file_name: &str = &matches.free[0]; let file_name = matches.value_of(options::FILE).unwrap();
// get the patterns to split on
let patterns: Vec<String> = matches
.values_of(options::PATTERN)
.unwrap()
.map(str::to_string)
.collect();
let patterns = return_if_err!(1, patterns::get_patterns(&patterns[..]));
let options = CsplitOptions::new(&matches); let options = CsplitOptions::new(&matches);
if file_name == "-" { if file_name == "-" {
let stdin = io::stdin(); let stdin = io::stdin();