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:
parent
18c2083c61
commit
9151410d08
2 changed files with 91 additions and 50 deletions
|
@ -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"
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue