1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

uutils: move clap::App creation to separate functions

This commit is contained in:
Michael Debertol 2021-06-15 15:35:02 +02:00
parent 5981351222
commit 0531153fa6
105 changed files with 3571 additions and 3253 deletions

7
Cargo.lock generated
View file

@ -1959,6 +1959,7 @@ dependencies = [
name = "uu_expr"
version = "0.0.6"
dependencies = [
"clap",
"libc",
"num-bigint",
"num-traits",
@ -1986,6 +1987,7 @@ dependencies = [
name = "uu_false"
version = "0.0.6"
dependencies = [
"clap",
"uucore",
"uucore_procs",
]
@ -2051,6 +2053,7 @@ dependencies = [
name = "uu_hostid"
version = "0.0.6"
dependencies = [
"clap",
"libc",
"uucore",
"uucore_procs",
@ -2327,6 +2330,7 @@ name = "uu_pr"
version = "0.0.6"
dependencies = [
"chrono",
"clap",
"getopts",
"itertools 0.10.0",
"quick-error 2.0.1",
@ -2349,6 +2353,7 @@ dependencies = [
name = "uu_printf"
version = "0.0.6"
dependencies = [
"clap",
"itertools 0.8.2",
"uucore",
"uucore_procs",
@ -2585,6 +2590,7 @@ dependencies = [
name = "uu_test"
version = "0.0.6"
dependencies = [
"clap",
"libc",
"redox_syscall 0.1.57",
"uucore",
@ -2628,6 +2634,7 @@ dependencies = [
name = "uu_true"
version = "0.0.6"
dependencies = [
"clap",
"uucore",
"uucore_procs",
]

View file

@ -17,13 +17,16 @@ static ABOUT: &str = "Display machine architecture";
static SUMMARY: &str = "Determine architecture name for current machine.";
pub fn uumain(args: impl uucore::Args) -> i32 {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(SUMMARY)
.get_matches_from(args);
uu_app().get_matches_from(args);
let uts = return_if_err!(1, PlatformInfo::new());
println!("{}", uts.machine().trim());
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(SUMMARY)
}

View file

@ -10,6 +10,7 @@ extern crate uucore;
use std::io::{stdin, Read};
use clap::App;
use uucore::encoding::Format;
pub mod base_common;
@ -56,3 +57,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
base_common::base_app(executable!(), VERSION, ABOUT)
}

View file

@ -78,10 +78,17 @@ pub fn parse_base_cmd_args(
about: &str,
usage: &str,
) -> Result<Config, String> {
let app = App::new(name)
let app = base_app(name, version, about).usage(usage);
let arg_list = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
Config::from(app.get_matches_from(arg_list))
}
pub fn base_app<'a>(name: &str, version: &'a str, about: &'a str) -> App<'static, 'a> {
App::new(name)
.version(version)
.about(about)
.usage(usage)
// Format arguments.
.arg(
Arg::with_name(options::DECODE)
@ -106,11 +113,7 @@ pub fn parse_base_cmd_args(
)
// "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 arg_list = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
Config::from(app.get_matches_from(arg_list))
.arg(Arg::with_name(options::FILE).index(1).multiple(true))
}
pub fn get_input<'a>(config: &Config, stdin_ref: &'a Stdin) -> Box<dyn Read + 'a> {

View file

@ -10,6 +10,7 @@
extern crate uucore;
use uu_base32::base_common;
pub use uu_base32::uu_app;
use uucore::encoding::Format;

View file

@ -40,31 +40,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
//
// Argument parsing
//
let matches = App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.usage(&usage[..])
.arg(
Arg::with_name(options::MULTIPLE)
.short("a")
.long(options::MULTIPLE)
.help("support multiple arguments and treat each as a NAME"),
)
.arg(Arg::with_name(options::NAME).multiple(true).hidden(true))
.arg(
Arg::with_name(options::SUFFIX)
.short("s")
.long(options::SUFFIX)
.value_name("SUFFIX")
.help("remove a trailing SUFFIX; implies -a"),
)
.arg(
Arg::with_name(options::ZERO)
.short("z")
.long(options::ZERO)
.help("end each output line with NUL, not newline"),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
// too few arguments
if !matches.is_present(options::NAME) {
@ -116,6 +92,32 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.arg(
Arg::with_name(options::MULTIPLE)
.short("a")
.long(options::MULTIPLE)
.help("support multiple arguments and treat each as a NAME"),
)
.arg(Arg::with_name(options::NAME).multiple(true).hidden(true))
.arg(
Arg::with_name(options::SUFFIX)
.short("s")
.long(options::SUFFIX)
.value_name("SUFFIX")
.help("remove a trailing SUFFIX; implies -a"),
)
.arg(
Arg::with_name(options::ZERO)
.short("z")
.long(options::ZERO)
.help("end each output line with NUL, not newline"),
)
}
fn basename(fullname: &str, suffix: &str) -> String {
// Remove all platform-specific path separators from the end
let path = fullname.trim_end_matches(is_separator);

View file

@ -169,7 +169,65 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let number_mode = if matches.is_present(options::NUMBER_NONBLANK) {
NumberingMode::NonEmpty
} else if matches.is_present(options::NUMBER) {
NumberingMode::All
} else {
NumberingMode::None
};
let show_nonprint = vec![
options::SHOW_ALL.to_owned(),
options::SHOW_NONPRINTING_ENDS.to_owned(),
options::SHOW_NONPRINTING_TABS.to_owned(),
options::SHOW_NONPRINTING.to_owned(),
]
.iter()
.any(|v| matches.is_present(v));
let show_ends = vec![
options::SHOW_ENDS.to_owned(),
options::SHOW_ALL.to_owned(),
options::SHOW_NONPRINTING_ENDS.to_owned(),
]
.iter()
.any(|v| matches.is_present(v));
let show_tabs = vec![
options::SHOW_ALL.to_owned(),
options::SHOW_TABS.to_owned(),
options::SHOW_NONPRINTING_TABS.to_owned(),
]
.iter()
.any(|v| matches.is_present(v));
let squeeze_blank = matches.is_present(options::SQUEEZE_BLANK);
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
let options = OutputOptions {
show_ends,
number: number_mode,
show_nonprint,
show_tabs,
squeeze_blank,
};
let success = cat_files(files, &options).is_ok();
if success {
0
} else {
1
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(SYNTAX)
@ -229,61 +287,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.long(options::SHOW_NONPRINTING)
.help("use ^ and M- notation, except for LF (\\n) and TAB (\\t)"),
)
.get_matches_from(args);
let number_mode = if matches.is_present(options::NUMBER_NONBLANK) {
NumberingMode::NonEmpty
} else if matches.is_present(options::NUMBER) {
NumberingMode::All
} else {
NumberingMode::None
};
let show_nonprint = vec![
options::SHOW_ALL.to_owned(),
options::SHOW_NONPRINTING_ENDS.to_owned(),
options::SHOW_NONPRINTING_TABS.to_owned(),
options::SHOW_NONPRINTING.to_owned(),
]
.iter()
.any(|v| matches.is_present(v));
let show_ends = vec![
options::SHOW_ENDS.to_owned(),
options::SHOW_ALL.to_owned(),
options::SHOW_NONPRINTING_ENDS.to_owned(),
]
.iter()
.any(|v| matches.is_present(v));
let show_tabs = vec![
options::SHOW_ALL.to_owned(),
options::SHOW_TABS.to_owned(),
options::SHOW_NONPRINTING_TABS.to_owned(),
]
.iter()
.any(|v| matches.is_present(v));
let squeeze_blank = matches.is_present(options::SQUEEZE_BLANK);
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
let options = OutputOptions {
show_ends,
number: number_mode,
show_nonprint,
show_tabs,
squeeze_blank,
};
let success = cat_files(files, &options).is_ok();
if success {
0
} else {
1
}
}
fn cat_handle<R: Read>(

View file

@ -73,84 +73,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let mut app = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::verbosity::CHANGES)
.short("c")
.long(options::verbosity::CHANGES)
.help("like verbose but report only when a change is made"),
)
.arg(
Arg::with_name(options::verbosity::SILENT)
.short("f")
.long(options::verbosity::SILENT),
)
.arg(
Arg::with_name(options::verbosity::QUIET)
.long(options::verbosity::QUIET)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(options::verbosity::VERBOSE)
.short("v")
.long(options::verbosity::VERBOSE)
.help("output a diagnostic for every file processed"),
)
.arg(
Arg::with_name(options::dereference::DEREFERENCE)
.long(options::dereference::DEREFERENCE),
)
.arg(
Arg::with_name(options::dereference::NO_DEREFERENCE)
.short("h")
.long(options::dereference::NO_DEREFERENCE)
.help(
"affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)",
),
)
.arg(
Arg::with_name(options::preserve_root::PRESERVE)
.long(options::preserve_root::PRESERVE)
.help("fail to operate recursively on '/'"),
)
.arg(
Arg::with_name(options::preserve_root::NO_PRESERVE)
.long(options::preserve_root::NO_PRESERVE)
.help("do not treat '/' specially (the default)"),
)
.arg(
Arg::with_name(options::REFERENCE)
.long(options::REFERENCE)
.value_name("RFILE")
.help("use RFILE's group rather than specifying GROUP values")
.takes_value(true)
.multiple(false),
)
.arg(
Arg::with_name(options::RECURSIVE)
.short("R")
.long(options::RECURSIVE)
.help("operate on files and directories recursively"),
)
.arg(
Arg::with_name(options::traverse::TRAVERSE)
.short(options::traverse::TRAVERSE)
.help("if a command line argument is a symbolic link to a directory, traverse it"),
)
.arg(
Arg::with_name(options::traverse::NO_TRAVERSE)
.short(options::traverse::NO_TRAVERSE)
.help("do not traverse any symbolic links (default)")
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::EVERY]),
)
.arg(
Arg::with_name(options::traverse::EVERY)
.short(options::traverse::EVERY)
.help("traverse every symbolic link to a directory encountered"),
);
let mut app = uu_app().usage(&usage[..]);
// we change the positional args based on whether
// --reference was used.
@ -274,6 +197,86 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
executor.exec()
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(VERSION)
.about(ABOUT)
.arg(
Arg::with_name(options::verbosity::CHANGES)
.short("c")
.long(options::verbosity::CHANGES)
.help("like verbose but report only when a change is made"),
)
.arg(
Arg::with_name(options::verbosity::SILENT)
.short("f")
.long(options::verbosity::SILENT),
)
.arg(
Arg::with_name(options::verbosity::QUIET)
.long(options::verbosity::QUIET)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(options::verbosity::VERBOSE)
.short("v")
.long(options::verbosity::VERBOSE)
.help("output a diagnostic for every file processed"),
)
.arg(
Arg::with_name(options::dereference::DEREFERENCE)
.long(options::dereference::DEREFERENCE),
)
.arg(
Arg::with_name(options::dereference::NO_DEREFERENCE)
.short("h")
.long(options::dereference::NO_DEREFERENCE)
.help(
"affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)",
),
)
.arg(
Arg::with_name(options::preserve_root::PRESERVE)
.long(options::preserve_root::PRESERVE)
.help("fail to operate recursively on '/'"),
)
.arg(
Arg::with_name(options::preserve_root::NO_PRESERVE)
.long(options::preserve_root::NO_PRESERVE)
.help("do not treat '/' specially (the default)"),
)
.arg(
Arg::with_name(options::REFERENCE)
.long(options::REFERENCE)
.value_name("RFILE")
.help("use RFILE's group rather than specifying GROUP values")
.takes_value(true)
.multiple(false),
)
.arg(
Arg::with_name(options::RECURSIVE)
.short("R")
.long(options::RECURSIVE)
.help("operate on files and directories recursively"),
)
.arg(
Arg::with_name(options::traverse::TRAVERSE)
.short(options::traverse::TRAVERSE)
.help("if a command line argument is a symbolic link to a directory, traverse it"),
)
.arg(
Arg::with_name(options::traverse::NO_TRAVERSE)
.short(options::traverse::NO_TRAVERSE)
.help("do not traverse any symbolic links (default)")
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::EVERY]),
)
.arg(
Arg::with_name(options::traverse::EVERY)
.short(options::traverse::EVERY)
.help("traverse every symbolic link to a directory encountered"),
)
}
struct Chgrper {
dest_gid: gid_t,
bit_flag: u8,

View file

@ -61,11 +61,64 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let after_help = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&after_help[..])
.get_matches_from(args);
let changes = matches.is_present(options::CHANGES);
let quiet = matches.is_present(options::QUIET);
let verbose = matches.is_present(options::VERBOSE);
let preserve_root = matches.is_present(options::PRESERVE_ROOT);
let recursive = matches.is_present(options::RECURSIVE);
let fmode = matches
.value_of(options::REFERENCE)
.and_then(|fref| match fs::metadata(fref) {
Ok(meta) => Some(meta.mode()),
Err(err) => crash!(1, "cannot stat attributes of '{}': {}", fref, err),
});
let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
let cmode = if mode_had_minus_prefix {
// clap parsing is finished, now put prefix back
format!("-{}", modes)
} else {
modes.to_string()
};
let mut files: Vec<String> = matches
.values_of(options::FILE)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let cmode = if fmode.is_some() {
// "--reference" and MODE are mutually exclusive
// if "--reference" was used MODE needs to be interpreted as another FILE
// it wasn't possible to implement this behavior directly with clap
files.push(cmode);
None
} else {
Some(cmode)
};
let chmoder = Chmoder {
changes,
quiet,
verbose,
preserve_root,
recursive,
fmode,
cmode,
};
match chmoder.chmod(files) {
Ok(()) => {}
Err(e) => return e,
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::CHANGES)
.long(options::CHANGES)
@ -120,55 +173,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.required_unless(options::MODE)
.multiple(true),
)
.get_matches_from(args);
let changes = matches.is_present(options::CHANGES);
let quiet = matches.is_present(options::QUIET);
let verbose = matches.is_present(options::VERBOSE);
let preserve_root = matches.is_present(options::PRESERVE_ROOT);
let recursive = matches.is_present(options::RECURSIVE);
let fmode = matches
.value_of(options::REFERENCE)
.and_then(|fref| match fs::metadata(fref) {
Ok(meta) => Some(meta.mode()),
Err(err) => crash!(1, "cannot stat attributes of '{}': {}", fref, err),
});
let modes = matches.value_of(options::MODE).unwrap(); // should always be Some because required
let cmode = if mode_had_minus_prefix {
// clap parsing is finished, now put prefix back
format!("-{}", modes)
} else {
modes.to_string()
};
let mut files: Vec<String> = matches
.values_of(options::FILE)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let cmode = if fmode.is_some() {
// "--reference" and MODE are mutually exclusive
// if "--reference" was used MODE needs to be interpreted as another FILE
// it wasn't possible to implement this behavior directly with clap
files.push(cmode);
None
} else {
Some(cmode)
};
let chmoder = Chmoder {
changes,
quiet,
verbose,
preserve_root,
recursive,
fmode,
cmode,
};
match chmoder.chmod(files) {
Ok(()) => {}
Err(e) => return e,
}
0
}
// Iterate 'args' and delete the first occurrence

View file

@ -73,101 +73,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::verbosity::CHANGES)
.short("c")
.long(options::verbosity::CHANGES)
.help("like verbose but report only when a change is made"),
)
.arg(Arg::with_name(options::dereference::DEREFERENCE).long(options::dereference::DEREFERENCE).help(
"affect the referent of each symbolic link (this is the default), rather than the symbolic link itself",
))
.arg(
Arg::with_name(options::dereference::NO_DEREFERENCE)
.short("h")
.long(options::dereference::NO_DEREFERENCE)
.help(
"affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)",
),
)
.arg(
Arg::with_name(options::FROM)
.long(options::FROM)
.help(
"change the owner and/or group of each file only if its current owner and/or group match those specified here. Either may be omitted, in which case a match is not required for the omitted attribute",
)
.value_name("CURRENT_OWNER:CURRENT_GROUP"),
)
.arg(
Arg::with_name(options::preserve_root::PRESERVE)
.long(options::preserve_root::PRESERVE)
.help("fail to operate recursively on '/'"),
)
.arg(
Arg::with_name(options::preserve_root::NO_PRESERVE)
.long(options::preserve_root::NO_PRESERVE)
.help("do not treat '/' specially (the default)"),
)
.arg(
Arg::with_name(options::verbosity::QUIET)
.long(options::verbosity::QUIET)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(options::RECURSIVE)
.short("R")
.long(options::RECURSIVE)
.help("operate on files and directories recursively"),
)
.arg(
Arg::with_name(options::REFERENCE)
.long(options::REFERENCE)
.help("use RFILE's owner and group rather than specifying OWNER:GROUP values")
.value_name("RFILE")
.min_values(1),
)
.arg(Arg::with_name(options::verbosity::SILENT).short("f").long(options::verbosity::SILENT))
.arg(
Arg::with_name(options::traverse::TRAVERSE)
.short(options::traverse::TRAVERSE)
.help("if a command line argument is a symbolic link to a directory, traverse it")
.overrides_with_all(&[options::traverse::EVERY, options::traverse::NO_TRAVERSE]),
)
.arg(
Arg::with_name(options::traverse::EVERY)
.short(options::traverse::EVERY)
.help("traverse every symbolic link to a directory encountered")
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::NO_TRAVERSE]),
)
.arg(
Arg::with_name(options::traverse::NO_TRAVERSE)
.short(options::traverse::NO_TRAVERSE)
.help("do not traverse any symbolic links (default)")
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::EVERY]),
)
.arg(
Arg::with_name(options::verbosity::VERBOSE)
.long(options::verbosity::VERBOSE)
.help("output a diagnostic for every file processed"),
)
.arg(
Arg::with_name(ARG_OWNER)
.multiple(false)
.takes_value(true)
.required(true),
)
.arg(
Arg::with_name(ARG_FILES)
.multiple(true)
.takes_value(true)
.required(true)
.min_values(1),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
/* First arg is the owner/group */
let owner = matches.value_of(ARG_OWNER).unwrap();
@ -273,6 +179,102 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
executor.exec()
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::verbosity::CHANGES)
.short("c")
.long(options::verbosity::CHANGES)
.help("like verbose but report only when a change is made"),
)
.arg(Arg::with_name(options::dereference::DEREFERENCE).long(options::dereference::DEREFERENCE).help(
"affect the referent of each symbolic link (this is the default), rather than the symbolic link itself",
))
.arg(
Arg::with_name(options::dereference::NO_DEREFERENCE)
.short("h")
.long(options::dereference::NO_DEREFERENCE)
.help(
"affect symbolic links instead of any referenced file (useful only on systems that can change the ownership of a symlink)",
),
)
.arg(
Arg::with_name(options::FROM)
.long(options::FROM)
.help(
"change the owner and/or group of each file only if its current owner and/or group match those specified here. Either may be omitted, in which case a match is not required for the omitted attribute",
)
.value_name("CURRENT_OWNER:CURRENT_GROUP"),
)
.arg(
Arg::with_name(options::preserve_root::PRESERVE)
.long(options::preserve_root::PRESERVE)
.help("fail to operate recursively on '/'"),
)
.arg(
Arg::with_name(options::preserve_root::NO_PRESERVE)
.long(options::preserve_root::NO_PRESERVE)
.help("do not treat '/' specially (the default)"),
)
.arg(
Arg::with_name(options::verbosity::QUIET)
.long(options::verbosity::QUIET)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(options::RECURSIVE)
.short("R")
.long(options::RECURSIVE)
.help("operate on files and directories recursively"),
)
.arg(
Arg::with_name(options::REFERENCE)
.long(options::REFERENCE)
.help("use RFILE's owner and group rather than specifying OWNER:GROUP values")
.value_name("RFILE")
.min_values(1),
)
.arg(Arg::with_name(options::verbosity::SILENT).short("f").long(options::verbosity::SILENT))
.arg(
Arg::with_name(options::traverse::TRAVERSE)
.short(options::traverse::TRAVERSE)
.help("if a command line argument is a symbolic link to a directory, traverse it")
.overrides_with_all(&[options::traverse::EVERY, options::traverse::NO_TRAVERSE]),
)
.arg(
Arg::with_name(options::traverse::EVERY)
.short(options::traverse::EVERY)
.help("traverse every symbolic link to a directory encountered")
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::NO_TRAVERSE]),
)
.arg(
Arg::with_name(options::traverse::NO_TRAVERSE)
.short(options::traverse::NO_TRAVERSE)
.help("do not traverse any symbolic links (default)")
.overrides_with_all(&[options::traverse::TRAVERSE, options::traverse::EVERY]),
)
.arg(
Arg::with_name(options::verbosity::VERBOSE)
.long(options::verbosity::VERBOSE)
.help("output a diagnostic for every file processed"),
)
.arg(
Arg::with_name(ARG_OWNER)
.multiple(false)
.takes_value(true)
.required(true),
)
.arg(
Arg::with_name(ARG_FILES)
.multiple(true)
.takes_value(true)
.required(true)
.min_values(1),
)
}
fn parse_spec(spec: &str) -> Result<(Option<u32>, Option<u32>), String> {
let args = spec.split_terminator(':').collect::<Vec<_>>();
let usr_only = args.len() == 1 && !args[0].is_empty();

View file

@ -36,54 +36,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(SYNTAX)
.arg(
Arg::with_name(options::NEWROOT)
.hidden(true)
.required(true)
.index(1),
)
.arg(
Arg::with_name(options::USER)
.short("u")
.long(options::USER)
.help("User (ID or name) to switch before running the program")
.value_name("USER"),
)
.arg(
Arg::with_name(options::GROUP)
.short("g")
.long(options::GROUP)
.help("Group (ID or name) to switch to")
.value_name("GROUP"),
)
.arg(
Arg::with_name(options::GROUPS)
.short("G")
.long(options::GROUPS)
.help("Comma-separated list of groups to switch to")
.value_name("GROUP1,GROUP2..."),
)
.arg(
Arg::with_name(options::USERSPEC)
.long(options::USERSPEC)
.help(
"Colon-separated user and group to switch to. \
Same as -u USER -g GROUP. \
Userspec has higher preference than -u and/or -g",
)
.value_name("USER:GROUP"),
)
.arg(
Arg::with_name(options::COMMAND)
.hidden(true)
.multiple(true)
.index(2),
)
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let default_shell: &'static str = "/bin/sh";
let default_option: &'static str = "-i";
@ -138,6 +91,56 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(SYNTAX)
.arg(
Arg::with_name(options::NEWROOT)
.hidden(true)
.required(true)
.index(1),
)
.arg(
Arg::with_name(options::USER)
.short("u")
.long(options::USER)
.help("User (ID or name) to switch before running the program")
.value_name("USER"),
)
.arg(
Arg::with_name(options::GROUP)
.short("g")
.long(options::GROUP)
.help("Group (ID or name) to switch to")
.value_name("GROUP"),
)
.arg(
Arg::with_name(options::GROUPS)
.short("G")
.long(options::GROUPS)
.help("Comma-separated list of groups to switch to")
.value_name("GROUP1,GROUP2..."),
)
.arg(
Arg::with_name(options::USERSPEC)
.long(options::USERSPEC)
.help(
"Colon-separated user and group to switch to. \
Same as -u USER -g GROUP. \
Userspec has higher preference than -u and/or -g",
)
.value_name("USER:GROUP"),
)
.arg(
Arg::with_name(options::COMMAND)
.hidden(true)
.multiple(true)
.index(2),
)
}
fn set_context(root: &Path, options: &clap::ArgMatches) {
let userspec_str = options.value_of(options::USERSPEC);
let user_str = options.value_of(options::USER).unwrap_or_default();

View file

@ -180,13 +180,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let matches = App::new(executable!())
.name(NAME)
.version(crate_version!())
.about(SUMMARY)
.usage(SYNTAX)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
@ -217,3 +211,12 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
exit_code
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.about(SUMMARY)
.usage(SYNTAX)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
}

View file

@ -137,10 +137,20 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let mut f1 = open_file(matches.value_of(options::FILE_1).unwrap()).unwrap();
let mut f2 = open_file(matches.value_of(options::FILE_2).unwrap()).unwrap();
comm(&mut f1, &mut f2, &matches);
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::COLUMN_1)
@ -167,12 +177,4 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
)
.arg(Arg::with_name(options::FILE_1).required(true))
.arg(Arg::with_name(options::FILE_2).required(true))
.get_matches_from(args);
let mut f1 = open_file(matches.value_of(options::FILE_1).unwrap()).unwrap();
let mut f2 = open_file(matches.value_of(options::FILE_2).unwrap()).unwrap();
comm(&mut f1, &mut f2, &matches);
0
}

View file

@ -290,13 +290,10 @@ static DEFAULT_ATTRIBUTES: &[Attribute] = &[
Attribute::Timestamps,
];
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(&*format!("{}\n{}", LONG_HELP, backup_control::BACKUP_CONTROL_LONG_HELP))
.usage(&usage[..])
.arg(Arg::with_name(options::TARGET_DIRECTORY)
.short("t")
.conflicts_with(options::NO_TARGET_DIRECTORY)
@ -464,6 +461,17 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.arg(Arg::with_name(options::PATHS)
.multiple(true))
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = uu_app()
.after_help(&*format!(
"{}\n{}",
LONG_HELP,
backup_control::BACKUP_CONTROL_LONG_HELP
))
.usage(&usage[..])
.get_matches_from(args);
let options = crash_if_err!(EXIT_ERR, Options::from_matches(&matches));

View file

@ -711,10 +711,37 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
// get the file to split
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);
if file_name == "-" {
let stdin = io::stdin();
crash_if_err!(1, csplit(&options, patterns, stdin.lock()));
} else {
let file = return_if_err!(1, File::open(file_name));
let file_metadata = return_if_err!(1, file.metadata());
if !file_metadata.is_file() {
crash!(1, "'{}' is not a regular file", file_name);
}
crash_if_err!(1, csplit(&options, patterns, BufReader::new(file)));
};
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.usage(&usage[..])
.arg(
Arg::with_name(options::SUFFIX_FORMAT)
.short("b")
@ -768,29 +795,4 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.required(true),
)
.after_help(LONG_HELP)
.get_matches_from(args);
// get the file to split
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);
if file_name == "-" {
let stdin = io::stdin();
crash_if_err!(1, csplit(&options, patterns, stdin.lock()));
} else {
let file = return_if_err!(1, File::open(file_name));
let file_metadata = return_if_err!(1, file.metadata());
if !file_metadata.is_file() {
crash!(1, "'{}' is not a regular file", file_name);
}
crash_if_err!(1, csplit(&options, patterns, BufReader::new(file)));
};
0
}

View file

@ -396,88 +396,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let matches = App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(SYNTAX)
.about(SUMMARY)
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::BYTES)
.short("b")
.long(options::BYTES)
.takes_value(true)
.help("filter byte columns from the input source")
.allow_hyphen_values(true)
.value_name("LIST")
.display_order(1),
)
.arg(
Arg::with_name(options::CHARACTERS)
.short("c")
.long(options::CHARACTERS)
.help("alias for character mode")
.takes_value(true)
.allow_hyphen_values(true)
.value_name("LIST")
.display_order(2),
)
.arg(
Arg::with_name(options::DELIMITER)
.short("d")
.long(options::DELIMITER)
.help("specify the delimiter character that separates fields in the input source. Defaults to Tab.")
.takes_value(true)
.value_name("DELIM")
.display_order(3),
)
.arg(
Arg::with_name(options::FIELDS)
.short("f")
.long(options::FIELDS)
.help("filter field columns from the input source")
.takes_value(true)
.allow_hyphen_values(true)
.value_name("LIST")
.display_order(4),
)
.arg(
Arg::with_name(options::COMPLEMENT)
.long(options::COMPLEMENT)
.help("invert the filter - instead of displaying only the filtered columns, display all but those columns")
.takes_value(false)
.display_order(5),
)
.arg(
Arg::with_name(options::ONLY_DELIMITED)
.short("s")
.long(options::ONLY_DELIMITED)
.help("in field mode, only print lines which contain the delimiter")
.takes_value(false)
.display_order(6),
)
.arg(
Arg::with_name(options::ZERO_TERMINATED)
.short("z")
.long(options::ZERO_TERMINATED)
.help("instead of filtering columns based on line, filter columns based on \\0 (NULL character)")
.takes_value(false)
.display_order(8),
)
.arg(
Arg::with_name(options::OUTPUT_DELIMITER)
.long(options::OUTPUT_DELIMITER)
.help("in field mode, replace the delimiter in output lines with this option's argument")
.takes_value(true)
.value_name("NEW_DELIM")
.display_order(7),
)
.arg(
Arg::with_name(options::FILE)
.hidden(true)
.multiple(true)
)
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let complement = matches.is_present(options::COMPLEMENT);
@ -627,3 +546,87 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(SYNTAX)
.about(SUMMARY)
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::BYTES)
.short("b")
.long(options::BYTES)
.takes_value(true)
.help("filter byte columns from the input source")
.allow_hyphen_values(true)
.value_name("LIST")
.display_order(1),
)
.arg(
Arg::with_name(options::CHARACTERS)
.short("c")
.long(options::CHARACTERS)
.help("alias for character mode")
.takes_value(true)
.allow_hyphen_values(true)
.value_name("LIST")
.display_order(2),
)
.arg(
Arg::with_name(options::DELIMITER)
.short("d")
.long(options::DELIMITER)
.help("specify the delimiter character that separates fields in the input source. Defaults to Tab.")
.takes_value(true)
.value_name("DELIM")
.display_order(3),
)
.arg(
Arg::with_name(options::FIELDS)
.short("f")
.long(options::FIELDS)
.help("filter field columns from the input source")
.takes_value(true)
.allow_hyphen_values(true)
.value_name("LIST")
.display_order(4),
)
.arg(
Arg::with_name(options::COMPLEMENT)
.long(options::COMPLEMENT)
.help("invert the filter - instead of displaying only the filtered columns, display all but those columns")
.takes_value(false)
.display_order(5),
)
.arg(
Arg::with_name(options::ONLY_DELIMITED)
.short("s")
.long(options::ONLY_DELIMITED)
.help("in field mode, only print lines which contain the delimiter")
.takes_value(false)
.display_order(6),
)
.arg(
Arg::with_name(options::ZERO_TERMINATED)
.short("z")
.long(options::ZERO_TERMINATED)
.help("instead of filtering columns based on line, filter columns based on \\0 (NULL character)")
.takes_value(false)
.display_order(8),
)
.arg(
Arg::with_name(options::OUTPUT_DELIMITER)
.long(options::OUTPUT_DELIMITER)
.help("in field mode, replace the delimiter in output lines with this option's argument")
.takes_value(true)
.value_name("NEW_DELIM")
.display_order(7),
)
.arg(
Arg::with_name(options::FILE)
.hidden(true)
.multiple(true)
)
}

View file

@ -142,71 +142,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
{0} [OPTION]... [MMDDhhmm[[CC]YY][.ss]]",
NAME
);
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&syntax[..])
.arg(
Arg::with_name(OPT_DATE)
.short("d")
.long(OPT_DATE)
.takes_value(true)
.help("display time described by STRING, not 'now'"),
)
.arg(
Arg::with_name(OPT_FILE)
.short("f")
.long(OPT_FILE)
.takes_value(true)
.help("like --date; once for each line of DATEFILE"),
)
.arg(
Arg::with_name(OPT_ISO_8601)
.short("I")
.long(OPT_ISO_8601)
.takes_value(true)
.help(ISO_8601_HELP_STRING),
)
.arg(
Arg::with_name(OPT_RFC_EMAIL)
.short("R")
.long(OPT_RFC_EMAIL)
.help(RFC_5322_HELP_STRING),
)
.arg(
Arg::with_name(OPT_RFC_3339)
.long(OPT_RFC_3339)
.takes_value(true)
.help(RFC_3339_HELP_STRING),
)
.arg(
Arg::with_name(OPT_DEBUG)
.long(OPT_DEBUG)
.help("annotate the parsed date, and warn about questionable usage to stderr"),
)
.arg(
Arg::with_name(OPT_REFERENCE)
.short("r")
.long(OPT_REFERENCE)
.takes_value(true)
.help("display the last modification time of FILE"),
)
.arg(
Arg::with_name(OPT_SET)
.short("s")
.long(OPT_SET)
.takes_value(true)
.help(OPT_SET_HELP_STRING),
)
.arg(
Arg::with_name(OPT_UNIVERSAL)
.short("u")
.long(OPT_UNIVERSAL)
.alias(OPT_UNIVERSAL_2)
.help("print or set Coordinated Universal Time (UTC)"),
)
.arg(Arg::with_name(OPT_FORMAT).multiple(false))
.get_matches_from(args);
let matches = uu_app().usage(&syntax[..]).get_matches_from(args);
let format = if let Some(form) = matches.value_of(OPT_FORMAT) {
if !form.starts_with('+') {
@ -314,6 +250,72 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_DATE)
.short("d")
.long(OPT_DATE)
.takes_value(true)
.help("display time described by STRING, not 'now'"),
)
.arg(
Arg::with_name(OPT_FILE)
.short("f")
.long(OPT_FILE)
.takes_value(true)
.help("like --date; once for each line of DATEFILE"),
)
.arg(
Arg::with_name(OPT_ISO_8601)
.short("I")
.long(OPT_ISO_8601)
.takes_value(true)
.help(ISO_8601_HELP_STRING),
)
.arg(
Arg::with_name(OPT_RFC_EMAIL)
.short("R")
.long(OPT_RFC_EMAIL)
.help(RFC_5322_HELP_STRING),
)
.arg(
Arg::with_name(OPT_RFC_3339)
.long(OPT_RFC_3339)
.takes_value(true)
.help(RFC_3339_HELP_STRING),
)
.arg(
Arg::with_name(OPT_DEBUG)
.long(OPT_DEBUG)
.help("annotate the parsed date, and warn about questionable usage to stderr"),
)
.arg(
Arg::with_name(OPT_REFERENCE)
.short("r")
.long(OPT_REFERENCE)
.takes_value(true)
.help("display the last modification time of FILE"),
)
.arg(
Arg::with_name(OPT_SET)
.short("s")
.long(OPT_SET)
.takes_value(true)
.help(OPT_SET_HELP_STRING),
)
.arg(
Arg::with_name(OPT_UNIVERSAL)
.short("u")
.long(OPT_UNIVERSAL)
.alias(OPT_UNIVERSAL_2)
.help("print or set Coordinated Universal Time (UTC)"),
)
.arg(Arg::with_name(OPT_FORMAT).multiple(false))
}
/// Return the appropriate format string for the given settings.
fn make_format_string(settings: &Settings) -> &str {
match settings.format {

View file

@ -258,120 +258,7 @@ fn use_size(free_size: u64, total_size: u64) -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_ALL)
.short("a")
.long("all")
.help("include dummy file systems"),
)
.arg(
Arg::with_name(OPT_BLOCKSIZE)
.short("B")
.long("block-size")
.takes_value(true)
.help(
"scale sizes by SIZE before printing them; e.g.\
'-BM' prints sizes in units of 1,048,576 bytes",
),
)
.arg(
Arg::with_name(OPT_DIRECT)
.long("direct")
.help("show statistics for a file instead of mount point"),
)
.arg(
Arg::with_name(OPT_TOTAL)
.long("total")
.help("produce a grand total"),
)
.arg(
Arg::with_name(OPT_HUMAN_READABLE)
.short("h")
.long("human-readable")
.conflicts_with(OPT_HUMAN_READABLE_2)
.help("print sizes in human readable format (e.g., 1K 234M 2G)"),
)
.arg(
Arg::with_name(OPT_HUMAN_READABLE_2)
.short("H")
.long("si")
.conflicts_with(OPT_HUMAN_READABLE)
.help("likewise, but use powers of 1000 not 1024"),
)
.arg(
Arg::with_name(OPT_INODES)
.short("i")
.long("inodes")
.help("list inode information instead of block usage"),
)
.arg(
Arg::with_name(OPT_KILO)
.short("k")
.help("like --block-size=1K"),
)
.arg(
Arg::with_name(OPT_LOCAL)
.short("l")
.long("local")
.help("limit listing to local file systems"),
)
.arg(
Arg::with_name(OPT_NO_SYNC)
.long("no-sync")
.conflicts_with(OPT_SYNC)
.help("do not invoke sync before getting usage info (default)"),
)
.arg(
Arg::with_name(OPT_OUTPUT)
.long("output")
.takes_value(true)
.use_delimiter(true)
.help(
"use the output format defined by FIELD_LIST,\
or print all fields if FIELD_LIST is omitted.",
),
)
.arg(
Arg::with_name(OPT_PORTABILITY)
.short("P")
.long("portability")
.help("use the POSIX output format"),
)
.arg(
Arg::with_name(OPT_SYNC)
.long("sync")
.conflicts_with(OPT_NO_SYNC)
.help("invoke sync before getting usage info"),
)
.arg(
Arg::with_name(OPT_TYPE)
.short("t")
.long("type")
.takes_value(true)
.use_delimiter(true)
.help("limit listing to file systems of type TYPE"),
)
.arg(
Arg::with_name(OPT_PRINT_TYPE)
.short("T")
.long("print-type")
.help("print file system type"),
)
.arg(
Arg::with_name(OPT_EXCLUDE_TYPE)
.short("x")
.long("exclude-type")
.takes_value(true)
.use_delimiter(true)
.help("limit listing to file systems not of type TYPE"),
)
.arg(Arg::with_name(OPT_PATHS).multiple(true))
.help("Filesystem(s) to list")
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let paths: Vec<String> = matches
.values_of(OPT_PATHS)
@ -511,3 +398,118 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
EXIT_OK
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_ALL)
.short("a")
.long("all")
.help("include dummy file systems"),
)
.arg(
Arg::with_name(OPT_BLOCKSIZE)
.short("B")
.long("block-size")
.takes_value(true)
.help(
"scale sizes by SIZE before printing them; e.g.\
'-BM' prints sizes in units of 1,048,576 bytes",
),
)
.arg(
Arg::with_name(OPT_DIRECT)
.long("direct")
.help("show statistics for a file instead of mount point"),
)
.arg(
Arg::with_name(OPT_TOTAL)
.long("total")
.help("produce a grand total"),
)
.arg(
Arg::with_name(OPT_HUMAN_READABLE)
.short("h")
.long("human-readable")
.conflicts_with(OPT_HUMAN_READABLE_2)
.help("print sizes in human readable format (e.g., 1K 234M 2G)"),
)
.arg(
Arg::with_name(OPT_HUMAN_READABLE_2)
.short("H")
.long("si")
.conflicts_with(OPT_HUMAN_READABLE)
.help("likewise, but use powers of 1000 not 1024"),
)
.arg(
Arg::with_name(OPT_INODES)
.short("i")
.long("inodes")
.help("list inode information instead of block usage"),
)
.arg(
Arg::with_name(OPT_KILO)
.short("k")
.help("like --block-size=1K"),
)
.arg(
Arg::with_name(OPT_LOCAL)
.short("l")
.long("local")
.help("limit listing to local file systems"),
)
.arg(
Arg::with_name(OPT_NO_SYNC)
.long("no-sync")
.conflicts_with(OPT_SYNC)
.help("do not invoke sync before getting usage info (default)"),
)
.arg(
Arg::with_name(OPT_OUTPUT)
.long("output")
.takes_value(true)
.use_delimiter(true)
.help(
"use the output format defined by FIELD_LIST,\
or print all fields if FIELD_LIST is omitted.",
),
)
.arg(
Arg::with_name(OPT_PORTABILITY)
.short("P")
.long("portability")
.help("use the POSIX output format"),
)
.arg(
Arg::with_name(OPT_SYNC)
.long("sync")
.conflicts_with(OPT_NO_SYNC)
.help("invoke sync before getting usage info"),
)
.arg(
Arg::with_name(OPT_TYPE)
.short("t")
.long("type")
.takes_value(true)
.use_delimiter(true)
.help("limit listing to file systems of type TYPE"),
)
.arg(
Arg::with_name(OPT_PRINT_TYPE)
.short("T")
.long("print-type")
.help("print file system type"),
)
.arg(
Arg::with_name(OPT_EXCLUDE_TYPE)
.short("x")
.long("exclude-type")
.takes_value(true)
.use_delimiter(true)
.help("limit listing to file systems not of type TYPE"),
)
.arg(Arg::with_name(OPT_PATHS).multiple(true))
.help("Filesystem(s) to list")
}

View file

@ -73,36 +73,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.usage(&usage[..])
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::BOURNE_SHELL)
.long("sh")
.short("b")
.visible_alias("bourne-shell")
.help("output Bourne shell code to set LS_COLORS")
.display_order(1),
)
.arg(
Arg::with_name(options::C_SHELL)
.long("csh")
.short("c")
.visible_alias("c-shell")
.help("output C shell code to set LS_COLORS")
.display_order(2),
)
.arg(
Arg::with_name(options::PRINT_DATABASE)
.long("print-database")
.short("p")
.help("print the byte counts")
.display_order(3),
)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
.get_matches_from(&args);
let matches = uu_app().usage(&usage[..]).get_matches_from(&args);
let files = matches
.values_of(options::FILE)
@ -181,6 +152,37 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::BOURNE_SHELL)
.long("sh")
.short("b")
.visible_alias("bourne-shell")
.help("output Bourne shell code to set LS_COLORS")
.display_order(1),
)
.arg(
Arg::with_name(options::C_SHELL)
.long("csh")
.short("c")
.visible_alias("c-shell")
.help("output C shell code to set LS_COLORS")
.display_order(2),
)
.arg(
Arg::with_name(options::PRINT_DATABASE)
.long("print-database")
.short("p")
.help("print the byte counts")
.display_order(3),
)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
}
pub trait StrUtils {
/// Remove comments and trim whitespace
fn purify(&self) -> &Self;

View file

@ -38,18 +38,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let after_help = get_long_usage();
let matches = App::new(executable!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&after_help[..])
.version(crate_version!())
.arg(
Arg::with_name(options::ZERO)
.long(options::ZERO)
.short("z")
.help("separate output with NUL rather than newline"),
)
.arg(Arg::with_name(options::DIR).hidden(true).multiple(true))
.get_matches_from(args);
let separator = if matches.is_present(options::ZERO) {
@ -92,3 +83,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.about(ABOUT)
.version(crate_version!())
.arg(
Arg::with_name(options::ZERO)
.long(options::ZERO)
.short("z")
.help("separate output with NUL rather than newline"),
)
.arg(Arg::with_name(options::DIR).hidden(true).multiple(true))
}

View file

@ -387,182 +387,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.usage(&usage[..])
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::ALL)
.short("a")
.long(options::ALL)
.help("write counts for all files, not just directories"),
)
.arg(
Arg::with_name(options::APPARENT_SIZE)
.long(options::APPARENT_SIZE)
.help(
"print apparent sizes, rather than disk usage \
although the apparent size is usually smaller, it may be larger due to holes \
in ('sparse') files, internal fragmentation, indirect blocks, and the like"
)
.alias("app") // The GNU test suite uses this alias
)
.arg(
Arg::with_name(options::BLOCK_SIZE)
.short("B")
.long(options::BLOCK_SIZE)
.value_name("SIZE")
.help(
"scale sizes by SIZE before printing them. \
E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below."
)
)
.arg(
Arg::with_name(options::BYTES)
.short("b")
.long("bytes")
.help("equivalent to '--apparent-size --block-size=1'")
)
.arg(
Arg::with_name(options::TOTAL)
.long("total")
.short("c")
.help("produce a grand total")
)
.arg(
Arg::with_name(options::MAX_DEPTH)
.short("d")
.long("max-depth")
.value_name("N")
.help(
"print the total for a directory (or file, with --all) \
only if it is N or fewer levels below the command \
line argument; --max-depth=0 is the same as --summarize"
)
)
.arg(
Arg::with_name(options::HUMAN_READABLE)
.long("human-readable")
.short("h")
.help("print sizes in human readable format (e.g., 1K 234M 2G)")
)
.arg(
Arg::with_name("inodes")
.long("inodes")
.help(
"list inode usage information instead of block usage like --block-size=1K"
)
)
.arg(
Arg::with_name(options::BLOCK_SIZE_1K)
.short("k")
.help("like --block-size=1K")
)
.arg(
Arg::with_name(options::COUNT_LINKS)
.short("l")
.long("count-links")
.help("count sizes many times if hard linked")
)
.arg(
Arg::with_name(options::DEREFERENCE)
.short("L")
.long(options::DEREFERENCE)
.help("dereference all symbolic links")
)
// .arg(
// Arg::with_name("no-dereference")
// .short("P")
// .long("no-dereference")
// .help("don't follow any symbolic links (this is the default)")
// )
.arg(
Arg::with_name(options::BLOCK_SIZE_1M)
.short("m")
.help("like --block-size=1M")
)
.arg(
Arg::with_name(options::NULL)
.short("0")
.long("null")
.help("end each output line with 0 byte rather than newline")
)
.arg(
Arg::with_name(options::SEPARATE_DIRS)
.short("S")
.long("separate-dirs")
.help("do not include size of subdirectories")
)
.arg(
Arg::with_name(options::SUMMARIZE)
.short("s")
.long("summarize")
.help("display only a total for each argument")
)
.arg(
Arg::with_name(options::SI)
.long(options::SI)
.help("like -h, but use powers of 1000 not 1024")
)
.arg(
Arg::with_name(options::ONE_FILE_SYSTEM)
.short("x")
.long(options::ONE_FILE_SYSTEM)
.help("skip directories on different file systems")
)
.arg(
Arg::with_name(options::THRESHOLD)
.short("t")
.long(options::THRESHOLD)
.alias("th")
.value_name("SIZE")
.number_of_values(1)
.allow_hyphen_values(true)
.help("exclude entries smaller than SIZE if positive, \
or entries greater than SIZE if negative")
)
// .arg(
// Arg::with_name("")
// .short("x")
// .long("exclude-from")
// .value_name("FILE")
// .help("exclude files that match any pattern in FILE")
// )
// .arg(
// Arg::with_name("exclude")
// .long("exclude")
// .value_name("PATTERN")
// .help("exclude files that match PATTERN")
// )
.arg(
Arg::with_name(options::TIME)
.long(options::TIME)
.value_name("WORD")
.require_equals(true)
.min_values(0)
.possible_values(&["atime", "access", "use", "ctime", "status", "birth", "creation"])
.help(
"show time of the last modification of any file in the \
directory, or any of its subdirectories. If WORD is given, show time as WORD instead \
of modification time: atime, access, use, ctime, status, birth or creation"
)
)
.arg(
Arg::with_name(options::TIME_STYLE)
.long(options::TIME_STYLE)
.value_name("STYLE")
.help(
"show times using style STYLE: \
full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'"
)
)
.arg(
Arg::with_name(options::FILE)
.hidden(true)
.multiple(true)
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let summarize = matches.is_present(options::SUMMARIZE);
@ -743,6 +568,183 @@ Try '{} --help' for more information.",
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::ALL)
.short("a")
.long(options::ALL)
.help("write counts for all files, not just directories"),
)
.arg(
Arg::with_name(options::APPARENT_SIZE)
.long(options::APPARENT_SIZE)
.help(
"print apparent sizes, rather than disk usage \
although the apparent size is usually smaller, it may be larger due to holes \
in ('sparse') files, internal fragmentation, indirect blocks, and the like"
)
.alias("app") // The GNU test suite uses this alias
)
.arg(
Arg::with_name(options::BLOCK_SIZE)
.short("B")
.long(options::BLOCK_SIZE)
.value_name("SIZE")
.help(
"scale sizes by SIZE before printing them. \
E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below."
)
)
.arg(
Arg::with_name(options::BYTES)
.short("b")
.long("bytes")
.help("equivalent to '--apparent-size --block-size=1'")
)
.arg(
Arg::with_name(options::TOTAL)
.long("total")
.short("c")
.help("produce a grand total")
)
.arg(
Arg::with_name(options::MAX_DEPTH)
.short("d")
.long("max-depth")
.value_name("N")
.help(
"print the total for a directory (or file, with --all) \
only if it is N or fewer levels below the command \
line argument; --max-depth=0 is the same as --summarize"
)
)
.arg(
Arg::with_name(options::HUMAN_READABLE)
.long("human-readable")
.short("h")
.help("print sizes in human readable format (e.g., 1K 234M 2G)")
)
.arg(
Arg::with_name("inodes")
.long("inodes")
.help(
"list inode usage information instead of block usage like --block-size=1K"
)
)
.arg(
Arg::with_name(options::BLOCK_SIZE_1K)
.short("k")
.help("like --block-size=1K")
)
.arg(
Arg::with_name(options::COUNT_LINKS)
.short("l")
.long("count-links")
.help("count sizes many times if hard linked")
)
.arg(
Arg::with_name(options::DEREFERENCE)
.short("L")
.long(options::DEREFERENCE)
.help("dereference all symbolic links")
)
// .arg(
// Arg::with_name("no-dereference")
// .short("P")
// .long("no-dereference")
// .help("don't follow any symbolic links (this is the default)")
// )
.arg(
Arg::with_name(options::BLOCK_SIZE_1M)
.short("m")
.help("like --block-size=1M")
)
.arg(
Arg::with_name(options::NULL)
.short("0")
.long("null")
.help("end each output line with 0 byte rather than newline")
)
.arg(
Arg::with_name(options::SEPARATE_DIRS)
.short("S")
.long("separate-dirs")
.help("do not include size of subdirectories")
)
.arg(
Arg::with_name(options::SUMMARIZE)
.short("s")
.long("summarize")
.help("display only a total for each argument")
)
.arg(
Arg::with_name(options::SI)
.long(options::SI)
.help("like -h, but use powers of 1000 not 1024")
)
.arg(
Arg::with_name(options::ONE_FILE_SYSTEM)
.short("x")
.long(options::ONE_FILE_SYSTEM)
.help("skip directories on different file systems")
)
.arg(
Arg::with_name(options::THRESHOLD)
.short("t")
.long(options::THRESHOLD)
.alias("th")
.value_name("SIZE")
.number_of_values(1)
.allow_hyphen_values(true)
.help("exclude entries smaller than SIZE if positive, \
or entries greater than SIZE if negative")
)
// .arg(
// Arg::with_name("")
// .short("x")
// .long("exclude-from")
// .value_name("FILE")
// .help("exclude files that match any pattern in FILE")
// )
// .arg(
// Arg::with_name("exclude")
// .long("exclude")
// .value_name("PATTERN")
// .help("exclude files that match PATTERN")
// )
.arg(
Arg::with_name(options::TIME)
.long(options::TIME)
.value_name("WORD")
.require_equals(true)
.min_values(0)
.possible_values(&["atime", "access", "use", "ctime", "status", "birth", "creation"])
.help(
"show time of the last modification of any file in the \
directory, or any of its subdirectories. If WORD is given, show time as WORD instead \
of modification time: atime, access, use, ctime, status, birth or creation"
)
)
.arg(
Arg::with_name(options::TIME_STYLE)
.long(options::TIME_STYLE)
.value_name("STYLE")
.help(
"show times using style STYLE: \
full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'"
)
)
.arg(
Arg::with_name(options::FILE)
.hidden(true)
.multiple(true)
)
}
#[derive(Clone, Copy)]
enum Threshold {
Lower(u64),

View file

@ -117,7 +117,26 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let no_newline = matches.is_present(options::NO_NEWLINE);
let escaped = matches.is_present(options::ENABLE_BACKSLASH_ESCAPE);
let values: Vec<String> = match matches.values_of(options::STRING) {
Some(s) => s.map(|s| s.to_string()).collect(),
None => vec!["".to_string()],
};
match execute(no_newline, escaped, values) {
Ok(_) => 0,
Err(f) => {
show_error!("{}", f);
1
}
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
// TrailingVarArg specifies the final positional argument is a VarArg
// and it doesn't attempts the parse any further args.
@ -154,22 +173,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.multiple(true)
.allow_hyphen_values(true),
)
.get_matches_from(args);
let no_newline = matches.is_present(options::NO_NEWLINE);
let escaped = matches.is_present(options::ENABLE_BACKSLASH_ESCAPE);
let values: Vec<String> = match matches.values_of(options::STRING) {
Some(s) => s.map(|s| s.to_string()).collect(),
None => vec!["".to_string()],
};
match execute(no_newline, escaped, values) {
Ok(_) => 0,
Err(f) => {
show_error!("{}", f);
1
}
}
}
fn execute(no_newline: bool, escaped: bool, free: Vec<String>) -> io::Result<()> {

View file

@ -114,7 +114,7 @@ fn build_command<'a, 'b>(args: &'a mut Vec<&'b str>) -> (Cow<'b, str>, &'a [&'b
(progname, &args[..])
}
fn create_app() -> App<'static, 'static> {
pub fn uu_app() -> App<'static, 'static> {
App::new(crate_name!())
.version(crate_version!())
.author(crate_authors!())
@ -158,7 +158,7 @@ fn create_app() -> App<'static, 'static> {
}
fn run_env(args: impl uucore::Args) -> Result<(), i32> {
let app = create_app();
let app = uu_app();
let matches = app.get_matches_from(args);
let ignore_env = matches.is_present("ignore-environment");

View file

@ -108,10 +108,16 @@ impl Options {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
expand(Options::new(&matches));
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::INITIAL)
@ -138,10 +144,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.hidden(true)
.takes_value(true)
)
.get_matches_from(args);
expand(Options::new(&matches));
0
}
fn open(path: String) -> BufReader<Box<dyn Read + 'static>> {

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/expr.rs"
[dependencies]
clap = "2.33.3"
libc = "0.2.42"
num-bigint = "0.4.0"
num-traits = "0.2.14"

View file

@ -8,13 +8,20 @@
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use uucore::InvalidEncodingHandling;
mod syntax_tree;
mod tokens;
static NAME: &str = "expr";
static VERSION: &str = env!("CARGO_PKG_VERSION");
const VERSION: &str = "version";
const HELP: &str = "help";
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.arg(Arg::with_name(VERSION).long(VERSION))
.arg(Arg::with_name(HELP).long(HELP))
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args
@ -133,5 +140,5 @@ Environment variables:
}
fn print_version() {
println!("{} {}", NAME, VERSION);
println!("{} {}", executable!(), crate_version!());
}

View file

@ -36,11 +36,7 @@ fn print_factors_str(num_str: &str, w: &mut impl io::Write) -> Result<(), Box<dy
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.arg(Arg::with_name(options::NUMBER).multiple(true))
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let stdout = stdout();
let mut w = io::BufWriter::new(stdout.lock());
@ -68,3 +64,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.arg(Arg::with_name(options::NUMBER).multiple(true))
}

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/false.rs"
[dependencies]
clap = "2.33.3"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -5,6 +5,15 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
use clap::{App, AppSettings};
use uucore::executable;
pub fn uumain(_: impl uucore::Args) -> i32 {
1
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.setting(AppSettings::DisableHelpFlags)
.setting(AppSettings::DisableVersion)
}

View file

@ -77,129 +77,7 @@ pub struct FmtOptions {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_CROWN_MARGIN)
.short("c")
.long(OPT_CROWN_MARGIN)
.help(
"First and second line of paragraph
may have different indentations, in which
case the first line's indentation is preserved,
and each subsequent line's indentation matches the second line.",
),
)
.arg(
Arg::with_name(OPT_TAGGED_PARAGRAPH)
.short("t")
.long("tagged-paragraph")
.help(
"Like -c, except that the first and second line of a paragraph *must*
have different indentation or they are treated as separate paragraphs.",
),
)
.arg(
Arg::with_name(OPT_PRESERVE_HEADERS)
.short("m")
.long("preserve-headers")
.help(
"Attempt to detect and preserve mail headers in the input.
Be careful when combining this flag with -p.",
),
)
.arg(
Arg::with_name(OPT_SPLIT_ONLY)
.short("s")
.long("split-only")
.help("Split lines only, do not reflow."),
)
.arg(
Arg::with_name(OPT_UNIFORM_SPACING)
.short("u")
.long("uniform-spacing")
.help(
"Insert exactly one
space between words, and two between sentences.
Sentence breaks in the input are detected as [?!.]
followed by two spaces or a newline; other punctuation
is not interpreted as a sentence break.",
),
)
.arg(
Arg::with_name(OPT_PREFIX)
.short("p")
.long("prefix")
.help(
"Reformat only lines
beginning with PREFIX, reattaching PREFIX to reformatted lines.
Unless -x is specified, leading whitespace will be ignored
when matching PREFIX.",
)
.value_name("PREFIX"),
)
.arg(
Arg::with_name(OPT_SKIP_PREFIX)
.short("P")
.long("skip-prefix")
.help(
"Do not reformat lines
beginning with PSKIP. Unless -X is specified, leading whitespace
will be ignored when matching PSKIP",
)
.value_name("PSKIP"),
)
.arg(
Arg::with_name(OPT_EXACT_PREFIX)
.short("x")
.long("exact-prefix")
.help(
"PREFIX must match at the
beginning of the line with no preceding whitespace.",
),
)
.arg(
Arg::with_name(OPT_EXACT_SKIP_PREFIX)
.short("X")
.long("exact-skip-prefix")
.help(
"PSKIP must match at the
beginning of the line with no preceding whitespace.",
),
)
.arg(
Arg::with_name(OPT_WIDTH)
.short("w")
.long("width")
.help("Fill output lines up to a maximum of WIDTH columns, default 79.")
.value_name("WIDTH"),
)
.arg(
Arg::with_name(OPT_GOAL)
.short("g")
.long("goal")
.help("Goal width, default ~0.94*WIDTH. Must be less than WIDTH.")
.value_name("GOAL"),
)
.arg(Arg::with_name(OPT_QUICK).short("q").long("quick").help(
"Break lines more quickly at the
expense of a potentially more ragged appearance.",
))
.arg(
Arg::with_name(OPT_TAB_WIDTH)
.short("T")
.long("tab-width")
.help(
"Treat tabs as TABWIDTH spaces for
determining line length, default 8. Note that this is used only for
calculating line lengths; tabs are preserved in the output.",
)
.value_name("TABWIDTH"),
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let mut files: Vec<String> = matches
.values_of(ARG_FILES)
@ -331,3 +209,127 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_CROWN_MARGIN)
.short("c")
.long(OPT_CROWN_MARGIN)
.help(
"First and second line of paragraph
may have different indentations, in which
case the first line's indentation is preserved,
and each subsequent line's indentation matches the second line.",
),
)
.arg(
Arg::with_name(OPT_TAGGED_PARAGRAPH)
.short("t")
.long("tagged-paragraph")
.help(
"Like -c, except that the first and second line of a paragraph *must*
have different indentation or they are treated as separate paragraphs.",
),
)
.arg(
Arg::with_name(OPT_PRESERVE_HEADERS)
.short("m")
.long("preserve-headers")
.help(
"Attempt to detect and preserve mail headers in the input.
Be careful when combining this flag with -p.",
),
)
.arg(
Arg::with_name(OPT_SPLIT_ONLY)
.short("s")
.long("split-only")
.help("Split lines only, do not reflow."),
)
.arg(
Arg::with_name(OPT_UNIFORM_SPACING)
.short("u")
.long("uniform-spacing")
.help(
"Insert exactly one
space between words, and two between sentences.
Sentence breaks in the input are detected as [?!.]
followed by two spaces or a newline; other punctuation
is not interpreted as a sentence break.",
),
)
.arg(
Arg::with_name(OPT_PREFIX)
.short("p")
.long("prefix")
.help(
"Reformat only lines
beginning with PREFIX, reattaching PREFIX to reformatted lines.
Unless -x is specified, leading whitespace will be ignored
when matching PREFIX.",
)
.value_name("PREFIX"),
)
.arg(
Arg::with_name(OPT_SKIP_PREFIX)
.short("P")
.long("skip-prefix")
.help(
"Do not reformat lines
beginning with PSKIP. Unless -X is specified, leading whitespace
will be ignored when matching PSKIP",
)
.value_name("PSKIP"),
)
.arg(
Arg::with_name(OPT_EXACT_PREFIX)
.short("x")
.long("exact-prefix")
.help(
"PREFIX must match at the
beginning of the line with no preceding whitespace.",
),
)
.arg(
Arg::with_name(OPT_EXACT_SKIP_PREFIX)
.short("X")
.long("exact-skip-prefix")
.help(
"PSKIP must match at the
beginning of the line with no preceding whitespace.",
),
)
.arg(
Arg::with_name(OPT_WIDTH)
.short("w")
.long("width")
.help("Fill output lines up to a maximum of WIDTH columns, default 79.")
.value_name("WIDTH"),
)
.arg(
Arg::with_name(OPT_GOAL)
.short("g")
.long("goal")
.help("Goal width, default ~0.94*WIDTH. Must be less than WIDTH.")
.value_name("GOAL"),
)
.arg(Arg::with_name(OPT_QUICK).short("q").long("quick").help(
"Break lines more quickly at the
expense of a potentially more ragged appearance.",
))
.arg(
Arg::with_name(OPT_TAB_WIDTH)
.short("T")
.long("tab-width")
.help(
"Treat tabs as TABWIDTH spaces for
determining line length, default 8. Note that this is used only for
calculating line lengths; tabs are preserved in the output.",
)
.value_name("TABWIDTH"),
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
}

View file

@ -36,7 +36,35 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.accept_any();
let (args, obs_width) = handle_obsolete(&args[..]);
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let bytes = matches.is_present(options::BYTES);
let spaces = matches.is_present(options::SPACES);
let poss_width = match matches.value_of(options::WIDTH) {
Some(v) => Some(v.to_owned()),
None => obs_width,
};
let width = match poss_width {
Some(inp_width) => match inp_width.parse::<usize>() {
Ok(width) => width,
Err(e) => crash!(1, "illegal width value (\"{}\"): {}", inp_width, e),
},
None => 80,
};
let files = match matches.values_of(options::FILE) {
Some(v) => v.map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
fold(files, bytes, spaces, width);
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(SYNTAX)
@ -68,31 +96,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true),
)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
.get_matches_from(args);
let bytes = matches.is_present(options::BYTES);
let spaces = matches.is_present(options::SPACES);
let poss_width = match matches.value_of(options::WIDTH) {
Some(v) => Some(v.to_owned()),
None => obs_width,
};
let width = match poss_width {
Some(inp_width) => match inp_width.parse::<usize>() {
Ok(width) => width,
Err(e) => crash!(1, "illegal width value (\"{}\"): {}", inp_width, e),
},
None => 80,
};
let files = match matches.values_of(options::FILE) {
Some(v) => v.map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
fold(files, bytes, spaces, width);
0
}
fn handle_obsolete(args: &[String]) -> (Vec<String>, Option<String>) {

View file

@ -35,17 +35,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::USERS)
.multiple(true)
.takes_value(true)
.value_name(options::USERS),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let users: Vec<String> = matches
.values_of(options::USERS)
@ -93,3 +83,15 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
exit_code
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::USERS)
.multiple(true)
.takes_value(true)
.value_name(options::USERS),
)
}

View file

@ -285,119 +285,7 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
// Default binary in Windows, text mode otherwise
let binary_flag_default = cfg!(windows);
let binary_help = format!(
"read in binary mode{}",
if binary_flag_default {
" (default)"
} else {
""
}
);
let text_help = format!(
"read in text mode{}",
if binary_flag_default {
""
} else {
" (default)"
}
);
let mut app = App::new(executable!())
.version(crate_version!())
.about("Compute and check message digests.")
.arg(
Arg::with_name("binary")
.short("b")
.long("binary")
.help(&binary_help),
)
.arg(
Arg::with_name("check")
.short("c")
.long("check")
.help("read hashsums from the FILEs and check them"),
)
.arg(
Arg::with_name("tag")
.long("tag")
.help("create a BSD-style checksum"),
)
.arg(
Arg::with_name("text")
.short("t")
.long("text")
.help(&text_help)
.conflicts_with("binary"),
)
.arg(
Arg::with_name("quiet")
.short("q")
.long("quiet")
.help("don't print OK for each successfully verified file"),
)
.arg(
Arg::with_name("status")
.short("s")
.long("status")
.help("don't output anything, status code shows success"),
)
.arg(
Arg::with_name("strict")
.long("strict")
.help("exit non-zero for improperly formatted checksum lines"),
)
.arg(
Arg::with_name("warn")
.short("w")
.long("warn")
.help("warn about improperly formatted checksum lines"),
)
// Needed for variable-length output sums (e.g. SHAKE)
.arg(
Arg::with_name("bits")
.long("bits")
.help("set the size of the output (only for SHAKE)")
.takes_value(true)
.value_name("BITS")
// XXX: should we actually use validators? they're not particularly efficient
.validator(is_valid_bit_num),
)
.arg(
Arg::with_name("FILE")
.index(1)
.multiple(true)
.value_name("FILE"),
);
if !is_custom_binary(&binary_name) {
let algorithms = &[
("md5", "work with MD5"),
("sha1", "work with SHA1"),
("sha224", "work with SHA224"),
("sha256", "work with SHA256"),
("sha384", "work with SHA384"),
("sha512", "work with SHA512"),
("sha3", "work with SHA3"),
("sha3-224", "work with SHA3-224"),
("sha3-256", "work with SHA3-256"),
("sha3-384", "work with SHA3-384"),
("sha3-512", "work with SHA3-512"),
(
"shake128",
"work with SHAKE128 using BITS for the output size",
),
(
"shake256",
"work with SHAKE256 using BITS for the output size",
),
("b2sum", "work with BLAKE2"),
];
for (name, desc) in algorithms {
app = app.arg(Arg::with_name(name).long(name).help(desc));
}
}
let app = uu_app(&binary_name);
// FIXME: this should use get_matches_from_safe() and crash!(), but at the moment that just
// causes "error: " to be printed twice (once from crash!() and once from clap). With
@ -445,6 +333,124 @@ pub fn uumain(mut args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app_common() -> App<'static, 'static> {
#[cfg(windows)]
const BINARY_HELP: &str = "read in binary mode (default)";
#[cfg(not(windows))]
const BINARY_HELP: &str = "read in binary mode";
#[cfg(windows)]
const TEXT_HELP: &str = "read in text mode";
#[cfg(not(windows))]
const TEXT_HELP: &str = "read in text mode (default)";
App::new(executable!())
.version(crate_version!())
.about("Compute and check message digests.")
.arg(
Arg::with_name("binary")
.short("b")
.long("binary")
.help(BINARY_HELP),
)
.arg(
Arg::with_name("check")
.short("c")
.long("check")
.help("read hashsums from the FILEs and check them"),
)
.arg(
Arg::with_name("tag")
.long("tag")
.help("create a BSD-style checksum"),
)
.arg(
Arg::with_name("text")
.short("t")
.long("text")
.help(TEXT_HELP)
.conflicts_with("binary"),
)
.arg(
Arg::with_name("quiet")
.short("q")
.long("quiet")
.help("don't print OK for each successfully verified file"),
)
.arg(
Arg::with_name("status")
.short("s")
.long("status")
.help("don't output anything, status code shows success"),
)
.arg(
Arg::with_name("strict")
.long("strict")
.help("exit non-zero for improperly formatted checksum lines"),
)
.arg(
Arg::with_name("warn")
.short("w")
.long("warn")
.help("warn about improperly formatted checksum lines"),
)
// Needed for variable-length output sums (e.g. SHAKE)
.arg(
Arg::with_name("bits")
.long("bits")
.help("set the size of the output (only for SHAKE)")
.takes_value(true)
.value_name("BITS")
// XXX: should we actually use validators? they're not particularly efficient
.validator(is_valid_bit_num),
)
.arg(
Arg::with_name("FILE")
.index(1)
.multiple(true)
.value_name("FILE"),
)
}
pub fn uu_app_custom() -> App<'static, 'static> {
let mut app = uu_app_common();
let algorithms = &[
("md5", "work with MD5"),
("sha1", "work with SHA1"),
("sha224", "work with SHA224"),
("sha256", "work with SHA256"),
("sha384", "work with SHA384"),
("sha512", "work with SHA512"),
("sha3", "work with SHA3"),
("sha3-224", "work with SHA3-224"),
("sha3-256", "work with SHA3-256"),
("sha3-384", "work with SHA3-384"),
("sha3-512", "work with SHA3-512"),
(
"shake128",
"work with SHAKE128 using BITS for the output size",
),
(
"shake256",
"work with SHAKE256 using BITS for the output size",
),
("b2sum", "work with BLAKE2"),
];
for (name, desc) in algorithms {
app = app.arg(Arg::with_name(name).long(name).help(desc));
}
app
}
// hashsum is handled differently in build.rs, therefore this is not the same
// as in other utilities.
fn uu_app(binary_name: &str) -> App<'static, 'static> {
if !is_custom_binary(binary_name) {
uu_app_custom()
} else {
uu_app_common()
}
}
#[allow(clippy::cognitive_complexity)]
fn hashsum<'a, I>(mut options: Options, files: I) -> Result<(), i32>
where

View file

@ -40,7 +40,7 @@ mod take;
use lines::zlines;
use take::take_all_but;
fn app<'a>() -> App<'a, 'a> {
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
@ -167,7 +167,7 @@ impl HeadOptions {
///Construct options from matches
pub fn get_from(args: impl uucore::Args) -> Result<Self, String> {
let matches = app().get_matches_from(arg_iterate(args)?);
let matches = uu_app().get_matches_from(arg_iterate(args)?);
let mut options = HeadOptions::new();

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/hostid.rs"
[dependencies]
clap = "2.33.3"
libc = "0.2.42"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -10,12 +10,10 @@
#[macro_use]
extern crate uucore;
use clap::{crate_version, App};
use libc::c_long;
use uucore::InvalidEncodingHandling;
static SYNTAX: &str = "[options]";
static SUMMARY: &str = "";
static LONG_HELP: &str = "";
// currently rust libc interface doesn't include gethostid
extern "C" {
@ -23,14 +21,17 @@ extern "C" {
}
pub fn uumain(args: impl uucore::Args) -> i32 {
app!(SYNTAX, SUMMARY, LONG_HELP).parse(
args.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any(),
);
uu_app().get_matches_from(args);
hostid();
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.usage(SYNTAX)
}
fn hostid() {
/*
* POSIX says gethostid returns a "32-bit identifier" but is silent

View file

@ -52,10 +52,25 @@ fn get_usage() -> String {
}
fn execute(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
match matches.value_of(OPT_HOST) {
None => display_hostname(&matches),
Some(host) => {
if let Err(err) = hostname::set(host) {
show_error!("{}", err);
1
} else {
0
}
}
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_DOMAIN)
.short("d")
@ -80,19 +95,6 @@ fn execute(args: impl uucore::Args) -> i32 {
possible",
))
.arg(Arg::with_name(OPT_HOST))
.get_matches_from(args);
match matches.value_of(OPT_HOST) {
None => display_hostname(&matches),
Some(host) => {
if let Err(err) = hostname::set(host) {
show_error!("{}", err);
1
} else {
0
}
}
}
}
fn display_hostname(matches: &ArgMatches) -> i32 {

View file

@ -115,106 +115,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let after_help = get_description();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&after_help[..])
.arg(
Arg::with_name(options::OPT_AUDIT)
.short("A")
.conflicts_with_all(&[
options::OPT_GROUP,
options::OPT_EFFECTIVE_USER,
options::OPT_HUMAN_READABLE,
options::OPT_PASSWORD,
options::OPT_GROUPS,
options::OPT_ZERO,
])
.help(
"Display the process audit user ID and other process audit properties,\n\
which requires privilege (not available on Linux).",
),
)
.arg(
Arg::with_name(options::OPT_EFFECTIVE_USER)
.short("u")
.long(options::OPT_EFFECTIVE_USER)
.conflicts_with(options::OPT_GROUP)
.help("Display only the effective user ID as a number."),
)
.arg(
Arg::with_name(options::OPT_GROUP)
.short("g")
.long(options::OPT_GROUP)
.help("Display only the effective group ID as a number"),
)
.arg(
Arg::with_name(options::OPT_GROUPS)
.short("G")
.long(options::OPT_GROUPS)
.conflicts_with_all(&[
options::OPT_GROUP,
options::OPT_EFFECTIVE_USER,
options::OPT_HUMAN_READABLE,
options::OPT_PASSWORD,
options::OPT_AUDIT,
])
.help(
"Display only the different group IDs as white-space separated numbers, \
in no particular order.",
),
)
.arg(
Arg::with_name(options::OPT_HUMAN_READABLE)
.short("p")
.help("Make the output human-readable. Each display is on a separate line."),
)
.arg(
Arg::with_name(options::OPT_NAME)
.short("n")
.long(options::OPT_NAME)
.help(
"Display the name of the user or group ID for the -G, -g and -u options \
instead of the number.\nIf any of the ID numbers cannot be mapped into \
names, the number will be displayed as usual.",
),
)
.arg(
Arg::with_name(options::OPT_PASSWORD)
.short("P")
.help("Display the id as a password file entry."),
)
.arg(
Arg::with_name(options::OPT_REAL_ID)
.short("r")
.long(options::OPT_REAL_ID)
.help(
"Display the real ID for the -G, -g and -u options instead of \
the effective ID.",
),
)
.arg(
Arg::with_name(options::OPT_ZERO)
.short("z")
.long(options::OPT_ZERO)
.help(
"delimit entries with NUL characters, not whitespace;\n\
not permitted in default format",
),
)
.arg(
Arg::with_name(options::OPT_CONTEXT)
.short("Z")
.long(options::OPT_CONTEXT)
.help("NotImplemented: print only the security context of the process"),
)
.arg(
Arg::with_name(options::ARG_USERS)
.multiple(true)
.takes_value(true)
.value_name(options::ARG_USERS),
)
.get_matches_from(args);
let users: Vec<String> = matches
@ -385,6 +288,107 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
exit_code
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::OPT_AUDIT)
.short("A")
.conflicts_with_all(&[
options::OPT_GROUP,
options::OPT_EFFECTIVE_USER,
options::OPT_HUMAN_READABLE,
options::OPT_PASSWORD,
options::OPT_GROUPS,
options::OPT_ZERO,
])
.help(
"Display the process audit user ID and other process audit properties,\n\
which requires privilege (not available on Linux).",
),
)
.arg(
Arg::with_name(options::OPT_EFFECTIVE_USER)
.short("u")
.long(options::OPT_EFFECTIVE_USER)
.conflicts_with(options::OPT_GROUP)
.help("Display only the effective user ID as a number."),
)
.arg(
Arg::with_name(options::OPT_GROUP)
.short("g")
.long(options::OPT_GROUP)
.help("Display only the effective group ID as a number"),
)
.arg(
Arg::with_name(options::OPT_GROUPS)
.short("G")
.long(options::OPT_GROUPS)
.conflicts_with_all(&[
options::OPT_GROUP,
options::OPT_EFFECTIVE_USER,
options::OPT_HUMAN_READABLE,
options::OPT_PASSWORD,
options::OPT_AUDIT,
])
.help(
"Display only the different group IDs as white-space separated numbers, \
in no particular order.",
),
)
.arg(
Arg::with_name(options::OPT_HUMAN_READABLE)
.short("p")
.help("Make the output human-readable. Each display is on a separate line."),
)
.arg(
Arg::with_name(options::OPT_NAME)
.short("n")
.long(options::OPT_NAME)
.help(
"Display the name of the user or group ID for the -G, -g and -u options \
instead of the number.\nIf any of the ID numbers cannot be mapped into \
names, the number will be displayed as usual.",
),
)
.arg(
Arg::with_name(options::OPT_PASSWORD)
.short("P")
.help("Display the id as a password file entry."),
)
.arg(
Arg::with_name(options::OPT_REAL_ID)
.short("r")
.long(options::OPT_REAL_ID)
.help(
"Display the real ID for the -G, -g and -u options instead of \
the effective ID.",
),
)
.arg(
Arg::with_name(options::OPT_ZERO)
.short("z")
.long(options::OPT_ZERO)
.help(
"delimit entries with NUL characters, not whitespace;\n\
not permitted in default format",
),
)
.arg(
Arg::with_name(options::OPT_CONTEXT)
.short("Z")
.long(options::OPT_CONTEXT)
.help("NotImplemented: print only the security context of the process"),
)
.arg(
Arg::with_name(options::ARG_USERS)
.multiple(true)
.takes_value(true)
.value_name(options::ARG_USERS),
)
}
fn pretty(possible_pw: Option<Passwd>) {
if let Some(p) = possible_pw {
print!("uid\t{}\ngroups\t", p.name());

View file

@ -98,10 +98,35 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let paths: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
if let Err(s) = check_unimplemented(&matches) {
show_error!("Unimplemented feature: {}", s);
return 2;
}
let behavior = match behavior(&matches) {
Ok(x) => x,
Err(ret) => {
return ret;
}
};
match behavior.main_function {
MainFunction::Directory => directory(paths, behavior),
MainFunction::Standard => standard(paths, behavior),
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_BACKUP)
.long(OPT_BACKUP)
@ -228,29 +253,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.value_name("CONTEXT")
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true).min_values(1))
.get_matches_from(args);
let paths: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
if let Err(s) = check_unimplemented(&matches) {
show_error!("Unimplemented feature: {}", s);
return 2;
}
let behavior = match behavior(&matches) {
Ok(x) => x,
Err(ret) => {
return ret;
}
};
match behavior.main_function {
MainFunction::Directory => directory(paths, behavior),
MainFunction::Standard => standard(paths, behavior),
}
}
/// Check for unimplemented command line arguments.

View file

@ -442,7 +442,72 @@ impl<'a> State<'a> {
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = App::new(NAME)
let matches = uu_app().get_matches_from(args);
let keys = parse_field_number_option(matches.value_of("j"));
let key1 = parse_field_number_option(matches.value_of("1"));
let key2 = parse_field_number_option(matches.value_of("2"));
let mut settings: Settings = Default::default();
if let Some(value) = matches.value_of("v") {
settings.print_unpaired = parse_file_number(value);
settings.print_joined = false;
} else if let Some(value) = matches.value_of("a") {
settings.print_unpaired = parse_file_number(value);
}
settings.ignore_case = matches.is_present("i");
settings.key1 = get_field_number(keys, key1);
settings.key2 = get_field_number(keys, key2);
if let Some(value) = matches.value_of("t") {
settings.separator = match value.len() {
0 => Sep::Line,
1 => Sep::Char(value.chars().next().unwrap()),
_ => crash!(1, "multi-character tab {}", value),
};
}
if let Some(format) = matches.value_of("o") {
if format == "auto" {
settings.autoformat = true;
} else {
settings.format = format
.split(|c| c == ' ' || c == ',' || c == '\t')
.map(Spec::parse)
.collect();
}
}
if let Some(empty) = matches.value_of("e") {
settings.empty = empty.to_string();
}
if matches.is_present("nocheck-order") {
settings.check_order = CheckOrder::Disabled;
}
if matches.is_present("check-order") {
settings.check_order = CheckOrder::Enabled;
}
if matches.is_present("header") {
settings.headers = true;
}
let file1 = matches.value_of("file1").unwrap();
let file2 = matches.value_of("file2").unwrap();
if file1 == "-" && file2 == "-" {
crash!(1, "both files cannot be standard input");
}
exec(file1, file2, &settings)
}
pub fn uu_app() -> App<'static, 'static> {
App::new(NAME)
.version(crate_version!())
.about(
"For each pair of input lines with identical join fields, write a line to
@ -542,68 +607,6 @@ FILENUM is 1 or 2, corresponding to FILE1 or FILE2",
.value_name("FILE2")
.hidden(true),
)
.get_matches_from(args);
let keys = parse_field_number_option(matches.value_of("j"));
let key1 = parse_field_number_option(matches.value_of("1"));
let key2 = parse_field_number_option(matches.value_of("2"));
let mut settings: Settings = Default::default();
if let Some(value) = matches.value_of("v") {
settings.print_unpaired = parse_file_number(value);
settings.print_joined = false;
} else if let Some(value) = matches.value_of("a") {
settings.print_unpaired = parse_file_number(value);
}
settings.ignore_case = matches.is_present("i");
settings.key1 = get_field_number(keys, key1);
settings.key2 = get_field_number(keys, key2);
if let Some(value) = matches.value_of("t") {
settings.separator = match value.len() {
0 => Sep::Line,
1 => Sep::Char(value.chars().next().unwrap()),
_ => crash!(1, "multi-character tab {}", value),
};
}
if let Some(format) = matches.value_of("o") {
if format == "auto" {
settings.autoformat = true;
} else {
settings.format = format
.split(|c| c == ' ' || c == ',' || c == '\t')
.map(Spec::parse)
.collect();
}
}
if let Some(empty) = matches.value_of("e") {
settings.empty = empty.to_string();
}
if matches.is_present("nocheck-order") {
settings.check_order = CheckOrder::Disabled;
}
if matches.is_present("check-order") {
settings.check_order = CheckOrder::Enabled;
}
if matches.is_present("header") {
settings.headers = true;
}
let file1 = matches.value_of("file1").unwrap();
let file2 = matches.value_of("file2").unwrap();
if file1 == "-" && file2 == "-" {
crash!(1, "both files cannot be standard input");
}
exec(file1, file2, &settings)
}
fn exec(file1: &str, file2: &str, settings: &Settings) -> i32 {

View file

@ -43,38 +43,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let (args, obs_signal) = handle_obsolete(args);
let usage = format!("{} [OPTIONS]... PID...", executable!());
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::LIST)
.short("l")
.long(options::LIST)
.help("Lists signals")
.conflicts_with(options::TABLE)
.conflicts_with(options::TABLE_OLD),
)
.arg(
Arg::with_name(options::TABLE)
.short("t")
.long(options::TABLE)
.help("Lists table of signals"),
)
.arg(Arg::with_name(options::TABLE_OLD).short("L").hidden(true))
.arg(
Arg::with_name(options::SIGNAL)
.short("s")
.long(options::SIGNAL)
.help("Sends given signal")
.takes_value(true),
)
.arg(
Arg::with_name(options::PIDS_OR_SIGNALS)
.hidden(true)
.multiple(true),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let mode = if matches.is_present(options::TABLE) || matches.is_present(options::TABLE_OLD) {
Mode::Table
@ -106,6 +75,39 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
EXIT_OK
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::LIST)
.short("l")
.long(options::LIST)
.help("Lists signals")
.conflicts_with(options::TABLE)
.conflicts_with(options::TABLE_OLD),
)
.arg(
Arg::with_name(options::TABLE)
.short("t")
.long(options::TABLE)
.help("Lists table of signals"),
)
.arg(Arg::with_name(options::TABLE_OLD).short("L").hidden(true))
.arg(
Arg::with_name(options::SIGNAL)
.short("s")
.long(options::SIGNAL)
.help("Sends given signal")
.takes_value(true),
)
.arg(
Arg::with_name(options::PIDS_OR_SIGNALS)
.hidden(true)
.multiple(true),
)
}
fn handle_obsolete(mut args: Vec<String>) -> (Vec<String>, Option<String>) {
let mut i = 0;
while i < args.len() {

View file

@ -32,19 +32,7 @@ pub fn normalize_error_message(e: Error) -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::FILES)
.hidden(true)
.required(true)
.min_values(2)
.max_values(2)
.takes_value(true),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let files: Vec<_> = matches
.values_of_os(options::FILES)
@ -61,3 +49,17 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::FILES)
.hidden(true)
.required(true)
.min_values(2)
.max_values(2)
.takes_value(true),
)
}

View file

@ -97,11 +97,71 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let long_usage = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&long_usage[..])
.get_matches_from(args);
/* the list of files */
let paths: Vec<PathBuf> = matches
.values_of(ARG_FILES)
.unwrap()
.map(PathBuf::from)
.collect();
let overwrite_mode = if matches.is_present(options::FORCE) {
OverwriteMode::Force
} else if matches.is_present(options::INTERACTIVE) {
OverwriteMode::Interactive
} else {
OverwriteMode::NoClobber
};
let backup_mode = if matches.is_present(options::B) {
BackupMode::ExistingBackup
} else if matches.is_present(options::BACKUP) {
match matches.value_of(options::BACKUP) {
None => BackupMode::ExistingBackup,
Some(mode) => match mode {
"simple" | "never" => BackupMode::SimpleBackup,
"numbered" | "t" => BackupMode::NumberedBackup,
"existing" | "nil" => BackupMode::ExistingBackup,
"none" | "off" => BackupMode::NoBackup,
_ => panic!(), // cannot happen as it is managed by clap
},
}
} else {
BackupMode::NoBackup
};
let backup_suffix = if matches.is_present(options::SUFFIX) {
matches.value_of(options::SUFFIX).unwrap()
} else {
"~"
};
let settings = Settings {
overwrite: overwrite_mode,
backup: backup_mode,
suffix: backup_suffix.to_string(),
symbolic: matches.is_present(options::SYMBOLIC),
relative: matches.is_present(options::RELATIVE),
target_dir: matches
.value_of(options::TARGET_DIRECTORY)
.map(String::from),
no_target_dir: matches.is_present(options::NO_TARGET_DIRECTORY),
no_dereference: matches.is_present(options::NO_DEREFERENCE),
verbose: matches.is_present(options::VERBOSE),
};
exec(&paths[..], &settings)
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(Arg::with_name(options::B).short(options::B).help(
"make a backup of each file that would otherwise be overwritten or \
removed",
@ -198,62 +258,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.required(true)
.min_values(1),
)
.get_matches_from(args);
/* the list of files */
let paths: Vec<PathBuf> = matches
.values_of(ARG_FILES)
.unwrap()
.map(PathBuf::from)
.collect();
let overwrite_mode = if matches.is_present(options::FORCE) {
OverwriteMode::Force
} else if matches.is_present(options::INTERACTIVE) {
OverwriteMode::Interactive
} else {
OverwriteMode::NoClobber
};
let backup_mode = if matches.is_present(options::B) {
BackupMode::ExistingBackup
} else if matches.is_present(options::BACKUP) {
match matches.value_of(options::BACKUP) {
None => BackupMode::ExistingBackup,
Some(mode) => match mode {
"simple" | "never" => BackupMode::SimpleBackup,
"numbered" | "t" => BackupMode::NumberedBackup,
"existing" | "nil" => BackupMode::ExistingBackup,
"none" | "off" => BackupMode::NoBackup,
_ => panic!(), // cannot happen as it is managed by clap
},
}
} else {
BackupMode::NoBackup
};
let backup_suffix = if matches.is_present(options::SUFFIX) {
matches.value_of(options::SUFFIX).unwrap()
} else {
"~"
};
let settings = Settings {
overwrite: overwrite_mode,
backup: backup_mode,
suffix: backup_suffix.to_string(),
symbolic: matches.is_present(options::SYMBOLIC),
relative: matches.is_present(options::RELATIVE),
target_dir: matches
.value_of(options::TARGET_DIRECTORY)
.map(String::from),
no_target_dir: matches.is_present(options::NO_TARGET_DIRECTORY),
no_dereference: matches.is_present(options::NO_DEREFERENCE),
verbose: matches.is_present(options::VERBOSE),
};
exec(&paths[..], &settings)
}
fn exec(files: &[PathBuf], settings: &Settings) -> i32 {

View file

@ -45,11 +45,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.accept_any();
let usage = get_usage();
let _ = App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
.usage(&usage[..])
.get_matches_from(args);
let _ = uu_app().usage(&usage[..]).get_matches_from(args);
match get_userlogin() {
Some(userlogin) => println!("{}", userlogin),
@ -58,3 +54,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(SUMMARY)
}

View file

@ -558,10 +558,22 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let app = App::new(executable!())
let app = uu_app().usage(&usage[..]);
let matches = app.get_matches_from(args);
let locs = matches
.values_of(options::PATHS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_else(|| vec![String::from(".")]);
list(locs, Config::from(matches))
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
// Format arguments
.arg(
@ -1095,16 +1107,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// Positional arguments
.arg(Arg::with_name(options::PATHS).multiple(true).takes_value(true))
.after_help(AFTER_HELP);
let matches = app.get_matches_from(args);
let locs = matches
.values_of(options::PATHS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_else(|| vec![String::from(".")]);
list(locs, Config::from(matches))
.after_help(AFTER_HELP)
}
/// Represents a Path along with it's associated data

View file

@ -32,10 +32,37 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// Linux-specific options, not implemented
// opts.optflag("Z", "context", "set SELinux security context" +
// " of each created directory to CTX"),
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let dirs: Vec<String> = matches
.values_of(ARG_DIRS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let verbose = matches.is_present(OPT_VERBOSE);
let recursive = matches.is_present(OPT_PARENTS);
// Translate a ~str in octal form to u16, default to 755
// Not tested on Windows
let mode_match = matches.value_of(OPT_MODE);
let mode: u16 = match mode_match {
Some(m) => {
let res: Option<u16> = u16::from_str_radix(m, 8).ok();
match res {
Some(r) => r,
_ => crash!(1, "no mode given"),
}
}
_ => 0o755_u16,
};
exec(dirs, recursive, mode, verbose)
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_MODE)
.short("m")
@ -62,31 +89,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true)
.min_values(1),
)
.get_matches_from(args);
let dirs: Vec<String> = matches
.values_of(ARG_DIRS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let verbose = matches.is_present(OPT_VERBOSE);
let recursive = matches.is_present(OPT_PARENTS);
// Translate a ~str in octal form to u16, default to 755
// Not tested on Windows
let mode_match = matches.value_of(OPT_MODE);
let mode: u16 = match mode_match {
Some(m) => {
let res: Option<u16> = u16::from_str_radix(m, 8).ok();
match res {
Some(r) => r,
_ => crash!(1, "no mode given"),
}
}
_ => 0o755_u16,
};
exec(dirs, recursive, mode, verbose)
}
/**

View file

@ -29,27 +29,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let matches = App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
.about(SUMMARY)
.arg(
Arg::with_name(options::MODE)
.short("m")
.long(options::MODE)
.help("file permissions for the fifo")
.default_value("0666")
.value_name("0666"),
)
.arg(
Arg::with_name(options::SE_LINUX_SECURITY_CONTEXT)
.short(options::SE_LINUX_SECURITY_CONTEXT)
.help("set the SELinux security context to default type")
)
.arg(Arg::with_name(options::CONTEXT).long(options::CONTEXT).value_name("CTX").help("like -Z, or if CTX is specified then set the SELinux\nor SMACK security context to CTX"))
.arg(Arg::with_name(options::FIFO).hidden(true).multiple(true))
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
if matches.is_present(options::CONTEXT) {
crash!(1, "--context is not implemented");
@ -88,3 +68,26 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
exit_code
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
.about(SUMMARY)
.arg(
Arg::with_name(options::MODE)
.short("m")
.long(options::MODE)
.help("file permissions for the fifo")
.default_value("0666")
.value_name("0666"),
)
.arg(
Arg::with_name(options::SE_LINUX_SECURITY_CONTEXT)
.short(options::SE_LINUX_SECURITY_CONTEXT)
.help("set the SELinux security context to default type")
)
.arg(Arg::with_name(options::CONTEXT).long(options::CONTEXT).value_name("CTX").help("like -Z, or if CTX is specified then set the SELinux\nor SMACK security context to CTX"))
.arg(Arg::with_name(options::FIFO).hidden(true).multiple(true))
}

View file

@ -89,48 +89,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
// opts.optflag("Z", "", "set the SELinux security context to default type");
// opts.optopt("", "context", "like -Z, or if CTX is specified then set the SELinux or SMACK security context to CTX");
let matches = App::new(executable!())
.version(crate_version!())
.usage(USAGE)
.after_help(LONG_HELP)
.about(ABOUT)
.arg(
Arg::with_name("mode")
.short("m")
.long("mode")
.value_name("MODE")
.help("set file permission bits to MODE, not a=rw - umask"),
)
.arg(
Arg::with_name("name")
.value_name("NAME")
.help("name of the new file")
.required(true)
.index(1),
)
.arg(
Arg::with_name("type")
.value_name("TYPE")
.help("type of the new file (b, c, u or p)")
.required(true)
.validator(valid_type)
.index(2),
)
.arg(
Arg::with_name("major")
.value_name("MAJOR")
.help("major file type")
.validator(valid_u64)
.index(3),
)
.arg(
Arg::with_name("minor")
.value_name("MINOR")
.help("minor file type")
.validator(valid_u64)
.index(4),
)
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let mode = match get_mode(&matches) {
Ok(mode) => mode,
@ -185,6 +144,50 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.usage(USAGE)
.after_help(LONG_HELP)
.about(ABOUT)
.arg(
Arg::with_name("mode")
.short("m")
.long("mode")
.value_name("MODE")
.help("set file permission bits to MODE, not a=rw - umask"),
)
.arg(
Arg::with_name("name")
.value_name("NAME")
.help("name of the new file")
.required(true)
.index(1),
)
.arg(
Arg::with_name("type")
.value_name("TYPE")
.help("type of the new file (b, c, u or p)")
.required(true)
.validator(valid_type)
.index(2),
)
.arg(
Arg::with_name("major")
.value_name("MAJOR")
.help("major file type")
.validator(valid_u64)
.index(3),
)
.arg(
Arg::with_name("minor")
.value_name("MINOR")
.help("minor file type")
.validator(valid_u64)
.index(4),
)
}
fn get_mode(matches: &ArgMatches) -> Result<mode_t, String> {
match matches.value_of("mode") {
None => Ok(MODE_RW_UGO),

View file

@ -40,61 +40,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_DIRECTORY)
.short("d")
.long(OPT_DIRECTORY)
.help("Make a directory instead of a file"),
)
.arg(
Arg::with_name(OPT_DRY_RUN)
.short("u")
.long(OPT_DRY_RUN)
.help("do not create anything; merely print a name (unsafe)"),
)
.arg(
Arg::with_name(OPT_QUIET)
.short("q")
.long("quiet")
.help("Fail silently if an error occurs."),
)
.arg(
Arg::with_name(OPT_SUFFIX)
.long(OPT_SUFFIX)
.help(
"append SUFFIX to TEMPLATE; SUFFIX must not contain a path separator. \
This option is implied if TEMPLATE does not end with X.",
)
.value_name("SUFFIX"),
)
.arg(
Arg::with_name(OPT_TMPDIR)
.short("p")
.long(OPT_TMPDIR)
.help(
"interpret TEMPLATE relative to DIR; if DIR is not specified, use \
$TMPDIR ($TMP on windows) if set, else /tmp. With this option, TEMPLATE must not \
be an absolute name; unlike with -t, TEMPLATE may contain \
slashes, but mktemp creates only the final component",
)
.value_name("DIR"),
)
.arg(Arg::with_name(OPT_T).short(OPT_T).help(
"Generate a template (using the supplied prefix and TMPDIR (TMP on windows) if set) \
to create a filename template [deprecated]",
))
.arg(
Arg::with_name(ARG_TEMPLATE)
.multiple(false)
.takes_value(true)
.max_values(1)
.default_value(DEFAULT_TEMPLATE),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let template = matches.value_of(ARG_TEMPLATE).unwrap();
let tmpdir = matches.value_of(OPT_TMPDIR).unwrap_or_default();
@ -171,6 +117,62 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_DIRECTORY)
.short("d")
.long(OPT_DIRECTORY)
.help("Make a directory instead of a file"),
)
.arg(
Arg::with_name(OPT_DRY_RUN)
.short("u")
.long(OPT_DRY_RUN)
.help("do not create anything; merely print a name (unsafe)"),
)
.arg(
Arg::with_name(OPT_QUIET)
.short("q")
.long("quiet")
.help("Fail silently if an error occurs."),
)
.arg(
Arg::with_name(OPT_SUFFIX)
.long(OPT_SUFFIX)
.help(
"append SUFFIX to TEMPLATE; SUFFIX must not contain a path separator. \
This option is implied if TEMPLATE does not end with X.",
)
.value_name("SUFFIX"),
)
.arg(
Arg::with_name(OPT_TMPDIR)
.short("p")
.long(OPT_TMPDIR)
.help(
"interpret TEMPLATE relative to DIR; if DIR is not specified, use \
$TMPDIR ($TMP on windows) if set, else /tmp. With this option, TEMPLATE must not \
be an absolute name; unlike with -t, TEMPLATE may contain \
slashes, but mktemp creates only the final component",
)
.value_name("DIR"),
)
.arg(Arg::with_name(OPT_T).short(OPT_T).help(
"Generate a template (using the supplied prefix and TMPDIR (TMP on windows) if set) \
to create a filename template [deprecated]",
))
.arg(
Arg::with_name(ARG_TEMPLATE)
.multiple(false)
.takes_value(true)
.max_values(1)
.default_value(DEFAULT_TEMPLATE),
)
}
fn parse_template(temp: &str) -> Option<(&str, usize, &str)> {
let right = match temp.rfind('X') {
Some(r) => r + 1,

View file

@ -51,7 +51,49 @@ pub mod options {
const MULTI_FILE_TOP_PROMPT: &str = "::::::::::::::\n{}\n::::::::::::::\n";
pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let mut buff = String::new();
let silent = matches.is_present(options::SILENT);
if let Some(files) = matches.values_of(options::FILES) {
let mut stdout = setup_term();
let length = files.len();
let mut files_iter = files.peekable();
while let (Some(file), next_file) = (files_iter.next(), files_iter.peek()) {
let file = Path::new(file);
if file.is_dir() {
terminal::disable_raw_mode().unwrap();
show_usage_error!("'{}' is a directory.", file.display());
return 1;
}
if !file.exists() {
terminal::disable_raw_mode().unwrap();
show_error!("cannot open {}: No such file or directory", file.display());
return 1;
}
if length > 1 {
buff.push_str(&MULTI_FILE_TOP_PROMPT.replace("{}", file.to_str().unwrap()));
}
let mut reader = BufReader::new(File::open(file).unwrap());
reader.read_to_string(&mut buff).unwrap();
more(&buff, &mut stdout, next_file.copied(), silent);
buff.clear();
}
reset_term(&mut stdout);
} else if atty::isnt(atty::Stream::Stdin) {
stdin().read_to_string(&mut buff).unwrap();
let mut stdout = setup_term();
more(&buff, &mut stdout, None, silent);
reset_term(&mut stdout);
} else {
show_usage_error!("bad usage");
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.about("A file perusal filter for CRT viewing.")
.version(crate_version!())
.arg(
@ -138,45 +180,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.multiple(true)
.help("Path to the files to be read"),
)
.get_matches_from(args);
let mut buff = String::new();
let silent = matches.is_present(options::SILENT);
if let Some(files) = matches.values_of(options::FILES) {
let mut stdout = setup_term();
let length = files.len();
let mut files_iter = files.peekable();
while let (Some(file), next_file) = (files_iter.next(), files_iter.peek()) {
let file = Path::new(file);
if file.is_dir() {
terminal::disable_raw_mode().unwrap();
show_usage_error!("'{}' is a directory.", file.display());
return 1;
}
if !file.exists() {
terminal::disable_raw_mode().unwrap();
show_error!("cannot open {}: No such file or directory", file.display());
return 1;
}
if length > 1 {
buff.push_str(&MULTI_FILE_TOP_PROMPT.replace("{}", file.to_str().unwrap()));
}
let mut reader = BufReader::new(File::open(file).unwrap());
reader.read_to_string(&mut buff).unwrap();
more(&buff, &mut stdout, next_file.copied(), silent);
buff.clear();
}
reset_term(&mut stdout);
} else if atty::isnt(atty::Stream::Stdin) {
stdin().read_to_string(&mut buff).unwrap();
let mut stdout = setup_term();
more(&buff, &mut stdout, None, silent);
reset_term(&mut stdout);
} else {
show_usage_error!("bad usage");
}
0
}
#[cfg(not(target_os = "fuchsia"))]

View file

@ -70,11 +70,64 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app()
.after_help(&*format!(
"{}\n{}",
LONG_HELP,
backup_control::BACKUP_CONTROL_LONG_HELP
))
.usage(&usage[..])
.get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let overwrite_mode = determine_overwrite_mode(&matches);
let backup_mode = backup_control::determine_backup_mode(
matches.is_present(OPT_BACKUP_NO_ARG) || matches.is_present(OPT_BACKUP),
matches.value_of(OPT_BACKUP),
);
if overwrite_mode == OverwriteMode::NoClobber && backup_mode != BackupMode::NoBackup {
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
return 1;
}
let backup_suffix = backup_control::determine_backup_suffix(matches.value_of(OPT_SUFFIX));
let behavior = Behavior {
overwrite: overwrite_mode,
backup: backup_mode,
suffix: backup_suffix,
update: matches.is_present(OPT_UPDATE),
target_dir: matches.value_of(OPT_TARGET_DIRECTORY).map(String::from),
no_target_dir: matches.is_present(OPT_NO_TARGET_DIRECTORY),
verbose: matches.is_present(OPT_VERBOSE),
};
let paths: Vec<PathBuf> = {
fn strip_slashes(p: &Path) -> &Path {
p.components().as_path()
}
let to_owned = |p: &Path| p.to_owned();
let paths = files.iter().map(Path::new);
if matches.is_present(OPT_STRIP_TRAILING_SLASHES) {
paths.map(strip_slashes).map(to_owned).collect()
} else {
paths.map(to_owned).collect()
}
};
exec(&paths[..], behavior)
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(&*format!("{}\n{}", LONG_HELP, backup_control::BACKUP_CONTROL_LONG_HELP))
.usage(&usage[..])
.arg(
Arg::with_name(OPT_BACKUP)
.long(OPT_BACKUP)
@ -153,51 +206,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.min_values(2)
.required(true)
)
.get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let overwrite_mode = determine_overwrite_mode(&matches);
let backup_mode = backup_control::determine_backup_mode(
matches.is_present(OPT_BACKUP_NO_ARG) || matches.is_present(OPT_BACKUP),
matches.value_of(OPT_BACKUP),
);
if overwrite_mode == OverwriteMode::NoClobber && backup_mode != BackupMode::NoBackup {
show_usage_error!("options --backup and --no-clobber are mutually exclusive");
return 1;
}
let backup_suffix = backup_control::determine_backup_suffix(matches.value_of(OPT_SUFFIX));
let behavior = Behavior {
overwrite: overwrite_mode,
backup: backup_mode,
suffix: backup_suffix,
update: matches.is_present(OPT_UPDATE),
target_dir: matches.value_of(OPT_TARGET_DIRECTORY).map(String::from),
no_target_dir: matches.is_present(OPT_NO_TARGET_DIRECTORY),
verbose: matches.is_present(OPT_VERBOSE),
};
let paths: Vec<PathBuf> = {
fn strip_slashes(p: &Path) -> &Path {
p.components().as_path()
}
let to_owned = |p: &Path| p.to_owned();
let paths = files.iter().map(Path::new);
if matches.is_present(OPT_STRIP_TRAILING_SLASHES) {
paths.map(strip_slashes).map(to_owned).collect()
} else {
paths.map(to_owned).collect()
}
};
exec(&paths[..], behavior)
}
fn determine_overwrite_mode(matches: &ArgMatches) -> OverwriteMode {

View file

@ -46,20 +46,7 @@ process).",
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.setting(AppSettings::TrailingVarArg)
.version(crate_version!())
.usage(&usage[..])
.arg(
Arg::with_name(options::ADJUSTMENT)
.short("n")
.long(options::ADJUSTMENT)
.help("add N to the niceness (default is 10)")
.takes_value(true)
.allow_hyphen_values(true),
)
.arg(Arg::with_name(options::COMMAND).multiple(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let mut niceness = unsafe {
nix::errno::Errno::clear();
@ -120,3 +107,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
126
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.setting(AppSettings::TrailingVarArg)
.version(crate_version!())
.arg(
Arg::with_name(options::ADJUSTMENT)
.short("n")
.long(options::ADJUSTMENT)
.help("add N to the niceness (default is 10)")
.takes_value(true)
.allow_hyphen_values(true),
)
.arg(Arg::with_name(options::COMMAND).multiple(true))
}

View file

@ -88,7 +88,62 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
// A mutable settings object, initialized with the defaults.
let mut settings = Settings {
header_numbering: NumberingStyle::NumberForNone,
body_numbering: NumberingStyle::NumberForAll,
footer_numbering: NumberingStyle::NumberForNone,
section_delimiter: ['\\', ':'],
starting_line_number: 1,
line_increment: 1,
join_blank_lines: 1,
number_width: 6,
number_format: NumberFormat::Right,
renumber: true,
number_separator: String::from("\t"),
};
// Update the settings from the command line options, and terminate the
// program if some options could not successfully be parsed.
let parse_errors = helper::parse_options(&mut settings, &matches);
if !parse_errors.is_empty() {
show_error!("Invalid arguments supplied.");
for message in &parse_errors {
println!("{}", message);
}
return 1;
}
let mut read_stdin = false;
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
for file in &files {
if file == "-" {
// If both file names and '-' are specified, we choose to treat first all
// regular files, and then read from stdin last.
read_stdin = true;
continue;
}
let path = Path::new(file);
let reader = File::open(path).unwrap();
let mut buffer = BufReader::new(reader);
nl(&mut buffer, &settings);
}
if read_stdin {
let mut buffer = BufReader::new(stdin());
nl(&mut buffer, &settings);
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
@ -169,58 +224,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.help("use NUMBER columns for line numbers")
.value_name("NUMBER"),
)
.get_matches_from(args);
// A mutable settings object, initialized with the defaults.
let mut settings = Settings {
header_numbering: NumberingStyle::NumberForNone,
body_numbering: NumberingStyle::NumberForAll,
footer_numbering: NumberingStyle::NumberForNone,
section_delimiter: ['\\', ':'],
starting_line_number: 1,
line_increment: 1,
join_blank_lines: 1,
number_width: 6,
number_format: NumberFormat::Right,
renumber: true,
number_separator: String::from("\t"),
};
// Update the settings from the command line options, and terminate the
// program if some options could not successfully be parsed.
let parse_errors = helper::parse_options(&mut settings, &matches);
if !parse_errors.is_empty() {
show_error!("Invalid arguments supplied.");
for message in &parse_errors {
println!("{}", message);
}
return 1;
}
let mut read_stdin = false;
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
for file in &files {
if file == "-" {
// If both file names and '-' are specified, we choose to treat first all
// regular files, and then read from stdin last.
read_stdin = true;
continue;
}
let path = Path::new(file);
let reader = File::open(path).unwrap();
let mut buffer = BufReader::new(reader);
nl(&mut buffer, &settings);
}
if read_stdin {
let mut buffer = BufReader::new(stdin());
nl(&mut buffer, &settings);
}
0
}
// nl implements the main functionality for an individual buffer.

View file

@ -45,19 +45,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::CMD)
.hidden(true)
.required(true)
.multiple(true),
)
.setting(AppSettings::TrailingVarArg)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
replace_fds();
@ -82,6 +70,20 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::CMD)
.hidden(true)
.required(true)
.multiple(true),
)
.setting(AppSettings::TrailingVarArg)
}
fn replace_fds() {
if atty::is(atty::Stream::Stdin) {
let new_stdin = match File::open(Path::new("/dev/null")) {

View file

@ -33,24 +33,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_ALL)
.short("")
.long(OPT_ALL)
.help("print the number of cores available to the system"),
)
.arg(
Arg::with_name(OPT_IGNORE)
.short("")
.long(OPT_IGNORE)
.takes_value(true)
.help("ignore up to N cores"),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let mut ignore = match matches.value_of(OPT_IGNORE) {
Some(numstr) => match numstr.parse() {
@ -86,6 +69,25 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_ALL)
.short("")
.long(OPT_ALL)
.help("print the number of cores available to the system"),
)
.arg(
Arg::with_name(OPT_IGNORE)
.short("")
.long(OPT_IGNORE)
.takes_value(true)
.help("ignore up to N cores"),
)
}
#[cfg(any(
target_os = "linux",
target_vendor = "apple",

View file

@ -156,10 +156,28 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let result =
parse_options(&matches).and_then(|options| match matches.values_of(options::NUMBER) {
Some(values) => handle_args(values, options),
None => handle_stdin(options),
});
match result {
Err(e) => {
std::io::stdout().flush().expect("error flushing stdout");
show_error!("{}", e);
1
}
_ => 0,
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.setting(AppSettings::AllowNegativeNumbers)
.arg(
@ -224,20 +242,4 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]),
)
.arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true))
.get_matches_from(args);
let result =
parse_options(&matches).and_then(|options| match matches.values_of(options::NUMBER) {
Some(values) => handle_args(values, options),
None => handle_stdin(options),
});
match result {
Err(e) => {
std::io::stdout().flush().expect("error flushing stdout");
show_error!("{}", e);
1
}
_ => 0,
}
}

View file

@ -214,7 +214,45 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let clap_opts = clap::App::new(executable!())
let clap_opts = uu_app();
let clap_matches = clap_opts
.clone() // Clone to reuse clap_opts to print help
.get_matches_from(args.clone());
let od_options = match OdOptions::new(clap_matches, args) {
Err(s) => {
crash!(1, "{}", s);
}
Ok(o) => o,
};
let mut input_offset =
InputOffset::new(od_options.radix, od_options.skip_bytes, od_options.label);
let mut input = open_input_peek_reader(
&od_options.input_strings,
od_options.skip_bytes,
od_options.read_bytes,
);
let mut input_decoder = InputDecoder::new(
&mut input,
od_options.line_bytes,
PEEK_BUFFER_SIZE,
od_options.byte_order,
);
let output_info = OutputInfo::new(
od_options.line_bytes,
&od_options.formats[..],
od_options.output_duplicates,
);
odfunc(&mut input_offset, &mut input_decoder, &output_info)
}
pub fn uu_app() -> clap::App<'static, 'static> {
clap::App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(USAGE)
@ -434,41 +472,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
AppSettings::DontDelimitTrailingValues,
AppSettings::DisableVersion,
AppSettings::DeriveDisplayOrder,
]);
let clap_matches = clap_opts
.clone() // Clone to reuse clap_opts to print help
.get_matches_from(args.clone());
let od_options = match OdOptions::new(clap_matches, args) {
Err(s) => {
crash!(1, "{}", s);
}
Ok(o) => o,
};
let mut input_offset =
InputOffset::new(od_options.radix, od_options.skip_bytes, od_options.label);
let mut input = open_input_peek_reader(
&od_options.input_strings,
od_options.skip_bytes,
od_options.read_bytes,
);
let mut input_decoder = InputDecoder::new(
&mut input,
od_options.line_bytes,
PEEK_BUFFER_SIZE,
od_options.byte_order,
);
let output_info = OutputInfo::new(
od_options.line_bytes,
&od_options.formats[..],
od_options.output_duplicates,
);
odfunc(&mut input_offset, &mut input_decoder, &output_info)
])
}
/// Loops through the input line by line, calling print_bytes to take care of the output.

View file

@ -37,7 +37,22 @@ fn read_line<R: Read>(
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let serial = matches.is_present(options::SERIAL);
let delimiters = matches.value_of(options::DELIMITER).unwrap().to_owned();
let files = matches
.values_of(options::FILE)
.unwrap()
.map(|s| s.to_owned())
.collect();
paste(files, serial, delimiters);
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
@ -61,18 +76,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.multiple(true)
.default_value("-"),
)
.get_matches_from(args);
let serial = matches.is_present(options::SERIAL);
let delimiters = matches.value_of(options::DELIMITER).unwrap().to_owned();
let files = matches
.values_of(options::FILE)
.unwrap()
.map(|s| s.to_owned())
.collect();
paste(files, serial, delimiters);
0
}
fn paste(filenames: Vec<String>, serial: bool, delimiters: String) {

View file

@ -49,27 +49,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::POSIX)
.short("p")
.help("check for most POSIX systems"),
)
.arg(
Arg::with_name(options::POSIX_SPECIAL)
.short("P")
.help(r#"check for empty names and leading "-""#),
)
.arg(
Arg::with_name(options::PORTABILITY)
.long(options::PORTABILITY)
.help("check for all POSIX systems (equivalent to -p -P)"),
)
.arg(Arg::with_name(options::PATH).hidden(true).multiple(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
// set working mode
let is_posix = matches.values_of(options::POSIX).is_some();
@ -115,6 +95,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::POSIX)
.short("p")
.help("check for most POSIX systems"),
)
.arg(
Arg::with_name(options::POSIX_SPECIAL)
.short("P")
.help(r#"check for empty names and leading "-""#),
)
.arg(
Arg::with_name(options::PORTABILITY)
.long(options::PORTABILITY)
.help("check for all POSIX systems (equivalent to -p -P)"),
)
.arg(Arg::with_name(options::PATH).hidden(true).multiple(true))
}
// check a path, given as a slice of it's components and an operating mode
fn check_path(mode: &Mode, path: &[String]) -> bool {
match *mode {

View file

@ -60,62 +60,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let after_help = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&after_help[..])
.arg(
Arg::with_name(options::LONG_FORMAT)
.short("l")
.requires(options::USER)
.help("produce long format output for the specified USERs"),
)
.arg(
Arg::with_name(options::OMIT_HOME_DIR)
.short("b")
.help("omit the user's home directory and shell in long format"),
)
.arg(
Arg::with_name(options::OMIT_PROJECT_FILE)
.short("h")
.help("omit the user's project file in long format"),
)
.arg(
Arg::with_name(options::OMIT_PLAN_FILE)
.short("p")
.help("omit the user's plan file in long format"),
)
.arg(
Arg::with_name(options::SHORT_FORMAT)
.short("s")
.help("do short format output, this is the default"),
)
.arg(
Arg::with_name(options::OMIT_HEADINGS)
.short("f")
.help("omit the line of column headings in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME)
.short("w")
.help("omit the user's full name in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME_HOST)
.short("i")
.help("omit the user's full name and remote host in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME_HOST_TIME)
.short("q")
.help("omit the user's full name, remote host and idle time in short format"),
)
.arg(
Arg::with_name(options::USER)
.takes_value(true)
.multiple(true),
)
.get_matches_from(args);
let users: Vec<String> = matches
@ -182,6 +129,63 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::LONG_FORMAT)
.short("l")
.requires(options::USER)
.help("produce long format output for the specified USERs"),
)
.arg(
Arg::with_name(options::OMIT_HOME_DIR)
.short("b")
.help("omit the user's home directory and shell in long format"),
)
.arg(
Arg::with_name(options::OMIT_PROJECT_FILE)
.short("h")
.help("omit the user's project file in long format"),
)
.arg(
Arg::with_name(options::OMIT_PLAN_FILE)
.short("p")
.help("omit the user's plan file in long format"),
)
.arg(
Arg::with_name(options::SHORT_FORMAT)
.short("s")
.help("do short format output, this is the default"),
)
.arg(
Arg::with_name(options::OMIT_HEADINGS)
.short("f")
.help("omit the line of column headings in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME)
.short("w")
.help("omit the user's full name in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME_HOST)
.short("i")
.help("omit the user's full name and remote host in short format"),
)
.arg(
Arg::with_name(options::OMIT_NAME_HOST_TIME)
.short("q")
.help("omit the user's full name, remote host and idle time in short format"),
)
.arg(
Arg::with_name(options::USER)
.takes_value(true)
.multiple(true),
)
}
struct Pinky {
include_idle: bool,
include_heading: bool,

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/pr.rs"
[dependencies]
clap = "2.33.3"
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["utmpx", "entries"] }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
getopts = "0.2.21"

View file

@ -23,6 +23,7 @@ use std::fs::{metadata, File};
use std::io::{stdin, stdout, BufRead, BufReader, Lines, Read, Stdout, Write};
#[cfg(unix)]
use std::os::unix::fs::FileTypeExt;
use uucore::executable;
type IOError = std::io::Error;
@ -167,6 +168,11 @@ quick_error! {
}
}
pub fn uu_app() -> clap::App<'static, 'static> {
// TODO: migrate to clap to get more shell completions
clap::App::new(executable!())
}
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args
.collect_str(uucore::InvalidEncodingHandling::Ignore)

View file

@ -26,23 +26,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_NULL)
.short("0")
.long(OPT_NULL)
.help("end each output line with 0 byte rather than newline"),
)
.arg(
Arg::with_name(ARG_VARIABLES)
.multiple(true)
.takes_value(true)
.min_values(1),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let variables: Vec<String> = matches
.values_of(ARG_VARIABLES)
@ -69,3 +53,21 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_NULL)
.short("0")
.long(OPT_NULL)
.help("end each output line with 0 byte rather than newline"),
)
.arg(
Arg::with_name(ARG_VARIABLES)
.multiple(true)
.takes_value(true)
.min_values(1),
)
}

View file

@ -18,6 +18,7 @@ edition = "2018"
path = "src/printf.rs"
[dependencies]
clap = "2.33.3"
itertools = "0.8.0"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -2,14 +2,18 @@
// spell-checker:ignore (change!) each's
// spell-checker:ignore (ToDO) LONGHELP FORMATSTRING templating parameterizing formatstr
#[macro_use]
extern crate uucore;
use clap::{crate_version, App, Arg};
use uucore::InvalidEncodingHandling;
mod cli;
mod memo;
mod tokenize;
static NAME: &str = "printf";
static VERSION: &str = env!("CARGO_PKG_VERSION");
const VERSION: &str = "version";
const HELP: &str = "help";
static LONGHELP_LEAD: &str = "printf
USAGE: printf FORMATSTRING [ARGUMENT]...
@ -290,10 +294,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if formatstr == "--help" {
print!("{} {}", LONGHELP_LEAD, LONGHELP_BODY);
} else if formatstr == "--version" {
println!("{} {}", NAME, VERSION);
println!("{} {}", executable!(), crate_version!());
} else {
let printf_args = &args[2..];
memo::Memo::run_all(formatstr, printf_args);
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.arg(Arg::with_name(VERSION).long(VERSION))
.arg(Arg::with_name(HELP).long(HELP))
}

View file

@ -638,7 +638,28 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.accept_any();
// let mut opts = Options::new();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let input_files: Vec<String> = match &matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
None => vec!["-".to_string()],
};
let config = get_config(&matches);
let word_filter = WordFilter::new(&matches, &config);
let file_map = read_input(&input_files, &config);
let word_set = create_word_set(&config, &word_filter, &file_map);
let output_file = if !config.gnu_ext && matches.args.len() == 2 {
matches.value_of(options::FILE).unwrap_or("-").to_string()
} else {
"-".to_owned()
};
write_traditional_output(&config, &file_map, &word_set, &output_file);
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(BRIEF)
@ -762,22 +783,4 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.value_name("NUMBER")
.takes_value(true),
)
.get_matches_from(args);
let input_files: Vec<String> = match &matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
None => vec!["-".to_string()],
};
let config = get_config(&matches);
let word_filter = WordFilter::new(&matches, &config);
let file_map = read_input(&input_files, &config);
let word_set = create_word_set(&config, &word_filter, &file_map);
let output_file = if !config.gnu_ext && matches.args.len() == 2 {
matches.value_of(options::FILE).unwrap_or("-").to_string()
} else {
"-".to_owned()
};
write_traditional_output(&config, &file_map, &word_set, &output_file);
0
}

View file

@ -39,23 +39,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_LOGICAL)
.short("L")
.long(OPT_LOGICAL)
.help("use PWD from environment, even if it contains symlinks"),
)
.arg(
Arg::with_name(OPT_PHYSICAL)
.short("P")
.long(OPT_PHYSICAL)
.help("avoid all symlinks"),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
match env::current_dir() {
Ok(logical_path) => {
@ -73,3 +57,21 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_LOGICAL)
.short("L")
.long(OPT_LOGICAL)
.help("use PWD from environment, even if it contains symlinks"),
)
.arg(
Arg::with_name(OPT_PHYSICAL)
.short("P")
.long(OPT_PHYSICAL)
.help("avoid all symlinks"),
)
}

View file

@ -35,69 +35,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_CANONICALIZE)
.short("f")
.long(OPT_CANONICALIZE)
.help(
"canonicalize by following every symlink in every component of the \
given name recursively; all but the last component must exist",
),
)
.arg(
Arg::with_name(OPT_CANONICALIZE_EXISTING)
.short("e")
.long("canonicalize-existing")
.help(
"canonicalize by following every symlink in every component of the \
given name recursively, all components must exist",
),
)
.arg(
Arg::with_name(OPT_CANONICALIZE_MISSING)
.short("m")
.long(OPT_CANONICALIZE_MISSING)
.help(
"canonicalize by following every symlink in every component of the \
given name recursively, without requirements on components existence",
),
)
.arg(
Arg::with_name(OPT_NO_NEWLINE)
.short("n")
.long(OPT_NO_NEWLINE)
.help("do not output the trailing delimiter"),
)
.arg(
Arg::with_name(OPT_QUIET)
.short("q")
.long(OPT_QUIET)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(OPT_SILENT)
.short("s")
.long(OPT_SILENT)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(OPT_VERBOSE)
.short("v")
.long(OPT_VERBOSE)
.help("report error message"),
)
.arg(
Arg::with_name(OPT_ZERO)
.short("z")
.long(OPT_ZERO)
.help("separate output with NUL rather than newline"),
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let mut no_newline = matches.is_present(OPT_NO_NEWLINE);
let use_zero = matches.is_present(OPT_ZERO);
@ -159,6 +97,70 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_CANONICALIZE)
.short("f")
.long(OPT_CANONICALIZE)
.help(
"canonicalize by following every symlink in every component of the \
given name recursively; all but the last component must exist",
),
)
.arg(
Arg::with_name(OPT_CANONICALIZE_EXISTING)
.short("e")
.long("canonicalize-existing")
.help(
"canonicalize by following every symlink in every component of the \
given name recursively, all components must exist",
),
)
.arg(
Arg::with_name(OPT_CANONICALIZE_MISSING)
.short("m")
.long(OPT_CANONICALIZE_MISSING)
.help(
"canonicalize by following every symlink in every component of the \
given name recursively, without requirements on components existence",
),
)
.arg(
Arg::with_name(OPT_NO_NEWLINE)
.short("n")
.long(OPT_NO_NEWLINE)
.help("do not output the trailing delimiter"),
)
.arg(
Arg::with_name(OPT_QUIET)
.short("q")
.long(OPT_QUIET)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(OPT_SILENT)
.short("s")
.long(OPT_SILENT)
.help("suppress most error messages"),
)
.arg(
Arg::with_name(OPT_VERBOSE)
.short("v")
.long(OPT_VERBOSE)
.help("report error message"),
)
.arg(
Arg::with_name(OPT_ZERO)
.short("z")
.long(OPT_ZERO)
.help("separate output with NUL rather than newline"),
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
}
fn show(path: &Path, no_newline: bool, use_zero: bool) {
let path = path.to_str().unwrap();
if use_zero {

View file

@ -29,10 +29,35 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
/* the list of files */
let paths: Vec<PathBuf> = matches
.values_of(ARG_FILES)
.unwrap()
.map(PathBuf::from)
.collect();
let strip = matches.is_present(OPT_STRIP);
let zero = matches.is_present(OPT_ZERO);
let quiet = matches.is_present(OPT_QUIET);
let mut retcode = 0;
for path in &paths {
if let Err(e) = resolve_path(path, strip, zero) {
if !quiet {
show_error!("{}: {}", e, path.display());
}
retcode = 1
};
}
retcode
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_QUIET)
.short("q")
@ -58,29 +83,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.required(true)
.min_values(1),
)
.get_matches_from(args);
/* the list of files */
let paths: Vec<PathBuf> = matches
.values_of(ARG_FILES)
.unwrap()
.map(PathBuf::from)
.collect();
let strip = matches.is_present(OPT_STRIP);
let zero = matches.is_present(OPT_ZERO);
let quiet = matches.is_present(OPT_QUIET);
let mut retcode = 0;
for path in &paths {
if let Err(e) = resolve_path(path, strip, zero) {
if !quiet {
show_error!("{}: {}", e, path.display());
}
retcode = 1
};
}
retcode
}
/// Resolve a path to an absolute form and print it.

View file

@ -35,26 +35,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.accept_any();
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::DIR)
.short("d")
.takes_value(true)
.help("If any of FROM and TO is not subpath of DIR, output absolute path instead of relative"),
)
.arg(
Arg::with_name(options::TO)
.required(true)
.takes_value(true),
)
.arg(
Arg::with_name(options::FROM)
.takes_value(true),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let to = Path::new(matches.value_of(options::TO).unwrap()).to_path_buf(); // required
let from = match matches.value_of(options::FROM) {
@ -99,3 +80,24 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
println!("{}", result.display());
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::DIR)
.short("d")
.takes_value(true)
.help("If any of FROM and TO is not subpath of DIR, output absolute path instead of relative"),
)
.arg(
Arg::with_name(options::TO)
.required(true)
.takes_value(true),
)
.arg(
Arg::with_name(options::FROM)
.takes_value(true),
)
}

View file

@ -77,11 +77,72 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let long_usage = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&long_usage[..])
.get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let force = matches.is_present(OPT_FORCE);
if files.is_empty() && !force {
// Still check by hand and not use clap
// Because "rm -f" is a thing
show_error!("missing an argument");
show_error!("for help, try '{0} --help'", executable!());
return 1;
} else {
let options = Options {
force,
interactive: {
if matches.is_present(OPT_PROMPT) {
InteractiveMode::Always
} else if matches.is_present(OPT_PROMPT_MORE) {
InteractiveMode::Once
} else if matches.is_present(OPT_INTERACTIVE) {
match matches.value_of(OPT_INTERACTIVE).unwrap() {
"none" => InteractiveMode::None,
"once" => InteractiveMode::Once,
"always" => InteractiveMode::Always,
val => crash!(1, "Invalid argument to interactive ({})", val),
}
} else {
InteractiveMode::None
}
},
one_fs: matches.is_present(OPT_ONE_FILE_SYSTEM),
preserve_root: !matches.is_present(OPT_NO_PRESERVE_ROOT),
recursive: matches.is_present(OPT_RECURSIVE) || matches.is_present(OPT_RECURSIVE_R),
dir: matches.is_present(OPT_DIR),
verbose: matches.is_present(OPT_VERBOSE),
};
if options.interactive == InteractiveMode::Once && (options.recursive || files.len() > 3) {
let msg = if options.recursive {
"Remove all arguments recursively? "
} else {
"Remove all arguments? "
};
if !prompt(msg) {
return 0;
}
}
if remove(files, options) {
return 1;
}
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_FORCE)
@ -151,63 +212,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true)
.min_values(1)
)
.get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let force = matches.is_present(OPT_FORCE);
if files.is_empty() && !force {
// Still check by hand and not use clap
// Because "rm -f" is a thing
show_error!("missing an argument");
show_error!("for help, try '{0} --help'", executable!());
return 1;
} else {
let options = Options {
force,
interactive: {
if matches.is_present(OPT_PROMPT) {
InteractiveMode::Always
} else if matches.is_present(OPT_PROMPT_MORE) {
InteractiveMode::Once
} else if matches.is_present(OPT_INTERACTIVE) {
match matches.value_of(OPT_INTERACTIVE).unwrap() {
"none" => InteractiveMode::None,
"once" => InteractiveMode::Once,
"always" => InteractiveMode::Always,
val => crash!(1, "Invalid argument to interactive ({})", val),
}
} else {
InteractiveMode::None
}
},
one_fs: matches.is_present(OPT_ONE_FILE_SYSTEM),
preserve_root: !matches.is_present(OPT_NO_PRESERVE_ROOT),
recursive: matches.is_present(OPT_RECURSIVE) || matches.is_present(OPT_RECURSIVE_R),
dir: matches.is_present(OPT_DIR),
verbose: matches.is_present(OPT_VERBOSE),
};
if options.interactive == InteractiveMode::Once && (options.recursive || files.len() > 3) {
let msg = if options.recursive {
"Remove all arguments recursively? "
} else {
"Remove all arguments? "
};
if !prompt(msg) {
return 0;
}
}
if remove(files, options) {
return 1;
}
}
0
}
// TODO: implement one-file-system (this may get partially implemented in walkdir)

View file

@ -33,10 +33,29 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let dirs: Vec<String> = matches
.values_of(ARG_DIRS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let ignore = matches.is_present(OPT_IGNORE_FAIL_NON_EMPTY);
let parents = matches.is_present(OPT_PARENTS);
let verbose = matches.is_present(OPT_VERBOSE);
match remove(dirs, ignore, parents, verbose) {
Ok(()) => ( /* pass */ ),
Err(e) => return e,
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_IGNORE_FAIL_NON_EMPTY)
.long(OPT_IGNORE_FAIL_NON_EMPTY)
@ -64,23 +83,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.min_values(1)
.required(true),
)
.get_matches_from(args);
let dirs: Vec<String> = matches
.values_of(ARG_DIRS)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let ignore = matches.is_present(OPT_IGNORE_FAIL_NON_EMPTY);
let parents = matches.is_present(OPT_PARENTS);
let verbose = matches.is_present(OPT_VERBOSE);
match remove(dirs, ignore, parents, verbose) {
Ok(()) => ( /* pass */ ),
Err(e) => return e,
}
0
}
fn remove(dirs: Vec<String>, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32> {

View file

@ -87,42 +87,7 @@ impl FromStr for Number {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.setting(AppSettings::AllowLeadingHyphen)
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(OPT_SEPARATOR)
.short("s")
.long("separator")
.help("Separator character (defaults to \\n)")
.takes_value(true)
.number_of_values(1),
)
.arg(
Arg::with_name(OPT_TERMINATOR)
.short("t")
.long("terminator")
.help("Terminator character (defaults to \\n)")
.takes_value(true)
.number_of_values(1),
)
.arg(
Arg::with_name(OPT_WIDTHS)
.short("w")
.long("widths")
.help("Equalize widths of all numbers by padding with zeros"),
)
.arg(
Arg::with_name(ARG_NUMBERS)
.multiple(true)
.takes_value(true)
.allow_hyphen_values(true)
.max_values(3)
.required(true),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let numbers = matches.values_of(ARG_NUMBERS).unwrap().collect::<Vec<_>>();
@ -197,6 +162,43 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.setting(AppSettings::AllowLeadingHyphen)
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(OPT_SEPARATOR)
.short("s")
.long("separator")
.help("Separator character (defaults to \\n)")
.takes_value(true)
.number_of_values(1),
)
.arg(
Arg::with_name(OPT_TERMINATOR)
.short("t")
.long("terminator")
.help("Terminator character (defaults to \\n)")
.takes_value(true)
.number_of_values(1),
)
.arg(
Arg::with_name(OPT_WIDTHS)
.short("w")
.long("widths")
.help("Equalize widths of all numbers by padding with zeros"),
)
.arg(
Arg::with_name(ARG_NUMBERS)
.multiple(true)
.takes_value(true)
.allow_hyphen_values(true)
.max_values(3)
.required(true),
)
}
fn done_printing<T: Num + PartialOrd>(next: &T, increment: &T, last: &T) -> bool {
if increment >= &T::zero() {
next > last

View file

@ -272,62 +272,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let app = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(AFTER_HELP)
.usage(&usage[..])
.arg(
Arg::with_name(options::FORCE)
.long(options::FORCE)
.short("f")
.help("change permissions to allow writing if necessary"),
)
.arg(
Arg::with_name(options::ITERATIONS)
.long(options::ITERATIONS)
.short("n")
.help("overwrite N times instead of the default (3)")
.value_name("NUMBER")
.default_value("3"),
)
.arg(
Arg::with_name(options::SIZE)
.long(options::SIZE)
.short("s")
.takes_value(true)
.value_name("N")
.help("shred this many bytes (suffixes like K, M, G accepted)"),
)
.arg(
Arg::with_name(options::REMOVE)
.short("u")
.long(options::REMOVE)
.help("truncate and remove file after overwriting; See below"),
)
.arg(
Arg::with_name(options::VERBOSE)
.long(options::VERBOSE)
.short("v")
.help("show progress"),
)
.arg(
Arg::with_name(options::EXACT)
.long(options::EXACT)
.short("x")
.help(
"do not round file sizes up to the next full block;\n\
this is the default for non-regular files",
),
)
.arg(
Arg::with_name(options::ZERO)
.long(options::ZERO)
.short("z")
.help("add a final overwrite with zeros to hide shredding"),
)
// Positional arguments
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true));
let app = uu_app().usage(&usage[..]);
let matches = app.get_matches_from(args);
@ -384,6 +329,64 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help(AFTER_HELP)
.arg(
Arg::with_name(options::FORCE)
.long(options::FORCE)
.short("f")
.help("change permissions to allow writing if necessary"),
)
.arg(
Arg::with_name(options::ITERATIONS)
.long(options::ITERATIONS)
.short("n")
.help("overwrite N times instead of the default (3)")
.value_name("NUMBER")
.default_value("3"),
)
.arg(
Arg::with_name(options::SIZE)
.long(options::SIZE)
.short("s")
.takes_value(true)
.value_name("N")
.help("shred this many bytes (suffixes like K, M, G accepted)"),
)
.arg(
Arg::with_name(options::REMOVE)
.short("u")
.long(options::REMOVE)
.help("truncate and remove file after overwriting; See below"),
)
.arg(
Arg::with_name(options::VERBOSE)
.long(options::VERBOSE)
.short("v")
.help("show progress"),
)
.arg(
Arg::with_name(options::EXACT)
.long(options::EXACT)
.short("x")
.help(
"do not round file sizes up to the next full block;\n\
this is the default for non-regular files",
),
)
.arg(
Arg::with_name(options::ZERO)
.long(options::ZERO)
.short("z")
.help("add a final overwrite with zeros to hide shredding"),
)
// Positional arguments
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
}
// TODO: Add support for all postfixes here up to and including EiB
// http://www.gnu.org/software/coreutils/manual/coreutils.html#Block-size
fn get_size(size_str_opt: Option<String>) -> Option<u64> {

View file

@ -56,7 +56,66 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let mode = if let Some(args) = matches.values_of(options::ECHO) {
Mode::Echo(args.map(String::from).collect())
} else if let Some(range) = matches.value_of(options::INPUT_RANGE) {
match parse_range(range) {
Ok(m) => Mode::InputRange(m),
Err(msg) => {
crash!(1, "{}", msg);
}
}
} else {
Mode::Default(matches.value_of(options::FILE).unwrap_or("-").to_string())
};
let options = Options {
head_count: match matches.value_of(options::HEAD_COUNT) {
Some(count) => match count.parse::<usize>() {
Ok(val) => val,
Err(_) => {
show_error!("invalid line count: '{}'", count);
return 1;
}
},
None => std::usize::MAX,
},
output: matches.value_of(options::OUTPUT).map(String::from),
random_source: matches.value_of(options::RANDOM_SOURCE).map(String::from),
repeat: matches.is_present(options::REPEAT),
sep: if matches.is_present(options::ZERO_TERMINATED) {
0x00_u8
} else {
0x0a_u8
},
};
match mode {
Mode::Echo(args) => {
let mut evec = args.iter().map(String::as_bytes).collect::<Vec<_>>();
find_seps(&mut evec, options.sep);
shuf_bytes(&mut evec, options);
}
Mode::InputRange((b, e)) => {
let rvec = (b..e).map(|x| format!("{}", x)).collect::<Vec<String>>();
let mut rvec = rvec.iter().map(String::as_bytes).collect::<Vec<&[u8]>>();
shuf_bytes(&mut rvec, options);
}
Mode::Default(filename) => {
let fdata = read_input_file(&filename);
let mut fdata = vec![&fdata[..]];
find_seps(&mut fdata, options.sep);
shuf_bytes(&mut fdata, options);
}
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.template(TEMPLATE)
@ -118,62 +177,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.help("line delimiter is NUL, not newline"),
)
.arg(Arg::with_name(options::FILE).takes_value(true))
.get_matches_from(args);
let mode = if let Some(args) = matches.values_of(options::ECHO) {
Mode::Echo(args.map(String::from).collect())
} else if let Some(range) = matches.value_of(options::INPUT_RANGE) {
match parse_range(range) {
Ok(m) => Mode::InputRange(m),
Err(msg) => {
crash!(1, "{}", msg);
}
}
} else {
Mode::Default(matches.value_of(options::FILE).unwrap_or("-").to_string())
};
let options = Options {
head_count: match matches.value_of(options::HEAD_COUNT) {
Some(count) => match count.parse::<usize>() {
Ok(val) => val,
Err(_) => {
show_error!("invalid line count: '{}'", count);
return 1;
}
},
None => std::usize::MAX,
},
output: matches.value_of(options::OUTPUT).map(String::from),
random_source: matches.value_of(options::RANDOM_SOURCE).map(String::from),
repeat: matches.is_present(options::REPEAT),
sep: if matches.is_present(options::ZERO_TERMINATED) {
0x00_u8
} else {
0x0a_u8
},
};
match mode {
Mode::Echo(args) => {
let mut evec = args.iter().map(String::as_bytes).collect::<Vec<_>>();
find_seps(&mut evec, options.sep);
shuf_bytes(&mut evec, options);
}
Mode::InputRange((b, e)) => {
let rvec = (b..e).map(|x| format!("{}", x)).collect::<Vec<String>>();
let mut rvec = rvec.iter().map(String::as_bytes).collect::<Vec<&[u8]>>();
shuf_bytes(&mut rvec, options);
}
Mode::Default(filename) => {
let fdata = read_input_file(&filename);
let mut fdata = vec![&fdata[..]];
find_seps(&mut fdata, options.sep);
shuf_bytes(&mut fdata, options);
}
}
0
}
fn read_input_file(filename: &str) -> Vec<u8> {

View file

@ -35,10 +35,20 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
if let Some(values) = matches.values_of(options::NUMBER) {
let numbers = values.collect();
sleep(numbers);
}
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.arg(
Arg::with_name(options::NUMBER)
@ -49,14 +59,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.multiple(true)
.required(true),
)
.get_matches_from(args);
if let Some(values) = matches.values_of(options::NUMBER) {
let numbers = values.collect();
sleep(numbers);
}
0
}
fn sleep(args: Vec<&str>) {

View file

@ -944,10 +944,170 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let mut settings: GlobalSettings = Default::default();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
settings.debug = matches.is_present(options::DEBUG);
// check whether user specified a zero terminated list of files for input, otherwise read files from args
let mut files: Vec<String> = if matches.is_present(options::FILES0_FROM) {
let files0_from: Vec<String> = matches
.values_of(options::FILES0_FROM)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let mut files = Vec::new();
for path in &files0_from {
let reader = open(path.as_str());
let buf_reader = BufReader::new(reader);
for line in buf_reader.split(b'\0').flatten() {
files.push(
std::str::from_utf8(&line)
.expect("Could not parse string from zero terminated input.")
.to_string(),
);
}
}
files
} else {
matches
.values_of(options::FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default()
};
settings.mode = if matches.is_present(options::modes::HUMAN_NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("human-numeric")
{
SortMode::HumanNumeric
} else if matches.is_present(options::modes::MONTH)
|| matches.value_of(options::modes::SORT) == Some("month")
{
SortMode::Month
} else if matches.is_present(options::modes::GENERAL_NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("general-numeric")
{
SortMode::GeneralNumeric
} else if matches.is_present(options::modes::NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("numeric")
{
SortMode::Numeric
} else if matches.is_present(options::modes::VERSION)
|| matches.value_of(options::modes::SORT) == Some("version")
{
SortMode::Version
} else if matches.is_present(options::modes::RANDOM)
|| matches.value_of(options::modes::SORT) == Some("random")
{
settings.salt = get_rand_string();
SortMode::Random
} else {
SortMode::Default
};
settings.dictionary_order = matches.is_present(options::DICTIONARY_ORDER);
settings.ignore_non_printing = matches.is_present(options::IGNORE_NONPRINTING);
if matches.is_present(options::PARALLEL) {
// "0" is default - threads = num of cores
settings.threads = matches
.value_of(options::PARALLEL)
.map(String::from)
.unwrap_or_else(|| "0".to_string());
env::set_var("RAYON_NUM_THREADS", &settings.threads);
}
settings.buffer_size = matches
.value_of(options::BUF_SIZE)
.map_or(DEFAULT_BUF_SIZE, |s| {
GlobalSettings::parse_byte_count(s)
.unwrap_or_else(|e| crash!(2, "{}", format_error_message(e, s, options::BUF_SIZE)))
});
settings.tmp_dir = matches
.value_of(options::TMP_DIR)
.map(PathBuf::from)
.unwrap_or_else(env::temp_dir);
settings.compress_prog = matches.value_of(options::COMPRESS_PROG).map(String::from);
if let Some(n_merge) = matches.value_of(options::BATCH_SIZE) {
settings.merge_batch_size = n_merge
.parse()
.unwrap_or_else(|_| crash!(2, "invalid --batch-size argument '{}'", n_merge));
}
settings.zero_terminated = matches.is_present(options::ZERO_TERMINATED);
settings.merge = matches.is_present(options::MERGE);
settings.check = matches.is_present(options::check::CHECK);
if matches.is_present(options::check::CHECK_SILENT)
|| matches!(
matches.value_of(options::check::CHECK),
Some(options::check::SILENT) | Some(options::check::QUIET)
)
{
settings.check_silent = true;
settings.check = true;
};
settings.ignore_case = matches.is_present(options::IGNORE_CASE);
settings.ignore_leading_blanks = matches.is_present(options::IGNORE_LEADING_BLANKS);
settings.output_file = matches.value_of(options::OUTPUT).map(String::from);
settings.reverse = matches.is_present(options::REVERSE);
settings.stable = matches.is_present(options::STABLE);
settings.unique = matches.is_present(options::UNIQUE);
if files.is_empty() {
/* if no file, default to stdin */
files.push("-".to_owned());
} else if settings.check && files.len() != 1 {
crash!(1, "extra operand `{}' not allowed with -c", files[1])
}
if let Some(arg) = matches.args.get(options::SEPARATOR) {
let separator = arg.vals[0].to_string_lossy();
let separator = separator;
if separator.len() != 1 {
crash!(1, "separator must be exactly one character long");
}
settings.separator = Some(separator.chars().next().unwrap())
}
if let Some(values) = matches.values_of(options::KEY) {
for value in values {
settings
.selectors
.push(FieldSelector::parse(value, &settings));
}
}
if !matches.is_present(options::KEY) {
// add a default selector matching the whole line
let key_settings = KeySettings::from(&settings);
settings.selectors.push(
FieldSelector::new(
KeyPosition {
field: 1,
char: 1,
ignore_blanks: key_settings.ignore_blanks,
},
None,
key_settings,
)
.unwrap(),
);
}
settings.init_precomputed();
exec(&files, &settings)
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::modes::SORT)
.long(options::modes::SORT)
@ -1169,164 +1329,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.help("underline the parts of the line that are actually used for sorting"),
)
.arg(Arg::with_name(options::FILES).multiple(true).takes_value(true))
.get_matches_from(args);
settings.debug = matches.is_present(options::DEBUG);
// check whether user specified a zero terminated list of files for input, otherwise read files from args
let mut files: Vec<String> = if matches.is_present(options::FILES0_FROM) {
let files0_from: Vec<String> = matches
.values_of(options::FILES0_FROM)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let mut files = Vec::new();
for path in &files0_from {
let reader = open(path.as_str());
let buf_reader = BufReader::new(reader);
for line in buf_reader.split(b'\0').flatten() {
files.push(
std::str::from_utf8(&line)
.expect("Could not parse string from zero terminated input.")
.to_string(),
);
}
}
files
} else {
matches
.values_of(options::FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default()
};
settings.mode = if matches.is_present(options::modes::HUMAN_NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("human-numeric")
{
SortMode::HumanNumeric
} else if matches.is_present(options::modes::MONTH)
|| matches.value_of(options::modes::SORT) == Some("month")
{
SortMode::Month
} else if matches.is_present(options::modes::GENERAL_NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("general-numeric")
{
SortMode::GeneralNumeric
} else if matches.is_present(options::modes::NUMERIC)
|| matches.value_of(options::modes::SORT) == Some("numeric")
{
SortMode::Numeric
} else if matches.is_present(options::modes::VERSION)
|| matches.value_of(options::modes::SORT) == Some("version")
{
SortMode::Version
} else if matches.is_present(options::modes::RANDOM)
|| matches.value_of(options::modes::SORT) == Some("random")
{
settings.salt = get_rand_string();
SortMode::Random
} else {
SortMode::Default
};
settings.dictionary_order = matches.is_present(options::DICTIONARY_ORDER);
settings.ignore_non_printing = matches.is_present(options::IGNORE_NONPRINTING);
if matches.is_present(options::PARALLEL) {
// "0" is default - threads = num of cores
settings.threads = matches
.value_of(options::PARALLEL)
.map(String::from)
.unwrap_or_else(|| "0".to_string());
env::set_var("RAYON_NUM_THREADS", &settings.threads);
}
settings.buffer_size = matches
.value_of(options::BUF_SIZE)
.map_or(DEFAULT_BUF_SIZE, |s| {
GlobalSettings::parse_byte_count(s)
.unwrap_or_else(|e| crash!(2, "{}", format_error_message(e, s, options::BUF_SIZE)))
});
settings.tmp_dir = matches
.value_of(options::TMP_DIR)
.map(PathBuf::from)
.unwrap_or_else(env::temp_dir);
settings.compress_prog = matches.value_of(options::COMPRESS_PROG).map(String::from);
if let Some(n_merge) = matches.value_of(options::BATCH_SIZE) {
settings.merge_batch_size = n_merge
.parse()
.unwrap_or_else(|_| crash!(2, "invalid --batch-size argument '{}'", n_merge));
}
settings.zero_terminated = matches.is_present(options::ZERO_TERMINATED);
settings.merge = matches.is_present(options::MERGE);
settings.check = matches.is_present(options::check::CHECK);
if matches.is_present(options::check::CHECK_SILENT)
|| matches!(
matches.value_of(options::check::CHECK),
Some(options::check::SILENT) | Some(options::check::QUIET)
)
{
settings.check_silent = true;
settings.check = true;
};
settings.ignore_case = matches.is_present(options::IGNORE_CASE);
settings.ignore_leading_blanks = matches.is_present(options::IGNORE_LEADING_BLANKS);
settings.output_file = matches.value_of(options::OUTPUT).map(String::from);
settings.reverse = matches.is_present(options::REVERSE);
settings.stable = matches.is_present(options::STABLE);
settings.unique = matches.is_present(options::UNIQUE);
if files.is_empty() {
/* if no file, default to stdin */
files.push("-".to_owned());
} else if settings.check && files.len() != 1 {
crash!(1, "extra operand `{}' not allowed with -c", files[1])
}
if let Some(arg) = matches.args.get(options::SEPARATOR) {
let separator = arg.vals[0].to_string_lossy();
let separator = separator;
if separator.len() != 1 {
crash!(1, "separator must be exactly one character long");
}
settings.separator = Some(separator.chars().next().unwrap())
}
if let Some(values) = matches.values_of(options::KEY) {
for value in values {
settings
.selectors
.push(FieldSelector::parse(value, &settings));
}
}
if !matches.is_present(options::KEY) {
// add a default selector matching the whole line
let key_settings = KeySettings::from(&settings);
settings.selectors.push(
FieldSelector::new(
KeyPosition {
field: 1,
char: 1,
ignore_blanks: key_settings.ignore_blanks,
},
None,
key_settings,
)
.unwrap(),
);
}
settings.init_precomputed();
exec(&files, &settings)
}
fn exec(files: &[String], settings: &GlobalSettings) -> i32 {

View file

@ -30,7 +30,7 @@ static OPT_ADDITIONAL_SUFFIX: &str = "additional-suffix";
static OPT_FILTER: &str = "filter";
static OPT_NUMERIC_SUFFIXES: &str = "numeric-suffixes";
static OPT_SUFFIX_LENGTH: &str = "suffix-length";
static OPT_DEFAULT_SUFFIX_LENGTH: usize = 2;
static OPT_DEFAULT_SUFFIX_LENGTH: &str = "2";
static OPT_VERBOSE: &str = "verbose";
static ARG_INPUT: &str = "input";
@ -54,85 +54,10 @@ size is 1000, and default PREFIX is 'x'. With no INPUT, or when INPUT is
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let long_usage = get_long_usage();
let default_suffix_length_str = OPT_DEFAULT_SUFFIX_LENGTH.to_string();
let matches = App::new(executable!())
.version(crate_version!())
.about("Create output files containing consecutive or interleaved sections of input")
let matches = uu_app()
.usage(&usage[..])
.after_help(&long_usage[..])
// strategy (mutually exclusive)
.arg(
Arg::with_name(OPT_BYTES)
.short("b")
.long(OPT_BYTES)
.takes_value(true)
.default_value("2")
.help("use suffixes of length N (default 2)"),
)
.arg(
Arg::with_name(OPT_LINE_BYTES)
.short("C")
.long(OPT_LINE_BYTES)
.takes_value(true)
.default_value("2")
.help("put at most SIZE bytes of lines per output file"),
)
.arg(
Arg::with_name(OPT_LINES)
.short("l")
.long(OPT_LINES)
.takes_value(true)
.default_value("1000")
.help("write to shell COMMAND file name is $FILE (Currently not implemented for Windows)"),
)
// rest of the arguments
.arg(
Arg::with_name(OPT_ADDITIONAL_SUFFIX)
.long(OPT_ADDITIONAL_SUFFIX)
.takes_value(true)
.default_value("")
.help("additional suffix to append to output file names"),
)
.arg(
Arg::with_name(OPT_FILTER)
.long(OPT_FILTER)
.takes_value(true)
.help("write to shell COMMAND file name is $FILE (Currently not implemented for Windows)"),
)
.arg(
Arg::with_name(OPT_NUMERIC_SUFFIXES)
.short("d")
.long(OPT_NUMERIC_SUFFIXES)
.takes_value(true)
.default_value("0")
.help("use numeric suffixes instead of alphabetic"),
)
.arg(
Arg::with_name(OPT_SUFFIX_LENGTH)
.short("a")
.long(OPT_SUFFIX_LENGTH)
.takes_value(true)
.default_value(default_suffix_length_str.as_str())
.help("use suffixes of length N (default 2)"),
)
.arg(
Arg::with_name(OPT_VERBOSE)
.long(OPT_VERBOSE)
.help("print a diagnostic just before each output file is opened"),
)
.arg(
Arg::with_name(ARG_INPUT)
.takes_value(true)
.default_value("-")
.index(1)
)
.arg(
Arg::with_name(ARG_PREFIX)
.takes_value(true)
.default_value("x")
.index(2)
)
.get_matches_from(args);
let mut settings = Settings {
@ -201,6 +126,84 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
split(&settings)
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about("Create output files containing consecutive or interleaved sections of input")
// strategy (mutually exclusive)
.arg(
Arg::with_name(OPT_BYTES)
.short("b")
.long(OPT_BYTES)
.takes_value(true)
.default_value("2")
.help("use suffixes of length N (default 2)"),
)
.arg(
Arg::with_name(OPT_LINE_BYTES)
.short("C")
.long(OPT_LINE_BYTES)
.takes_value(true)
.default_value("2")
.help("put at most SIZE bytes of lines per output file"),
)
.arg(
Arg::with_name(OPT_LINES)
.short("l")
.long(OPT_LINES)
.takes_value(true)
.default_value("1000")
.help("write to shell COMMAND file name is $FILE (Currently not implemented for Windows)"),
)
// rest of the arguments
.arg(
Arg::with_name(OPT_ADDITIONAL_SUFFIX)
.long(OPT_ADDITIONAL_SUFFIX)
.takes_value(true)
.default_value("")
.help("additional suffix to append to output file names"),
)
.arg(
Arg::with_name(OPT_FILTER)
.long(OPT_FILTER)
.takes_value(true)
.help("write to shell COMMAND file name is $FILE (Currently not implemented for Windows)"),
)
.arg(
Arg::with_name(OPT_NUMERIC_SUFFIXES)
.short("d")
.long(OPT_NUMERIC_SUFFIXES)
.takes_value(true)
.default_value("0")
.help("use numeric suffixes instead of alphabetic"),
)
.arg(
Arg::with_name(OPT_SUFFIX_LENGTH)
.short("a")
.long(OPT_SUFFIX_LENGTH)
.takes_value(true)
.default_value(OPT_DEFAULT_SUFFIX_LENGTH)
.help("use suffixes of length N (default 2)"),
)
.arg(
Arg::with_name(OPT_VERBOSE)
.long(OPT_VERBOSE)
.help("print a diagnostic just before each output file is opened"),
)
.arg(
Arg::with_name(ARG_INPUT)
.takes_value(true)
.default_value("-")
.index(1)
)
.arg(
Arg::with_name(ARG_PREFIX)
.takes_value(true)
.default_value("x")
.index(2)
)
}
#[allow(dead_code)]
struct Settings {
prefix: String,

View file

@ -947,11 +947,24 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let long_usage = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&long_usage[..])
.get_matches_from(args);
match Stater::new(matches) {
Ok(stater) => stater.exec(),
Err(e) => {
show_error!("{}", e);
1
}
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::DEREFERENCE)
.short("L")
@ -996,13 +1009,4 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true)
.min_values(1),
)
.get_matches_from(args);
match Stater::new(matches) {
Ok(stater) => stater.exec(),
Err(e) => {
show_error!("{}", e);
1
}
}
}

View file

@ -154,10 +154,40 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.accept_any();
let usage = get_usage();
let matches = App::new(executable!())
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let options = ProgramOptions::try_from(&matches)
.unwrap_or_else(|e| crash!(125, "{}\nTry 'stdbuf --help' for more information.", e.0));
let mut command_values = matches.values_of::<&str>(options::COMMAND).unwrap();
let mut command = Command::new(command_values.next().unwrap());
let command_params: Vec<&str> = command_values.collect();
let mut tmp_dir = tempdir().unwrap();
let (preload_env, libstdbuf) = return_if_err!(1, get_preload_env(&mut tmp_dir));
command.env(preload_env, libstdbuf);
set_command_env(&mut command, "_STDBUF_I", options.stdin);
set_command_env(&mut command, "_STDBUF_O", options.stdout);
set_command_env(&mut command, "_STDBUF_E", options.stderr);
command.args(command_params);
let mut process = match command.spawn() {
Ok(p) => p,
Err(e) => crash!(1, "failed to execute process: {}", e),
};
match process.wait() {
Ok(status) => match status.code() {
Some(i) => i,
None => crash!(1, "process killed by signal {}", status.signal().unwrap()),
},
Err(e) => crash!(1, "{}", e),
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help(LONG_HELP)
.setting(AppSettings::TrailingVarArg)
.arg(
@ -191,32 +221,4 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.hidden(true)
.required(true),
)
.get_matches_from(args);
let options = ProgramOptions::try_from(&matches)
.unwrap_or_else(|e| crash!(125, "{}\nTry 'stdbuf --help' for more information.", e.0));
let mut command_values = matches.values_of::<&str>(options::COMMAND).unwrap();
let mut command = Command::new(command_values.next().unwrap());
let command_params: Vec<&str> = command_values.collect();
let mut tmp_dir = tempdir().unwrap();
let (preload_env, libstdbuf) = return_if_err!(1, get_preload_env(&mut tmp_dir));
command.env(preload_env, libstdbuf);
set_command_env(&mut command, "_STDBUF_I", options.stdin);
set_command_env(&mut command, "_STDBUF_O", options.stdout);
set_command_env(&mut command, "_STDBUF_E", options.stderr);
command.args(command_params);
let mut process = match command.spawn() {
Ok(p) => p,
Err(e) => crash!(1, "failed to execute process: {}", e),
};
match process.wait() {
Ok(status) => match status.code() {
Some(i) => i,
None => crash!(1, "process killed by signal {}", status.signal().unwrap()),
},
Err(e) => crash!(1, "{}", e),
}
}

View file

@ -98,24 +98,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
.about(SUMMARY)
.arg(Arg::with_name(options::FILE).multiple(true).hidden(true))
.arg(
Arg::with_name(options::BSD_COMPATIBLE)
.short(options::BSD_COMPATIBLE)
.help("use the BSD sum algorithm, use 1K blocks (default)"),
)
.arg(
Arg::with_name(options::SYSTEM_V_COMPATIBLE)
.short("s")
.long(options::SYSTEM_V_COMPATIBLE)
.help("use System V sum algorithm, use 512 bytes blocks"),
)
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.clone().map(|v| v.to_owned()).collect(),
@ -155,3 +138,23 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
exit_code
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
.about(SUMMARY)
.arg(Arg::with_name(options::FILE).multiple(true).hidden(true))
.arg(
Arg::with_name(options::BSD_COMPATIBLE)
.short(options::BSD_COMPATIBLE)
.help("use the BSD sum algorithm, use 1K blocks (default)"),
)
.arg(
Arg::with_name(options::SYSTEM_V_COMPATIBLE)
.short("s")
.long(options::SYSTEM_V_COMPATIBLE)
.help("use System V sum algorithm, use 512 bytes blocks"),
)
}

View file

@ -166,26 +166,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::FILE_SYSTEM)
.short("f")
.long(options::FILE_SYSTEM)
.conflicts_with(options::DATA)
.help("sync the file systems that contain the files (Linux and Windows only)"),
)
.arg(
Arg::with_name(options::DATA)
.short("d")
.long(options::DATA)
.conflicts_with(options::FILE_SYSTEM)
.help("sync only file data, no unneeded metadata (Linux only)"),
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
@ -211,6 +192,27 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::FILE_SYSTEM)
.short("f")
.long(options::FILE_SYSTEM)
.conflicts_with(options::DATA)
.help("sync the file systems that contain the files (Linux and Windows only)"),
)
.arg(
Arg::with_name(options::DATA)
.short("d")
.long(options::DATA)
.conflicts_with(options::FILE_SYSTEM)
.help("sync only file data, no unneeded metadata (Linux only)"),
)
.arg(Arg::with_name(ARG_FILES).multiple(true).takes_value(true))
}
fn sync() -> isize {
unsafe { platform::do_sync() }
}

View file

@ -31,7 +31,31 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
let before = matches.is_present(options::BEFORE);
let regex = matches.is_present(options::REGEX);
let separator = match matches.value_of(options::SEPARATOR) {
Some(m) => {
if m.is_empty() {
crash!(1, "separator cannot be empty")
} else {
m.to_owned()
}
}
None => "\n".to_owned(),
};
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
tac(files, before, regex, &separator[..])
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
@ -58,27 +82,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true),
)
.arg(Arg::with_name(options::FILE).hidden(true).multiple(true))
.get_matches_from(args);
let before = matches.is_present(options::BEFORE);
let regex = matches.is_present(options::REGEX);
let separator = match matches.value_of(options::SEPARATOR) {
Some(m) => {
if m.is_empty() {
crash!(1, "separator cannot be empty")
} else {
m.to_owned()
}
}
None => "\n".to_owned(),
};
let files: Vec<String> = match matches.values_of(options::FILE) {
Some(v) => v.map(|v| v.to_owned()).collect(),
None => vec!["-".to_owned()],
};
tac(files, before, regex, &separator[..])
}
fn tac(filenames: Vec<String>, before: bool, _: bool, separator: &str) -> i32 {

View file

@ -72,74 +72,7 @@ impl Default for Settings {
pub fn uumain(args: impl uucore::Args) -> i32 {
let mut settings: Settings = Default::default();
let app = App::new(executable!())
.version(crate_version!())
.about("output the last part of files")
// TODO: add usage
.arg(
Arg::with_name(options::BYTES)
.short("c")
.long(options::BYTES)
.takes_value(true)
.allow_hyphen_values(true)
.overrides_with_all(&[options::BYTES, options::LINES])
.help("Number of bytes to print"),
)
.arg(
Arg::with_name(options::FOLLOW)
.short("f")
.long(options::FOLLOW)
.help("Print the file as it grows"),
)
.arg(
Arg::with_name(options::LINES)
.short("n")
.long(options::LINES)
.takes_value(true)
.allow_hyphen_values(true)
.overrides_with_all(&[options::BYTES, options::LINES])
.help("Number of lines to print"),
)
.arg(
Arg::with_name(options::PID)
.long(options::PID)
.takes_value(true)
.help("with -f, terminate after process ID, PID dies"),
)
.arg(
Arg::with_name(options::verbosity::QUIET)
.short("q")
.long(options::verbosity::QUIET)
.visible_alias("silent")
.overrides_with_all(&[options::verbosity::QUIET, options::verbosity::VERBOSE])
.help("never output headers giving file names"),
)
.arg(
Arg::with_name(options::SLEEP_INT)
.short("s")
.takes_value(true)
.long(options::SLEEP_INT)
.help("Number or seconds to sleep between polling the file when running with -f"),
)
.arg(
Arg::with_name(options::verbosity::VERBOSE)
.short("v")
.long(options::verbosity::VERBOSE)
.overrides_with_all(&[options::verbosity::QUIET, options::verbosity::VERBOSE])
.help("always output headers giving file names"),
)
.arg(
Arg::with_name(options::ZERO_TERM)
.short("z")
.long(options::ZERO_TERM)
.help("Line delimiter is NUL, not newline"),
)
.arg(
Arg::with_name(options::ARG_FILES)
.multiple(true)
.takes_value(true)
.min_values(1),
);
let app = uu_app();
let matches = app.get_matches_from(args);
@ -244,6 +177,77 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about("output the last part of files")
// TODO: add usage
.arg(
Arg::with_name(options::BYTES)
.short("c")
.long(options::BYTES)
.takes_value(true)
.allow_hyphen_values(true)
.overrides_with_all(&[options::BYTES, options::LINES])
.help("Number of bytes to print"),
)
.arg(
Arg::with_name(options::FOLLOW)
.short("f")
.long(options::FOLLOW)
.help("Print the file as it grows"),
)
.arg(
Arg::with_name(options::LINES)
.short("n")
.long(options::LINES)
.takes_value(true)
.allow_hyphen_values(true)
.overrides_with_all(&[options::BYTES, options::LINES])
.help("Number of lines to print"),
)
.arg(
Arg::with_name(options::PID)
.long(options::PID)
.takes_value(true)
.help("with -f, terminate after process ID, PID dies"),
)
.arg(
Arg::with_name(options::verbosity::QUIET)
.short("q")
.long(options::verbosity::QUIET)
.visible_alias("silent")
.overrides_with_all(&[options::verbosity::QUIET, options::verbosity::VERBOSE])
.help("never output headers giving file names"),
)
.arg(
Arg::with_name(options::SLEEP_INT)
.short("s")
.takes_value(true)
.long(options::SLEEP_INT)
.help("Number or seconds to sleep between polling the file when running with -f"),
)
.arg(
Arg::with_name(options::verbosity::VERBOSE)
.short("v")
.long(options::verbosity::VERBOSE)
.overrides_with_all(&[options::verbosity::QUIET, options::verbosity::VERBOSE])
.help("always output headers giving file names"),
)
.arg(
Arg::with_name(options::ZERO_TERM)
.short("z")
.long(options::ZERO_TERM)
.help("Line delimiter is NUL, not newline"),
)
.arg(
Arg::with_name(options::ARG_FILES)
.multiple(true)
.takes_value(true)
.min_values(1),
)
}
fn follow<T: Read>(readers: &mut [BufReader<T>], filenames: &[String], settings: &Settings) {
assert!(settings.follow);
let mut last = readers.len() - 1;

View file

@ -39,25 +39,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.after_help("If a FILE is -, it refers to a file named - .")
.arg(
Arg::with_name(options::APPEND)
.long(options::APPEND)
.short("a")
.help("append to the given FILEs, do not overwrite"),
)
.arg(
Arg::with_name(options::IGNORE_INTERRUPTS)
.long(options::IGNORE_INTERRUPTS)
.short("i")
.help("ignore interrupt signals (ignored on non-Unix platforms)"),
)
.arg(Arg::with_name(options::FILE).multiple(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let options = Options {
append: matches.is_present(options::APPEND),
@ -74,6 +56,26 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.after_help("If a FILE is -, it refers to a file named - .")
.arg(
Arg::with_name(options::APPEND)
.long(options::APPEND)
.short("a")
.help("append to the given FILEs, do not overwrite"),
)
.arg(
Arg::with_name(options::IGNORE_INTERRUPTS)
.long(options::IGNORE_INTERRUPTS)
.short("i")
.help("ignore interrupt signals (ignored on non-Unix platforms)"),
)
.arg(Arg::with_name(options::FILE).multiple(true))
}
#[cfg(unix)]
fn ignore_interrupts() -> Result<()> {
let ret = unsafe { libc::signal(libc::SIGINT, libc::SIG_IGN) };

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/test.rs"
[dependencies]
clap = "2.33.3"
libc = "0.2.42"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -10,9 +10,17 @@
mod parser;
use clap::{App, AppSettings};
use parser::{parse, Symbol};
use std::ffi::{OsStr, OsString};
use std::path::Path;
use uucore::executable;
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.setting(AppSettings::DisableHelpFlags)
.setting(AppSettings::DisableVersion)
}
pub fn uumain(mut args: impl uucore::Args) -> i32 {
let program = args.next().unwrap_or_else(|| OsString::from("test"));

View file

@ -102,9 +102,25 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let app = App::new("timeout")
let app = uu_app().usage(&usage[..]);
let matches = app.get_matches_from(args);
let config = Config::from(matches);
timeout(
&config.command,
config.duration,
config.signal,
config.kill_after,
config.foreground,
config.preserve_status,
config.verbose,
)
}
pub fn uu_app() -> App<'static, 'static> {
App::new("timeout")
.version(crate_version!())
.usage(&usage[..])
.about(ABOUT)
.arg(
Arg::with_name(options::FOREGROUND)
@ -144,20 +160,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.required(true)
.multiple(true)
)
.setting(AppSettings::TrailingVarArg);
let matches = app.get_matches_from(args);
let config = Config::from(matches);
timeout(
&config.command,
config.duration,
config.signal,
config.kill_after,
config.foreground,
config.preserve_status,
config.verbose,
)
.setting(AppSettings::TrailingVarArg)
}
/// Remove pre-existing SIGCHLD handlers that would make waiting for the child's exit code fail.

View file

@ -55,80 +55,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::ACCESS)
.short("a")
.help("change only the access time"),
)
.arg(
Arg::with_name(options::sources::CURRENT)
.short("t")
.help("use [[CC]YY]MMDDhhmm[.ss] instead of the current time")
.value_name("STAMP")
.takes_value(true),
)
.arg(
Arg::with_name(options::sources::DATE)
.short("d")
.long(options::sources::DATE)
.help("parse argument and use it instead of current time")
.value_name("STRING"),
)
.arg(
Arg::with_name(options::MODIFICATION)
.short("m")
.help("change only the modification time"),
)
.arg(
Arg::with_name(options::NO_CREATE)
.short("c")
.long(options::NO_CREATE)
.help("do not create any files"),
)
.arg(
Arg::with_name(options::NO_DEREF)
.short("h")
.long(options::NO_DEREF)
.help(
"affect each symbolic link instead of any referenced file \
(only for systems that can change the timestamps of a symlink)",
),
)
.arg(
Arg::with_name(options::sources::REFERENCE)
.short("r")
.long(options::sources::REFERENCE)
.help("use this file's times instead of the current time")
.value_name("FILE"),
)
.arg(
Arg::with_name(options::TIME)
.long(options::TIME)
.help(
"change only the specified time: \"access\", \"atime\", or \
\"use\" are equivalent to -a; \"modify\" or \"mtime\" are \
equivalent to -m",
)
.value_name("WORD")
.possible_values(&["access", "atime", "use"])
.takes_value(true),
)
.arg(
Arg::with_name(ARG_FILES)
.multiple(true)
.takes_value(true)
.min_values(1),
)
.group(ArgGroup::with_name(options::SOURCES).args(&[
options::sources::CURRENT,
options::sources::DATE,
options::sources::REFERENCE,
]))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
@ -236,6 +163,81 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
error_code
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::ACCESS)
.short("a")
.help("change only the access time"),
)
.arg(
Arg::with_name(options::sources::CURRENT)
.short("t")
.help("use [[CC]YY]MMDDhhmm[.ss] instead of the current time")
.value_name("STAMP")
.takes_value(true),
)
.arg(
Arg::with_name(options::sources::DATE)
.short("d")
.long(options::sources::DATE)
.help("parse argument and use it instead of current time")
.value_name("STRING"),
)
.arg(
Arg::with_name(options::MODIFICATION)
.short("m")
.help("change only the modification time"),
)
.arg(
Arg::with_name(options::NO_CREATE)
.short("c")
.long(options::NO_CREATE)
.help("do not create any files"),
)
.arg(
Arg::with_name(options::NO_DEREF)
.short("h")
.long(options::NO_DEREF)
.help(
"affect each symbolic link instead of any referenced file \
(only for systems that can change the timestamps of a symlink)",
),
)
.arg(
Arg::with_name(options::sources::REFERENCE)
.short("r")
.long(options::sources::REFERENCE)
.help("use this file's times instead of the current time")
.value_name("FILE"),
)
.arg(
Arg::with_name(options::TIME)
.long(options::TIME)
.help(
"change only the specified time: \"access\", \"atime\", or \
\"use\" are equivalent to -a; \"modify\" or \"mtime\" are \
equivalent to -m",
)
.value_name("WORD")
.possible_values(&["access", "atime", "use"])
.takes_value(true),
)
.arg(
Arg::with_name(ARG_FILES)
.multiple(true)
.takes_value(true)
.min_values(1),
)
.group(ArgGroup::with_name(options::SOURCES).args(&[
options::sources::CURRENT,
options::sources::DATE,
options::sources::REFERENCE,
]))
}
fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {
let metadata = if follow {
fs::symlink_metadata(path)

View file

@ -249,46 +249,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let after_help = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&after_help[..])
.arg(
Arg::with_name(options::COMPLEMENT)
// .visible_short_alias('C') // TODO: requires clap "3.0.0-beta.2"
.short("c")
.long(options::COMPLEMENT)
.help("use the complement of SET1"),
)
.arg(
Arg::with_name("C") // work around for `Arg::visible_short_alias`
.short("C")
.help("same as -c"),
)
.arg(
Arg::with_name(options::DELETE)
.short("d")
.long(options::DELETE)
.help("delete characters in SET1, do not translate"),
)
.arg(
Arg::with_name(options::SQUEEZE)
.long(options::SQUEEZE)
.short("s")
.help(
"replace each sequence of a repeated character that is
listed in the last specified SET, with a single occurrence
of that character",
),
)
.arg(
Arg::with_name(options::TRUNCATE)
.long(options::TRUNCATE)
.short("t")
.help("first truncate SET1 to length of SET2"),
)
.arg(Arg::with_name(options::SETS).multiple(true))
.get_matches_from(args);
let delete_flag = matches.is_present(options::DELETE);
@ -358,3 +321,44 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::COMPLEMENT)
// .visible_short_alias('C') // TODO: requires clap "3.0.0-beta.2"
.short("c")
.long(options::COMPLEMENT)
.help("use the complement of SET1"),
)
.arg(
Arg::with_name("C") // work around for `Arg::visible_short_alias`
.short("C")
.help("same as -c"),
)
.arg(
Arg::with_name(options::DELETE)
.short("d")
.long(options::DELETE)
.help("delete characters in SET1, do not translate"),
)
.arg(
Arg::with_name(options::SQUEEZE)
.long(options::SQUEEZE)
.short("s")
.help(
"replace each sequence of a repeated character that is
listed in the last specified SET, with a single occurrence
of that character",
),
)
.arg(
Arg::with_name(options::TRUNCATE)
.long(options::TRUNCATE)
.short("t")
.help("first truncate SET1 to length of SET2"),
)
.arg(Arg::with_name(options::SETS).multiple(true))
}

View file

@ -15,6 +15,7 @@ edition = "2018"
path = "src/true.rs"
[dependencies]
clap = "2.33.3"
uucore = { version=">=0.0.8", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -5,6 +5,15 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
use clap::{App, AppSettings};
use uucore::executable;
pub fn uumain(_: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.setting(AppSettings::DisableHelpFlags)
.setting(AppSettings::DisableVersion)
}

View file

@ -93,45 +93,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let long_usage = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&long_usage[..])
.arg(
Arg::with_name(options::IO_BLOCKS)
.short("o")
.long(options::IO_BLOCKS)
.help("treat SIZE as the number of I/O blocks of the file rather than bytes (NOT IMPLEMENTED)")
)
.arg(
Arg::with_name(options::NO_CREATE)
.short("c")
.long(options::NO_CREATE)
.help("do not create files that do not exist")
)
.arg(
Arg::with_name(options::REFERENCE)
.short("r")
.long(options::REFERENCE)
.required_unless(options::SIZE)
.help("base the size of each file on the size of RFILE")
.value_name("RFILE")
)
.arg(
Arg::with_name(options::SIZE)
.short("s")
.long(options::SIZE)
.required_unless(options::REFERENCE)
.help("set or adjust the size of each file according to SIZE, which is in bytes unless --io-blocks is specified")
.value_name("SIZE")
)
.arg(Arg::with_name(options::ARG_FILES)
.value_name("FILE")
.multiple(true)
.takes_value(true)
.required(true)
.min_values(1))
.get_matches_from(args);
let files: Vec<String> = matches
@ -168,6 +132,46 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::IO_BLOCKS)
.short("o")
.long(options::IO_BLOCKS)
.help("treat SIZE as the number of I/O blocks of the file rather than bytes (NOT IMPLEMENTED)")
)
.arg(
Arg::with_name(options::NO_CREATE)
.short("c")
.long(options::NO_CREATE)
.help("do not create files that do not exist")
)
.arg(
Arg::with_name(options::REFERENCE)
.short("r")
.long(options::REFERENCE)
.required_unless(options::SIZE)
.help("base the size of each file on the size of RFILE")
.value_name("RFILE")
)
.arg(
Arg::with_name(options::SIZE)
.short("s")
.long(options::SIZE)
.required_unless(options::REFERENCE)
.help("set or adjust the size of each file according to SIZE, which is in bytes unless --io-blocks is specified")
.value_name("SIZE")
)
.arg(Arg::with_name(options::ARG_FILES)
.value_name("FILE")
.multiple(true)
.takes_value(true)
.required(true)
.min_values(1))
}
/// Truncate the named file to the specified size.
///
/// If `create` is true, then the file will be created if it does not

View file

@ -30,16 +30,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.version(crate_version!())
.usage(USAGE)
.about(SUMMARY)
.arg(
Arg::with_name(options::FILE)
.default_value("-")
.hidden(true),
)
.get_matches_from(args);
let matches = uu_app().get_matches_from(args);
let input = matches
.value_of(options::FILE)
@ -98,6 +89,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.usage(USAGE)
.about(SUMMARY)
.arg(
Arg::with_name(options::FILE)
.default_value("-")
.hidden(true),
)
}
// We use String as a representation of node here
// but using integer may improve performance.
struct Graph {

View file

@ -33,19 +33,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::ConvertLossy)
.accept_any();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::SILENT)
.long(options::SILENT)
.visible_alias("quiet")
.short("s")
.help("print nothing, only return an exit status")
.required(false),
)
.get_matches_from_safe(args);
let matches = uu_app().usage(&usage[..]).get_matches_from_safe(args);
let matches = match matches {
Ok(m) => m,
@ -88,3 +76,17 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
libc::EXIT_FAILURE
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::SILENT)
.long(options::SILENT)
.visible_alias("quiet")
.short("s")
.help("print nothing, only return an exit status")
.required(false),
)
}

View file

@ -47,49 +47,7 @@ const HOST_OS: &str = "Redox";
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = format!("{} [OPTION]...", executable!());
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(Arg::with_name(options::ALL)
.short("a")
.long(options::ALL)
.help("Behave as though all of the options -mnrsv were specified."))
.arg(Arg::with_name(options::KERNELNAME)
.short("s")
.long(options::KERNELNAME)
.alias("sysname") // Obsolescent option in GNU uname
.help("print the kernel name."))
.arg(Arg::with_name(options::NODENAME)
.short("n")
.long(options::NODENAME)
.help("print the nodename (the nodename may be a name that the system is known by to a communications network)."))
.arg(Arg::with_name(options::KERNELRELEASE)
.short("r")
.long(options::KERNELRELEASE)
.alias("release") // Obsolescent option in GNU uname
.help("print the operating system release."))
.arg(Arg::with_name(options::KERNELVERSION)
.short("v")
.long(options::KERNELVERSION)
.help("print the operating system version."))
.arg(Arg::with_name(options::HWPLATFORM)
.short("i")
.long(options::HWPLATFORM)
.help("print the hardware platform (non-portable)"))
.arg(Arg::with_name(options::MACHINE)
.short("m")
.long(options::MACHINE)
.help("print the machine hardware name."))
.arg(Arg::with_name(options::PROCESSOR)
.short("p")
.long(options::PROCESSOR)
.help("print the processor type (non-portable)"))
.arg(Arg::with_name(options::OS)
.short("o")
.long(options::OS)
.help("print the operating system name."))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let uname = return_if_err!(1, PlatformInfo::new());
let mut output = String::new();
@ -155,3 +113,47 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(Arg::with_name(options::ALL)
.short("a")
.long(options::ALL)
.help("Behave as though all of the options -mnrsv were specified."))
.arg(Arg::with_name(options::KERNELNAME)
.short("s")
.long(options::KERNELNAME)
.alias("sysname") // Obsolescent option in GNU uname
.help("print the kernel name."))
.arg(Arg::with_name(options::NODENAME)
.short("n")
.long(options::NODENAME)
.help("print the nodename (the nodename may be a name that the system is known by to a communications network)."))
.arg(Arg::with_name(options::KERNELRELEASE)
.short("r")
.long(options::KERNELRELEASE)
.alias("release") // Obsolescent option in GNU uname
.help("print the operating system release."))
.arg(Arg::with_name(options::KERNELVERSION)
.short("v")
.long(options::KERNELVERSION)
.help("print the operating system version."))
.arg(Arg::with_name(options::HWPLATFORM)
.short("i")
.long(options::HWPLATFORM)
.help("print the hardware platform (non-portable)"))
.arg(Arg::with_name(options::MACHINE)
.short("m")
.long(options::MACHINE)
.help("print the machine hardware name."))
.arg(Arg::with_name(options::PROCESSOR)
.short("p")
.long(options::PROCESSOR)
.help("print the processor type (non-portable)"))
.arg(Arg::with_name(options::OS)
.short("o")
.long(options::OS)
.help("print the operating system name."))
}

View file

@ -94,7 +94,15 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.collect_str(InvalidEncodingHandling::Ignore)
.accept_any();
let matches = App::new(executable!())
let matches = uu_app().get_matches_from(args);
unexpand(Options::new(matches));
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.name(NAME)
.version(crate_version!())
.usage(USAGE)
@ -126,11 +134,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.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));
0
}
fn open(path: String) -> BufReader<Box<dyn Read + 'static>> {

View file

@ -238,11 +238,52 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let long_usage = get_long_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
let matches = uu_app()
.usage(&usage[..])
.after_help(&long_usage[..])
.get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let (in_file_name, out_file_name) = match files.len() {
0 => ("-".to_owned(), "-".to_owned()),
1 => (files[0].clone(), "-".to_owned()),
2 => (files[0].clone(), files[1].clone()),
_ => {
// Cannot happen as clap will fail earlier
crash!(1, "Extra operand: {}", files[2]);
}
};
let uniq = Uniq {
repeats_only: matches.is_present(options::REPEATED)
|| matches.is_present(options::ALL_REPEATED),
uniques_only: matches.is_present(options::UNIQUE),
all_repeated: matches.is_present(options::ALL_REPEATED)
|| matches.is_present(options::GROUP),
delimiters: get_delimiter(&matches),
show_counts: matches.is_present(options::COUNT),
skip_fields: opt_parsed(options::SKIP_FIELDS, &matches),
slice_start: opt_parsed(options::SKIP_CHARS, &matches),
slice_stop: opt_parsed(options::CHECK_CHARS, &matches),
ignore_case: matches.is_present(options::IGNORE_CASE),
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
};
uniq.print_uniq(
&mut open_input_file(in_file_name),
&mut open_output_file(out_file_name),
);
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::ALL_REPEATED)
.short("D")
@ -329,43 +370,6 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
.takes_value(true)
.max_values(2),
)
.get_matches_from(args);
let files: Vec<String> = matches
.values_of(ARG_FILES)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default();
let (in_file_name, out_file_name) = match files.len() {
0 => ("-".to_owned(), "-".to_owned()),
1 => (files[0].clone(), "-".to_owned()),
2 => (files[0].clone(), files[1].clone()),
_ => {
// Cannot happen as clap will fail earlier
crash!(1, "Extra operand: {}", files[2]);
}
};
let uniq = Uniq {
repeats_only: matches.is_present(options::REPEATED)
|| matches.is_present(options::ALL_REPEATED),
uniques_only: matches.is_present(options::UNIQUE),
all_repeated: matches.is_present(options::ALL_REPEATED)
|| matches.is_present(options::GROUP),
delimiters: get_delimiter(&matches),
show_counts: matches.is_present(options::COUNT),
skip_fields: opt_parsed(options::SKIP_FIELDS, &matches),
slice_start: opt_parsed(options::SKIP_CHARS, &matches),
slice_stop: opt_parsed(options::CHECK_CHARS, &matches),
ignore_case: matches.is_present(options::IGNORE_CASE),
zero_terminated: matches.is_present(options::ZERO_TERMINATED),
};
uniq.print_uniq(
&mut open_input_file(in_file_name),
&mut open_output_file(out_file_name),
);
0
}
fn get_delimiter(matches: &ArgMatches) -> Delimiters {

View file

@ -33,12 +33,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(Arg::with_name(OPT_PATH).hidden(true).multiple(true))
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let paths: Vec<String> = matches
.values_of(OPT_PATH)
@ -98,3 +93,10 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
0
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(Arg::with_name(OPT_PATH).hidden(true).multiple(true))
}

View file

@ -38,17 +38,7 @@ fn get_usage() -> String {
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.usage(&usage[..])
.arg(
Arg::with_name(options::SINCE)
.short("s")
.long(options::SINCE)
.help("system up since"),
)
.get_matches_from(args);
let matches = uu_app().usage(&usage[..]).get_matches_from(args);
let (boot_time, user_count) = process_utmpx();
let uptime = get_uptime(boot_time);
@ -73,6 +63,18 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
pub fn uu_app() -> App<'static, 'static> {
App::new(executable!())
.version(crate_version!())
.about(ABOUT)
.arg(
Arg::with_name(options::SINCE)
.short("s")
.long(options::SINCE)
.help("system up since"),
)
}
#[cfg(unix)]
fn print_loadavg() {
use uucore::libc::c_double;

Some files were not shown because too many files have changed in this diff Show more