diff --git a/src/base32/Cargo.toml b/src/base32/Cargo.toml index 7d0dd2171..1401f6650 100644 --- a/src/base32/Cargo.toml +++ b/src/base32/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_base32" path = "base32.rs" [dependencies] -getopts = "*" uucore = { path="../uucore" } [dependencies.clippy] diff --git a/src/base32/base32.rs b/src/base32/base32.rs index 0f65c19c8..700afe734 100644 --- a/src/base32/base32.rs +++ b/src/base32/base32.rs @@ -8,46 +8,38 @@ #![crate_name = "uu_base32"] -extern crate getopts; - #[macro_use] extern crate uucore; use uucore::encoding::{Data, Format, wrap_print}; -use getopts::Options; use std::fs::File; use std::io::{BufReader, Read, stdin, Write}; use std::path::Path; -static NAME: &'static str = "base32"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]"; +static SUMMARY: &'static str = "Base32 encode or decode FILE, or standard input, to standard output."; +static LONG_HELP: &'static str = " + With no FILE, or when FILE is -, read standard input. + + The data are encoded as described for the base32 alphabet in RFC + 4648. When decoding, the input may contain newlines in addition + to the bytes of the formal base32 alphabet. Use --ignore-garbage + to attempt to recover from any other non-alphabet bytes in the + encoded stream. +"; pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("d", "decode", "decode data"); - opts.optflag("i", + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("d", "decode", "decode data") + .optflag("i", "ignore-garbage", - "when decoding, ignore non-alphabetic characters"); - opts.optopt("w", + "when decoding, ignore non-alphabetic characters") + .optopt("w", "wrap", "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)", - "COLS"); - opts.optflag("", "help", "display this help text and exit"); - opts.optflag("", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { - disp_err!("{}", e); - return 1; - } - }; - - if matches.opt_present("help") { - return help(&opts); - } else if matches.opt_present("version") { - return version(); - } - + "COLS") + .parse(args); + let line_wrap = match matches.opt_str("wrap") { Some(s) => { match s.parse() { @@ -88,23 +80,3 @@ pub fn uumain(args: Vec) -> i32 { 0 } - -fn help(opts: &Options) -> i32 { - let msg = format!("Usage: {} [OPTION]... [FILE]\n\n\ - Base32 encode or decode FILE, or standard input, to standard output.\n\ - With no FILE, or when FILE is -, read standard input.\n\n\ - The data are encoded as described for the base32 alphabet in RFC \ - 4648.\nWhen decoding, the input may contain newlines in addition \ - to the bytes of the formal\nbase32 alphabet. Use --ignore-garbage \ - to attempt to recover from any other\nnon-alphabet bytes in the \ - encoded stream.", - NAME); - - print!("{}", opts.usage(&msg)); - 0 -} - -fn version() -> i32 { - println!("{} {}", NAME, VERSION); - 0 -} diff --git a/src/base64/Cargo.toml b/src/base64/Cargo.toml index 0da38e783..83e18d0d2 100644 --- a/src/base64/Cargo.toml +++ b/src/base64/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_base64" path = "base64.rs" [dependencies] -getopts = "*" uucore = { path="../uucore" } [[bin]] diff --git a/src/base64/base64.rs b/src/base64/base64.rs index 85b8f7bfa..d5dd53696 100644 --- a/src/base64/base64.rs +++ b/src/base64/base64.rs @@ -9,45 +9,38 @@ // that was distributed with this source code. // -extern crate getopts; #[macro_use] extern crate uucore; use uucore::encoding::{Data, Format, wrap_print}; -use getopts::Options; use std::fs::File; use std::io::{BufReader, Read, stdin, Write}; use std::path::Path; -static NAME: &'static str = "base64"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]"; +static SUMMARY: &'static str = "Base64 encode or decode FILE, or standard input, to standard output."; +static LONG_HELP: &'static str = " + With no FILE, or when FILE is -, read standard input. + + The data are encoded as described for the base64 alphabet in RFC + 3548. When decoding, the input may contain newlines in addition + to the bytes of the formal base64 alphabet. Use --ignore-garbage + to attempt to recover from any other non-alphabet bytes in the + encoded stream. +"; pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("d", "decode", "decode data"); - opts.optflag("i", + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("d", "decode", "decode data") + .optflag("i", "ignore-garbage", - "when decoding, ignore non-alphabetic characters"); - opts.optopt("w", + "when decoding, ignore non-alphabetic characters") + .optopt("w", "wrap", "wrap encoded lines after COLS character (default 76, 0 to disable wrapping)", - "COLS"); - opts.optflag("", "help", "display this help text and exit"); - opts.optflag("", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { - disp_err!("{}", e); - return 1; - } - }; - - if matches.opt_present("help") { - return help(&opts); - } else if matches.opt_present("version") { - return version(); - } + "COLS") + .parse(args); let line_wrap = match matches.opt_str("wrap") { Some(s) => { @@ -89,23 +82,3 @@ pub fn uumain(args: Vec) -> i32 { 0 } - -fn help(opts: &Options) -> i32 { - let msg = format!("Usage: {} [OPTION]... [FILE]\n\n\ - Base64 encode or decode FILE, or standard input, to standard output.\n\ - With no FILE, or when FILE is -, read standard input.\n\n\ - The data are encoded as described for the base64 alphabet in RFC \ - 3548. When\ndecoding, the input may contain newlines in addition \ - to the bytes of the formal\nbase64 alphabet. Use --ignore-garbage \ - to attempt to recover from any other\nnon-alphabet bytes in the \ - encoded stream.", - NAME); - - print!("{}", opts.usage(&msg)); - 0 -} - -fn version() -> i32 { - println!("{} {}", NAME, VERSION); - 0 -} diff --git a/src/basename/Cargo.toml b/src/basename/Cargo.toml index 9187cb0cf..33ab7e06f 100644 --- a/src/basename/Cargo.toml +++ b/src/basename/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_basename" path = "basename.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/basename/basename.rs b/src/basename/basename.rs index 55a72ad56..f4bb3977f 100644 --- a/src/basename/basename.rs +++ b/src/basename/basename.rs @@ -9,49 +9,29 @@ * file that was distributed with this source code. */ -extern crate getopts; extern crate libc; #[macro_use] extern crate uucore; -use getopts::Options; use std::io::Write; use std::path::{is_separator, PathBuf}; static NAME: &'static str = "basename"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "NAME [SUFFIX]"; +static SUMMARY: &'static str = "Print NAME with any leading directory components removed + If specified, also remove a trailing SUFFIX"; +static LONG_HELP: &'static str = ""; pub fn uumain(args: Vec) -> i32 { // // Argument parsing // - let mut opts = Options::new(); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("Usage: {0} NAME [SUFFIX]\n or: {0} OPTION\n\n\ - Print NAME with any leading directory components removed.\n\ - If specified, also remove a trailing SUFFIX.", NAME); - - print!("{}", opts.usage(&msg)); - - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .parse(args); // too few arguments - if args.len() < 2 { + if matches.free.len() < 1 { crash!( 1, "{0}: {1}\nTry '{0} --help' for more information.", @@ -60,12 +40,12 @@ pub fn uumain(args: Vec) -> i32 { ); } // too many arguments - else if args.len() > 3 { + else if matches.free.len() > 2 { crash!( 1, "{0}: extra operand '{1}'\nTry '{0} --help' for more information.", NAME, - args[3] + matches.free[2] ); } @@ -73,10 +53,10 @@ pub fn uumain(args: Vec) -> i32 { // Main Program Processing // - let mut name = strip_dir(&args[1]); + let mut name = strip_dir(&matches.free[0]); - if args.len() > 2 { - let suffix = args[2].clone(); + if matches.free.len() > 1 { + let suffix = matches.free[1].clone(); name = strip_suffix(name.as_ref(), suffix.as_ref()); } diff --git a/src/cat/Cargo.toml b/src/cat/Cargo.toml index 991a206de..dab41706e 100644 --- a/src/cat/Cargo.toml +++ b/src/cat/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_cat" path = "cat.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/cat/cat.rs b/src/cat/cat.rs index e612a506c..d303388c8 100644 --- a/src/cat/cat.rs +++ b/src/cat/cat.rs @@ -11,53 +11,35 @@ /* last synced with: cat (GNU coreutils) 8.13 */ -extern crate getopts; extern crate libc; #[macro_use] extern crate uucore; -use getopts::Options; use std::fs::File; use std::intrinsics::{copy_nonoverlapping}; use std::io::{stdout, stdin, stderr, Write, Read, Result}; use uucore::fs::is_stdin_interactive; -static NAME: &'static str = "cat"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]..."; +static SUMMARY: &'static str = "Concatenate FILE(s), or standard input, to standard output + With no FILE, or when FILE is -, read standard input."; +static LONG_HELP: &'static str = ""; pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("A", "show-all", "equivalent to -vET"); - opts.optflag("b", "number-nonblank", - "number nonempty output lines, overrides -n"); - opts.optflag("e", "", "equivalent to -vE"); - opts.optflag("E", "show-ends", "display $ at end of each line"); - opts.optflag("n", "number", "number all output lines"); - opts.optflag("s", "squeeze-blank", "suppress repeated empty output lines"); - opts.optflag("t", "", "equivalent to -vT"); - opts.optflag("T", "show-tabs", "display TAB characters as ^I"); - opts.optflag("v", "show-nonprinting", - "use ^ and M- notation, except for LF (\\n) and TAB (\\t)"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!("Invalid options\n{}", f) - }; - if matches.opt_present("help") { - let msg = format!("{} {}\n\n\ - Usage:\n {0} [OPTION]... [FILE]...\n\n\ - Concatenate FILE(s), or standard input, to standard output.\n\n\ - With no FILE, or when FILE is -, read standard input.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("A", "show-all", "equivalent to -vET") + .optflag("b", "number-nonblank", + "number nonempty output lines, overrides -n") + .optflag("e", "", "equivalent to -vE") + .optflag("E", "show-ends", "display $ at end of each line") + .optflag("n", "number", "number all output lines") + .optflag("s", "squeeze-blank", "suppress repeated empty output lines") + .optflag("t", "", "equivalent to -vT") + .optflag("T", "show-tabs", "display TAB characters as ^I") + .optflag("v", "show-nonprinting", + "use ^ and M- notation, except for LF (\\n) and TAB (\\t)") + .parse(args); let number_mode = if matches.opt_present("b") { NumberingMode::NumberNonEmpty diff --git a/src/chmod/Cargo.toml b/src/chmod/Cargo.toml index 40914154f..d17902d0b 100644 --- a/src/chmod/Cargo.toml +++ b/src/chmod/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_chmod" path = "chmod.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } walker = "*" diff --git a/src/chmod/chmod.rs b/src/chmod/chmod.rs index 70e3935cd..cfb148bf6 100644 --- a/src/chmod/chmod.rs +++ b/src/chmod/chmod.rs @@ -9,14 +9,12 @@ * file that was distributed with this source code. */ -extern crate getopts; extern crate libc; extern crate walker; #[macro_use] extern crate uucore; -use getopts::Options; use std::error::Error; use std::ffi::CString; use std::io::{self, Write}; @@ -25,19 +23,25 @@ use std::path::Path; use walker::Walker; const NAME: &'static str = "chmod"; -const VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SUMMARY: &'static str = "Change the mode of each FILE to MODE. + With --reference, change the mode of each FILE to that of RFILE."; +static LONG_HELP: &'static str = " + Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'. +"; pub fn uumain(mut args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("c", "changes", "like verbose but report only when a change is made (unimplemented)"); - opts.optflag("f", "quiet", "suppress most error messages (unimplemented)"); // TODO: support --silent - opts.optflag("v", "verbose", "output a diagnostic for every file processed (unimplemented)"); - opts.optflag("", "no-preserve-root", "do not treat '/' specially (the default)"); - opts.optflag("", "preserve-root", "fail to operate recursively on '/'"); - opts.optopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE"); - opts.optflag("R", "recursive", "change files and directories recursively"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); + let syntax = format!("[OPTION]... MODE[,MODE]... FILE... + {0} [OPTION]... OCTAL-MODE FILE... + {0} [OPTION]... --reference=RFILE FILE...", NAME); + let mut opts = new_coreopts!(&syntax, SUMMARY, LONG_HELP); + opts.optflag("c", "changes", "like verbose but report only when a change is made (unimplemented)") + .optflag("f", "quiet", "suppress most error messages (unimplemented)") // TODO: support --silent + .optflag("v", "verbose", "output a diagnostic for every file processed (unimplemented)") + .optflag("", "no-preserve-root", "do not treat '/' specially (the default)") + .optflag("", "preserve-root", "fail to operate recursively on '/'") + .optopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE") + .optflag("R", "recursive", "change files and directories recursively"); + // sanitize input for - at beginning (e.g. chmod -x testfile). Remove // the option and save it for later, after parsing is finished. let mut negative_option = None; @@ -59,28 +63,8 @@ pub fn uumain(mut args: Vec) -> i32 { } } - let mut matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { crash!(1, "{}", f) } - }; - if matches.opt_present("help") { - let msg = format!("{name} {version} - -Usage: - {program} [OPTION]... MODE[,MODE]... FILE... - {program} [OPTION]... OCTAL-MODE FILE... - {program} [OPTION]... --reference=RFILE FILE... - -Change the mode of each FILE to MODE. -With --reference, change the mode of each FILE to that of RFILE. -Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.", - name = NAME, version = VERSION, program = NAME); - - print!("{}", opts.usage(&msg)); - return 0; - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - } else if matches.free.is_empty() { + let mut matches = opts.parse(args); + if matches.free.is_empty() { show_error!("missing an argument"); show_error!("for help, try '{} --help'", NAME); return 1; diff --git a/src/chroot/chroot.rs b/src/chroot/chroot.rs index 6f5c63eeb..f35bec42f 100644 --- a/src/chroot/chroot.rs +++ b/src/chroot/chroot.rs @@ -17,7 +17,6 @@ extern crate uucore; use uucore::libc::{self, setgid, setuid, chroot, setgroups}; use uucore::entries; -use getopts::Options; use std::ffi::CString; use std::io::{Error, Write}; use std::iter::FromIterator; @@ -25,31 +24,22 @@ use std::path::Path; use std::process::Command; static NAME: &'static str = "chroot"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... NEWROOT [COMMAND [ARG]...]"; +static SUMMARY: &'static str = "Run COMMAND with root directory set to NEWROOT."; +static LONG_HELP: &'static str = " + If COMMAND is not specified, it defaults to '$(SHELL) -i'. + If $(SHELL) is not set, /bin/sh is used. +"; pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optopt("u", "user", "User (ID or name) to switch before running the program", "USER"); - opts.optopt("g", "group", "Group (ID or name) to switch to", "GROUP"); - opts.optopt("G", "groups", "Comma-separated list of groups to switch to", "GROUP1,GROUP2..."); - opts.optopt("", "userspec", "Colon-separated user and group to switch to. \ + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optopt("u", "user", "User (ID or name) to switch before running the program", "USER") + .optopt("g", "group", "Group (ID or name) to switch to", "GROUP") + .optopt("G", "groups", "Comma-separated list of groups to switch to", "GROUP1,GROUP2...") + .optopt("", "userspec", "Colon-separated user and group to switch to. \ Same as -u USER -g GROUP. \ - Userspec has higher preference than -u and/or -g", "USER:GROUP"); - opts.optflag("h", "help", "Show help"); - opts.optflag("V", "version", "Show program's version"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("{}", f); - help_menu(opts); - return 1 - } - }; - - if matches.opt_present("V") { version(); return 0 } - if matches.opt_present("h") { help_menu(opts); return 0 } + Userspec has higher preference than -u and/or -g", "USER:GROUP") + .parse(args); if matches.free.is_empty() { println!("Missing operand: NEWROOT"); @@ -184,20 +174,3 @@ fn set_user(user: &str) { } } } - -fn version() { - println!("{} {}", NAME, VERSION) -} - -fn help_menu(options: Options) { - let msg = format!("{0} {1} - -Usage: - {0} [OPTION]... NEWROOT [COMMAND [ARG]...] - -Run COMMAND with root directory set to NEWROOT. -If COMMAND is not specified, it defaults to '$(SHELL) -i'. -If $(SHELL) is not set, /bin/sh is used.", NAME, VERSION); - - print!("{}", options.usage(&msg)); -} diff --git a/src/cksum/Cargo.toml b/src/cksum/Cargo.toml index 84bddcc5d..9f7bc96e8 100644 --- a/src/cksum/Cargo.toml +++ b/src/cksum/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_cksum" path = "cksum.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/cksum/cksum.rs b/src/cksum/cksum.rs index d5e5ea520..efb8dad19 100644 --- a/src/cksum/cksum.rs +++ b/src/cksum/cksum.rs @@ -9,12 +9,10 @@ * file that was distributed with this source code. */ -extern crate getopts; #[macro_use] extern crate uucore; -use getopts::Options; use std::fs::File; use std::io::{self, stdin, Read, Write, BufReader}; #[cfg(not(windows))] @@ -25,8 +23,9 @@ use crc_table::CRC_TABLE; mod crc_table; -static NAME: &'static str = "cksum"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTIONS] [FILE]..."; +static SUMMARY: &'static str = "Print CRC and size for each file"; +static LONG_HELP: &'static str = ""; #[inline] fn crc_update(crc: u32, input: u8) -> u32 { @@ -88,31 +87,8 @@ fn cksum(fname: &str) -> io::Result<(u32, usize)> { } pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] [FILE]... - -Print CRC and size for each file.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .parse(args); let files = matches.free; diff --git a/src/comm/Cargo.toml b/src/comm/Cargo.toml index a0fc8f92f..545b9b7d9 100644 --- a/src/comm/Cargo.toml +++ b/src/comm/Cargo.toml @@ -8,8 +8,9 @@ name = "uu_comm" path = "comm.rs" [dependencies] -getopts = "*" libc = "*" +getopts = "*" +uucore = { path="../uucore" } [[bin]] name = "comm" diff --git a/src/comm/comm.rs b/src/comm/comm.rs index c42efe2b2..749daa501 100644 --- a/src/comm/comm.rs +++ b/src/comm/comm.rs @@ -11,14 +11,17 @@ extern crate getopts; -use getopts::Options; +#[macro_use] +extern crate uucore; + use std::cmp::Ordering; use std::fs::File; use std::io::{self, BufRead, BufReader, stdin, Stdin}; use std::path::Path; -static NAME: &'static str = "comm"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTIONS] FILE1 FILE2"; +static SUMMARY: &'static str = "Compare sorted files line by line"; +static LONG_HELP: &'static str = ""; fn mkdelim(col: usize, opts: &getopts::Matches) -> String { let mut s = String::new(); @@ -122,39 +125,12 @@ fn open_file(name: &str) -> io::Result { } pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - opts.optflag("1", "", "suppress column 1 (lines uniq to FILE1)"); - opts.optflag("2", "", "suppress column 2 (lines uniq to FILE2)"); - opts.optflag("3", "", "suppress column 3 (lines that appear in both files)"); - opts.optopt("", "output-delimiter", "separate columns with STR", "STR"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") || matches.free.len() != 2 { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] FILE1 FILE2 - -Compare sorted files line by line.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - - if matches.free.len() != 2 { - return 1; - } - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("1", "", "suppress column 1 (lines uniq to FILE1)") + .optflag("2", "", "suppress column 2 (lines uniq to FILE2)") + .optflag("3", "", "suppress column 3 (lines that appear in both files)") + .optopt("", "output-delimiter", "separate columns with STR", "STR") + .parse(args); let mut f1 = open_file(matches.free[0].as_ref()).unwrap(); let mut f2 = open_file(matches.free[1].as_ref()).unwrap(); diff --git a/src/dircolors/Cargo.toml b/src/dircolors/Cargo.toml index e5aff0373..790f48a6d 100644 --- a/src/dircolors/Cargo.toml +++ b/src/dircolors/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_dircolors" path = "dircolors.rs" [dependencies] -getopts = "*" glob = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/dircolors/dircolors.rs b/src/dircolors/dircolors.rs index 6fd82f336..f35e13404 100644 --- a/src/dircolors/dircolors.rs +++ b/src/dircolors/dircolors.rs @@ -10,20 +10,23 @@ extern crate libc; extern crate glob; -extern crate getopts; #[macro_use] extern crate uucore; -use getopts::Options; use std::fs::File; use std::io::{BufRead, BufReader, Write}; use std::borrow::Borrow; use std::env; -static NAME: &'static str = "dircolors"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]"; +static SUMMARY: &'static str = "Output commands to set the LS_COLORS environment variable."; +static LONG_HELP: &'static str = " + If FILE is specified, read it to determine which colors to use for which + file types and extensions. Otherwise, a precompiled database is used. + For details on the format of these files, run 'dircolors --print-database' +"; mod colors; use colors::INTERNAL_DB; @@ -55,49 +58,15 @@ pub fn guess_syntax() -> OutputFmt { } pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("b", "sh", "output Bourne shell code to set LS_COLORS"); - opts.optflag("", + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("b", "sh", "output Bourne shell code to set LS_COLORS") + .optflag("", "bourne-shell", - "output Bourne shell code to set LS_COLORS"); - opts.optflag("c", "csh", "output C shell code to set LS_COLORS"); - opts.optflag("", "c-shell", "output C shell code to set LS_COLORS"); - opts.optflag("p", "print-database", "print the byte counts"); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - disp_err!("{}", f); - return 1; - } - }; - - if matches.opt_present("help") { - println!("Usage: {} [OPTION]... [FILE] -Output commands to set the LS_COLORS environment variable. - -Determine format of output: - -b, --sh, --bourne-shell output Bourne shell code to set LS_COLORS - -c, --csh, --c-shell output C shell code to set LS_COLORS - -p, --print-database output defaults - --help display this help and exit - --version output version information and exit - -If FILE is specified, read it to determine which colors to use for which -file types and extensions. Otherwise, a precompiled database is used. -For details on the format of these files, run 'dircolors --print-database'.", - NAME); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + "output Bourne shell code to set LS_COLORS") + .optflag("c", "csh", "output C shell code to set LS_COLORS") + .optflag("", "c-shell", "output C shell code to set LS_COLORS") + .optflag("p", "print-database", "print the byte counts") + .parse(args); if (matches.opt_present("csh") || matches.opt_present("c-shell") || matches.opt_present("sh") || matches.opt_present("bourne-shell")) && diff --git a/src/dirname/Cargo.toml b/src/dirname/Cargo.toml index 9800f0291..e1b6c447c 100644 --- a/src/dirname/Cargo.toml +++ b/src/dirname/Cargo.toml @@ -8,8 +8,8 @@ name = "uu_dirname" path = "dirname.rs" [dependencies] -getopts = "*" libc = "*" +uucore = { path="../uucore" } [[bin]] name = "dirname" diff --git a/src/dirname/dirname.rs b/src/dirname/dirname.rs index c189d6049..db5b2f095 100644 --- a/src/dirname/dirname.rs +++ b/src/dirname/dirname.rs @@ -9,42 +9,24 @@ * file that was distributed with this source code. */ -extern crate getopts; +#[macro_use] +extern crate uucore; use std::path::Path; -static NAME: &'static str = "dirname"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static NAME: &'static str = "dirname"; +static SYNTAX: &'static str = "[OPTION] NAME..."; +static SUMMARY: &'static str = "strip last component from file name"; +static LONG_HELP: &'static str = " + Output each NAME with its last non-slash component and trailing slashes + removed; if NAME contains no /'s, output '.' (meaning the current + directory). +"; pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("z", "zero", "separate output with NUL rather than newline"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => panic!("Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - strip last component from file name - -Usage: - {0} [OPTION] NAME... - -Output each NAME with its last non-slash component and trailing slashes -removed; if NAME contains no /'s, output '.' (meaning the current -directory).", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("z", "zero", "separate output with NUL rather than newline") + .parse(args); let separator = if matches.opt_present("zero") {"\0"} else {"\n"}; diff --git a/src/du/Cargo.toml b/src/du/Cargo.toml index a49e44ca6..dfba4477f 100644 --- a/src/du/Cargo.toml +++ b/src/du/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_du" path = "du.rs" [dependencies] -getopts = "*" libc = "*" time = "*" uucore = { path="../uucore" } diff --git a/src/du/du.rs b/src/du/du.rs index 5f91c67f1..22798714a 100644 --- a/src/du/du.rs +++ b/src/du/du.rs @@ -11,7 +11,6 @@ #![allow(non_snake_case)] -extern crate getopts; extern crate libc; extern crate time; @@ -27,8 +26,18 @@ use time::Timespec; use std::sync::mpsc::channel; use std::thread; -static NAME: &'static str = "du"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static NAME: &'static str = "du"; +static SUMMARY: &'static str = "estimate file space usage"; +static LONG_HELP: &'static str = " + Display values are in units of the first available SIZE from + --block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ‐ + ment variables. Otherwise, units default to 1024 bytes (or 512 if + POSIXLY_CORRECT is set). + + SIZE is an integer and optional unit (example: 10M is 10*1024*1024). + Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (pow‐ + ers of 1000). +"; struct Options { all: bool, @@ -119,22 +128,23 @@ fn du(path: &PathBuf, mut my_stat: Stat, options: Arc, depth: usize) -> } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - + let syntax = format!("[OPTION]... [FILE]... + {0} [OPTION]... --files0-from=F", NAME); + let matches = new_coreopts!(&syntax, SUMMARY, LONG_HELP) // In task - opts.optflag("a", "all", " write counts for all files, not just directories"); + .optflag("a", "all", " write counts for all files, not just directories") // In main - opts.optflag("", "apparent-size", "print apparent sizes, rather than disk usage; + .optflag("", "apparent-size", "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"); + in ('sparse') files, internal fragmentation, indirect blocks, and the like") // In main - opts.optopt("B", "block-size", "scale sizes by SIZE before printing them. + .optopt("B", "block-size", "scale sizes by SIZE before printing them. E.g., '-BM' prints sizes in units of 1,048,576 bytes. See SIZE format below.", - "SIZE"); + "SIZE") // In main - opts.optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'"); + .optflag("b", "bytes", "equivalent to '--apparent-size --block-size=1'") // In main - opts.optflag("c", "total", "produce a grand total"); + .optflag("c", "total", "produce a grand total") // In task // opts.optflag("D", "dereference-args", "dereference only symlinks that are listed // on the command line"), @@ -145,25 +155,25 @@ pub fn uumain(args: Vec) -> i32 { // // In task // opts.optflag("H", "", "equivalent to --dereference-args (-D)"), // In main - opts.optflag("h", "human-readable", "print sizes in human readable format (e.g., 1K 234M 2G)"); + .optflag("h", "human-readable", "print sizes in human readable format (e.g., 1K 234M 2G)") // In main - opts.optflag("", "si", "like -h, but use powers of 1000 not 1024"); + .optflag("", "si", "like -h, but use powers of 1000 not 1024") // In main - opts.optflag("k", "", "like --block-size=1K"); + .optflag("k", "", "like --block-size=1K") // In task - opts.optflag("l", "count-links", "count sizes many times if hard linked"); + .optflag("l", "count-links", "count sizes many times if hard linked") // // In main - opts.optflag("m", "", "like --block-size=1M"); + .optflag("m", "", "like --block-size=1M") // // In task // opts.optflag("L", "dereference", "dereference all symbolic links"), // // In task // opts.optflag("P", "no-dereference", "don't follow any symbolic links (this is the default)"), // // In main - opts.optflag("0", "null", "end each output line with 0 byte rather than newline"); + .optflag("0", "null", "end each output line with 0 byte rather than newline") // In main - opts.optflag("S", "separate-dirs", "do not include size of subdirectories"); + .optflag("S", "separate-dirs", "do not include size of subdirectories") // In main - opts.optflag("s", "summarize", "display only a total for each argument"); + .optflag("s", "summarize", "display only a total for each argument") // // In task // opts.optflag("x", "one-file-system", "skip directories on different file systems"), // // In task @@ -171,52 +181,17 @@ pub fn uumain(args: Vec) -> i32 { // // In task // opts.optopt("", "exclude", "exclude files that match PATTERN", "PATTERN"), // In main - opts.optopt("d", "max-depth", "print the total for a directory (or file, with --all) + .optopt("d", "max-depth", "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", "N"); + line argument; --max-depth=0 is the same as --summarize", "N") // In main - opts.optflagopt("", "time", "show time of the last modification of any file in the + .optflagopt("", "time", "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 or status", "WORD"); + atime, access, use, ctime or status", "WORD") // In main - opts.optopt("", "time-style", "show times using style STYLE: - full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE"); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("Invalid options\n{}", f); - return 1; - } - }; - - if matches.opt_present("help") { - println!("{program} {version} - estimate file space usage - -Usage - {program} [OPTION]... [FILE]... - {program} [OPTION]... --files0-from=F - -{usage} - -Display values are in units of the first available SIZE from ---block-size, and the DU_BLOCK_SIZE, BLOCK_SIZE and BLOCKSIZE environ‐ -ment variables. Otherwise, units default to 1024 bytes (or 512 if -POSIXLY_CORRECT is set). - -SIZE is an integer and optional unit (example: 10M is 10*1024*1024). -Units are K, M, G, T, P, E, Z, Y (powers of 1024) or KB, MB, ... (pow‐ -ers of 1000).", - program = NAME, - version = VERSION, - usage = opts.usage("Summarize disk usage of each FILE, recursively for directories.")); - return 0; - } else if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + .optopt("", "time-style", "show times using style STYLE: + full-iso, long-iso, iso, +FORMAT FORMAT is interpreted like 'date'", "STYLE") + .parse(args); let summarize = matches.opt_present("summarize"); diff --git a/src/echo/Cargo.toml b/src/echo/Cargo.toml index 968492310..741466dca 100644 --- a/src/echo/Cargo.toml +++ b/src/echo/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_echo" path = "echo.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/echo/echo.rs b/src/echo/echo.rs index b1c6b1b28..551bf5303 100644 --- a/src/echo/echo.rs +++ b/src/echo/echo.rs @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ -extern crate getopts; extern crate libc; #[macro_use] @@ -19,8 +18,25 @@ use std::io::Write; use std::str::from_utf8; #[allow(dead_code)] -static NAME: &'static str = "echo"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTIONS]... [STRING]..."; +static SUMMARY: &'static str = "display a line of text"; +static LONG_HELP: &'static str = r#" + Echo the STRING(s) to standard output. + If -e is in effect, the following sequences are recognized: + + \\\\ backslash + \\a alert (BEL) + \\b backspace + \\c produce no further output + \\e escape + \\f form feed + \\n new line + \\r carriage return + \\t horizontal tab + \\v vertical tab + \\0NNN byte with octal value NNN (1 to 3 digits) + \\xHH byte with hexadecimal value HH (1 to 2 digits) +"#; #[derive(Clone)] struct EchoOptions { @@ -77,101 +93,21 @@ fn convert_str(string: &[u8], index: usize, base: u32) -> (char, usize) { } } -fn parse_options(args: Vec, options: &mut EchoOptions) -> Option> { - let mut echo_args = vec!(); - 'argloop: for arg in args.into_iter().skip(1) { - match arg.as_ref() { - "--help" | "-h" => { - print_help(); - return None; - } - "--version" | "-V" => { - print_version(); - return None; - } - "-n" => options.newline = true, - "-e" => options.escape = true, - "-E" => options.escape = false, - _ => { - if arg.len() > 1 && arg.chars().next().unwrap_or('_') == '-' { - let mut newopts = options.clone(); - for ch in arg.chars().skip(1) { - match ch { - 'h' => { - print_help(); - return None; - } - 'V' => { - print_version(); - return None; - } - 'n' => newopts.newline = true, - 'e' => newopts.escape = true, - 'E' => newopts.escape = false, - _ => { - echo_args.push(arg.clone()); - continue 'argloop; - } - } - } - *options = newopts; - } else { - echo_args.push(arg); - } - } - } - } - Some(echo_args) -} - -fn print_help() { - let mut opts = getopts::Options::new(); - opts.optflag("n", "", "do not output the trailing newline"); - opts.optflag("e", "", "enable interpretation of backslash escapes"); - opts.optflag("E", "", "disable interpretation of backslash escapes (default)"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let msg = format!("{0} {1} - display a line of text - -Usage: - {0} [SHORT-OPTION]... [STRING]... - {0} LONG-OPTION - -Echo the STRING(s) to standard output. -If -e is in effect, the following sequences are recognized: - -\\\\ backslash -\\a alert (BEL) -\\b backspace -\\c produce no further output -\\e escape -\\f form feed -\\n new line -\\r carriage return -\\t horizontal tab -\\v vertical tab -\\0NNN byte with octal value NNN (1 to 3 digits) -\\xHH byte with hexadecimal value HH (1 to 2 digits)", NAME, VERSION); - - print!("{}", opts.usage(&msg)); -} - -fn print_version() { - println!("{} {}", NAME, VERSION); -} - pub fn uumain(args: Vec) -> i32 { let mut options = EchoOptions { newline: false, escape: false }; - let free = match parse_options(args, &mut options) { - Some(vec) => vec, - None => return 0 - }; + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("n", "", "do not output the trailing newline") + .optflag("e", "", "enable interpretation of backslash escapes") + .optflag("E", "", "disable interpretation of backslash escapes (default)") + .parse(args); + options.newline = matches.opt_present("n"); + options.escape = matches.opt_present("e"); + let free = matches.free; if !free.is_empty() { let string = free.join(" "); if options.escape { diff --git a/src/env/Cargo.toml b/src/env/Cargo.toml index d3d53c2ac..9822ec6b9 100644 --- a/src/env/Cargo.toml +++ b/src/env/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_env" path = "env.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/env/env.rs b/src/env/env.rs index dd4305e8f..eb57d69f1 100644 --- a/src/env/env.rs +++ b/src/env/env.rs @@ -20,8 +20,12 @@ use std::env; use std::io::Write; use std::process::Command; -static NAME: &'static str = "env"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static NAME: &'static str = "env"; +static SYNTAX: &'static str = "[OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]"; +static SUMMARY: &'static str = "Set each NAME to VALUE in the environment and run COMMAND"; +static LONG_HELP: &'static str = " + A mere - implies -i. If no COMMAND, print the resulting environment +"; struct options { ignore_env: bool, @@ -31,22 +35,6 @@ struct options { program: Vec } -fn usage() { - println!("Usage: {} [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]", NAME); - println!("Set each NAME to VALUE in the environment and run COMMAND\n"); - println!("Possible options are:"); - println!(" -i --ignore-environment\t start with an empty environment"); - println!(" -0 --null \t end each output line with a 0 byte rather than newline"); - println!(" -u --unset NAME \t remove variable from the environment"); - println!(" -h --help \t display this help and exit"); - println!(" -V --version \t output version information and exit\n"); - println!("A mere - implies -i. If no COMMAND, print the resulting environment"); -} - -fn version() { - println!("{} {}", NAME, VERSION); -} - // print name=value env pairs on screen // if null is true, separate pairs with a \0, \n otherwise fn print_env(null: bool) { @@ -56,7 +44,11 @@ fn print_env(null: bool) { } pub fn uumain(args: Vec) -> i32 { - // to handle arguments the same way than GNU env, we can't use getopts + let mut core_opts = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP); + core_opts.optflag("i", "ignore-environment", "start with an empty environment") + .optflag("0", "null", "end each output line with a 0 byte rather than newline") + .optopt("u", "unset", "remove variable from the environment", "NAME"); + let mut opts = Box::new(options { ignore_env: false, null: false, @@ -94,8 +86,8 @@ pub fn uumain(args: Vec) -> i32 { } } else if opt.starts_with("--") { match opt.as_ref() { - "--help" => { usage(); return 0; } - "--version" => { version(); return 0; } + "--help" => { core_opts.parse(vec![String::from("--help")]); return 0; } + "--version" => { core_opts.parse(vec![String::from("--version")]); return 0; } "--ignore-environment" => opts.ignore_env = true, "--null" => opts.null = true, @@ -128,8 +120,6 @@ pub fn uumain(args: Vec) -> i32 { for c in chars { // short versions of options match c { - 'h' => { usage(); return 0; } - 'V' => { version(); return 0; } 'i' => opts.ignore_env = true, '0' => opts.null = true, 'u' => { @@ -172,7 +162,7 @@ pub fn uumain(args: Vec) -> i32 { // read program arguments for opt in iter { - opts.program.push(opt.clone()); + opts.program.push(opt.clone()) } if opts.ignore_env { diff --git a/src/expand/Cargo.toml b/src/expand/Cargo.toml index 748b93168..5eeab0a34 100644 --- a/src/expand/Cargo.toml +++ b/src/expand/Cargo.toml @@ -8,9 +8,9 @@ name = "uu_expand" path = "expand.rs" [dependencies] -getopts = "*" libc = "*" unicode-width = "*" +getopts = "*" uucore = { path="../uucore" } [[bin]] diff --git a/src/expand/expand.rs b/src/expand/expand.rs index 7cfadbeb5..2ccfb376d 100644 --- a/src/expand/expand.rs +++ b/src/expand/expand.rs @@ -11,9 +11,9 @@ * file that was distributed with this source code. */ -extern crate getopts; extern crate libc; extern crate unicode_width; +extern crate getopts; #[macro_use] extern crate uucore; @@ -24,8 +24,10 @@ use std::iter::repeat; use std::str::from_utf8; use unicode_width::UnicodeWidthChar; -static NAME: &'static str = "expand"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]..."; +static SUMMARY: &'static str = "Convert tabs in each FILE to spaces, writing to standard output. + With no FILE, or when FILE is -, read standard input."; +static LONG_HELP: &'static str = ""; static DEFAULT_TABSTOP: usize = 8; @@ -89,32 +91,12 @@ impl Options { } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("i", "initial", "do not convert tabs after non blanks"); - opts.optopt("t", "tabs", "have tabs NUMBER characters apart, not 8", "NUMBER"); - opts.optopt("t", "tabs", "use comma separated list of explicit tab positions", "LIST"); - opts.optflag("U", "no-utf8", "interpret input file as 8-bit ASCII rather than UTF-8"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("help") { - println!("Usage: {} [OPTION]... [FILE]...", NAME); - println!("{}", opts.usage( - "Convert tabs in each FILE to spaces, writing to standard output.\n\ - With no FILE, or when FILE is -, read standard input.")); - return 0; - } - - if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("i", "initial", "do not convert tabs after non blanks") + .optopt("t", "tabs", "have tabs NUMBER characters apart, not 8", "NUMBER") + .optopt("t", "tabs", "use comma separated list of explicit tab positions", "LIST") + .optflag("U", "no-utf8", "interpret input file as 8-bit ASCII rather than UTF-8") + .parse(args); expand(Options::new(matches)); diff --git a/src/factor/Cargo.toml b/src/factor/Cargo.toml index 00118dda0..e3d505c14 100644 --- a/src/factor/Cargo.toml +++ b/src/factor/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_factor" path = "factor.rs" [dependencies] -getopts = "*" libc = "*" rand = "*" uucore = { path="../uucore" } diff --git a/src/factor/factor.rs b/src/factor/factor.rs index 91539cc6d..f58f12300 100644 --- a/src/factor/factor.rs +++ b/src/factor/factor.rs @@ -13,7 +13,6 @@ * that was distributed with this source code. */ -extern crate getopts; extern crate libc; extern crate rand; @@ -31,8 +30,10 @@ use std::mem::swap; mod numeric; mod prime_table; -static NAME: &'static str = "factor"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION] [NUMBER]..."; +static SUMMARY: &'static str = "Print the prime factors of the given number(s). + If none are specified, read from standard input."; +static LONG_HELP: &'static str = ""; fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 { if num < 1 << 63 { @@ -158,33 +159,8 @@ fn print_factors_str(num_str: &str) { } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("h", "help", "show this help message"); - opts.optflag("v", "version", "print the version and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: -\t{0} [NUMBER]... -\t{0} [OPTION] - -Print the prime factors of the given number(s). If none are specified, -read from standard input.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 1; - } - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .parse(args); if matches.free.is_empty() { for line in BufReader::new(stdin()).lines() { diff --git a/src/fmt/Cargo.toml b/src/fmt/Cargo.toml index 3378b79ad..8af1f9d17 100644 --- a/src/fmt/Cargo.toml +++ b/src/fmt/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_fmt" path = "fmt.rs" [dependencies] -getopts = "*" libc = "*" unicode-width = "*" uucore = { path="../uucore" } diff --git a/src/fmt/fmt.rs b/src/fmt/fmt.rs index 79c4f7fad..d2be2c105 100644 --- a/src/fmt/fmt.rs +++ b/src/fmt/fmt.rs @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ -extern crate getopts; extern crate unicode_width; #[macro_use] @@ -35,8 +34,9 @@ mod linebreak; mod parasplit; // program's NAME and VERSION are used for -V and -h -static NAME: &'static str = "fmt"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]..."; +static SUMMARY: &'static str = "Reformat paragraphs from input files (or stdin) to stdout."; +static LONG_HELP: &'static str = ""; pub type FileOrStdReader = BufReader>; pub struct FmtOptions { @@ -58,43 +58,21 @@ pub struct FmtOptions { } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("c", "crown-margin", "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."); - opts.optflag("t", "tagged-paragraph", "Like -c, except that the first and second line of a paragraph *must* have different indentation or they are treated as separate paragraphs."); - opts.optflag("m", "preserve-headers", "Attempt to detect and preserve mail headers in the input. Be careful when combining this flag with -p."); - opts.optflag("s", "split-only", "Split lines only, do not reflow."); - opts.optflag("u", "uniform-spacing", "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."); - - opts.optopt("p", "prefix", "Reformat only lines beginning with PREFIX, reattaching PREFIX to reformatted lines. Unless -x is specified, leading whitespace will be ignored when matching PREFIX.", "PREFIX"); - opts.optopt("P", "skip-prefix", "Do not reformat lines beginning with PSKIP. Unless -X is specified, leading whitespace will be ignored when matching PSKIP", "PSKIP"); - - opts.optflag("x", "exact-prefix", "PREFIX must match at the beginning of the line with no preceding whitespace."); - opts.optflag("X", "exact-skip-prefix", "PSKIP must match at the beginning of the line with no preceding whitespace."); - - opts.optopt("w", "width", "Fill output lines up to a maximum of WIDTH columns, default 79.", "WIDTH"); - opts.optopt("g", "goal", "Goal width, default ~0.94*WIDTH. Must be less than WIDTH.", "GOAL"); - - opts.optflag("q", "quick", "Break lines more quickly at the expense of a potentially more ragged appearance."); - - opts.optopt("T", "tab-width", "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.", "TABWIDTH"); - - opts.optflag("V", "version", "Output version information and exit."); - opts.optflag("h", "help", "Display this help message and exit."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}\nTry `{} --help' for more information.", f, NAME) - }; - - if matches.opt_present("h") { - println!("Usage: {} [OPTION]... [FILE]...\n\n{}", NAME, opts.usage("Reformat paragraphs from input files (or stdin) to stdout.")); - } - - if matches.opt_present("V") || matches.opt_present("h") { - println!("{} {}", NAME, VERSION); - return 0 - } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("c", "crown-margin", "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.") + .optflag("t", "tagged-paragraph", "Like -c, except that the first and second line of a paragraph *must* have different indentation or they are treated as separate paragraphs.") + .optflag("m", "preserve-headers", "Attempt to detect and preserve mail headers in the input. Be careful when combining this flag with -p.") + .optflag("s", "split-only", "Split lines only, do not reflow.") + .optflag("u", "uniform-spacing", "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.") + .optopt("p", "prefix", "Reformat only lines beginning with PREFIX, reattaching PREFIX to reformatted lines. Unless -x is specified, leading whitespace will be ignored when matching PREFIX.", "PREFIX") + .optopt("P", "skip-prefix", "Do not reformat lines beginning with PSKIP. Unless -X is specified, leading whitespace will be ignored when matching PSKIP", "PSKIP") + .optflag("x", "exact-prefix", "PREFIX must match at the beginning of the line with no preceding whitespace.") + .optflag("X", "exact-skip-prefix", "PSKIP must match at the beginning of the line with no preceding whitespace.") + .optopt("w", "width", "Fill output lines up to a maximum of WIDTH columns, default 79.", "WIDTH") + .optopt("g", "goal", "Goal width, default ~0.94*WIDTH. Must be less than WIDTH.", "GOAL") + .optflag("q", "quick", "Break lines more quickly at the expense of a potentially more ragged appearance.") + .optopt("T", "tab-width", "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.", "TABWIDTH") + .parse(args); let mut fmt_opts = FmtOptions { crown : false, diff --git a/src/fold/Cargo.toml b/src/fold/Cargo.toml index 99bc629e7..45e78a77e 100644 --- a/src/fold/Cargo.toml +++ b/src/fold/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_fold" path = "fold.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/fold/fold.rs b/src/fold/fold.rs index a5d1da874..b51a23451 100644 --- a/src/fold/fold.rs +++ b/src/fold/fold.rs @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ -extern crate getopts; extern crate libc; #[macro_use] @@ -19,56 +18,40 @@ use std::fs::File; use std::io::{BufRead, BufReader, Read, stdin, Write}; use std::path::Path; -static NAME: &'static str = "fold"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [FILE]..."; +static SUMMARY: &'static str = "Writes each file (or standard input if no files are given) + to standard output whilst breaking long lines"; +static LONG_HELP: &'static str = ""; pub fn uumain(args: Vec) -> i32 { let (args, obs_width) = handle_obsolete(&args[..]); - let mut opts = getopts::Options::new(); + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("b", "bytes", "count using bytes rather than columns (meaning control characters such as newline are not treated specially)") + .optflag("s", "spaces", "break lines at word boundaries rather than a hard cut-off") + .optopt("w", "width", "set WIDTH as the maximum line width rather than 80", "WIDTH") + .parse(args); - opts.optflag("b", "bytes", "count using bytes rather than columns (meaning control characters such as newline are not treated specially)"); - opts.optflag("s", "spaces", "break lines at word boundaries rather than a hard cut-off"); - opts.optopt("w", "width", "set WIDTH as the maximum line width rather than 80", "WIDTH"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "{}", f) - }; - - if matches.opt_present("h") { - println!("{} {}", NAME, VERSION); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]... [FILE]...", NAME); - println!(""); - print!("{}", opts.usage("Writes each file (or standard input if no files are given) to standard output whilst breaking long lines")); - } else if matches.opt_present("V") { - println!("{} {}", NAME, VERSION); - } else { - let bytes = matches.opt_present("b"); - let spaces = matches.opt_present("s"); - let poss_width = - if matches.opt_present("w") { - matches.opt_str("w") - } else { - obs_width - }; - let width = match poss_width { - Some(inp_width) => match inp_width.parse::() { - Ok(width) => width, - Err(e) => crash!(1, "illegal width value (\"{}\"): {}", inp_width, e) - }, - None => 80 - }; - let files = if matches.free.is_empty() { - vec!("-".to_owned()) + let bytes = matches.opt_present("b"); + let spaces = matches.opt_present("s"); + let poss_width = + if matches.opt_present("w") { + matches.opt_str("w") } else { - matches.free + obs_width }; - fold(files, bytes, spaces, width); - } + let width = match poss_width { + Some(inp_width) => match inp_width.parse::() { + Ok(width) => width, + Err(e) => crash!(1, "illegal width value (\"{}\"): {}", inp_width, e) + }, + None => 80 + }; + let files = if matches.free.is_empty() { + vec!("-".to_owned()) + } else { + matches.free + }; + fold(files, bytes, spaces, width); 0 } diff --git a/src/head/head.rs b/src/head/head.rs index eca492c7f..8b761336a 100644 --- a/src/head/head.rs +++ b/src/head/head.rs @@ -21,8 +21,9 @@ use std::fs::File; use std::path::Path; use std::str::from_utf8; -static NAME: &'static str = "head"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = ""; +static SUMMARY: &'static str = ""; +static LONG_HELP: &'static str = ""; enum FilterMode { Bytes(usize), @@ -47,35 +48,19 @@ pub fn uumain(args: Vec) -> i32 { let mut settings: Settings = Default::default(); // handle obsolete -number syntax - let options = match obsolete(&args[1..]) { + let new_args = match obsolete(&args[0..]) { (args, Some(n)) => { settings.mode = FilterMode::Lines(n); args }, (args, None) => args }; - let args = options; - - let mut opts = getopts::Options::new(); - - opts.optopt("c", "bytes", "Print the first K bytes. With the leading '-', print all but the last K bytes", "[-]K"); - opts.optopt("n", "lines", "Print the first K lines. With the leading '-', print all but the last K lines", "[-]K"); - opts.optflag("q", "quiet", "never print headers giving file names"); - opts.optflag("v", "verbose", "always print headers giving file names"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args) { - Ok (m) => { m } - Err(_) => { - println!("{}", opts.usage("")); - return 1; - } - }; - - if matches.opt_present("h") { - println!("{}", opts.usage("")); - return 0; - } - if matches.opt_present("V") { version(); return 0 } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optopt("c", "bytes", "Print the first K bytes. With the leading '-', print all but the last K bytes", "[-]K") + .optopt("n", "lines", "Print the first K lines. With the leading '-', print all but the last K lines", "[-]K") + .optflag("q", "quiet", "never print headers giving file names") + .optflag("v", "verbose", "always print headers giving file names") + .optflag("h", "help", "display this help and exit") + .optflag("V", "version", "output version information and exit") + .parse(new_args); let use_bytes = matches.opt_present("c"); @@ -155,7 +140,7 @@ pub fn uumain(args: Vec) -> i32 { // getopts works correctly. fn obsolete(options: &[String]) -> (Vec, Option) { let mut options: Vec = options.to_vec(); - let mut a = 0; + let mut a = 1; let b = options.len(); while a < b { @@ -203,7 +188,3 @@ fn head(reader: &mut BufReader, settings: &Settings) -> bool { } true } - -fn version() { - println!("{} {}", NAME, VERSION); -} diff --git a/src/hostid/Cargo.toml b/src/hostid/Cargo.toml index 985eebe3b..cab7329c8 100644 --- a/src/hostid/Cargo.toml +++ b/src/hostid/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_hostid" path = "hostid.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/hostid/hostid.rs b/src/hostid/hostid.rs index a266fbcfe..05e31f7d4 100644 --- a/src/hostid/hostid.rs +++ b/src/hostid/hostid.rs @@ -9,7 +9,6 @@ * that was distributed with this source code. */ -extern crate getopts; extern crate libc; #[macro_use] @@ -17,10 +16,9 @@ extern crate uucore; use libc::c_long; -static NAME: &'static str = "hostid"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); - -static EXIT_ERR: i32 = 1; +static SYNTAX: &'static str = "[options]"; +static SUMMARY: &'static str = ""; +static LONG_HELP: &'static str = ""; pub enum Mode { HostId, @@ -34,44 +32,12 @@ extern { } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(_) => { - help(&opts); - return EXIT_ERR; - }, - }; - - let mode = if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("help") { - Mode::Help - } else { - Mode::HostId - }; - - match mode { - Mode::HostId => hostid(), - Mode::Help => help(&opts), - Mode::Version => version(), - } - + new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .parse(args); + hostid(); 0 } -fn version() { - println!("{} {}", NAME, VERSION); -} - -fn help(opts: &getopts::Options) { - let msg = format!("Usage:\n {} [options]", NAME); - print!("{}", opts.usage(&msg)); -} - fn hostid() { /* * POSIX says gethostid returns a "32-bit identifier" but is silent diff --git a/src/hostname/Cargo.toml b/src/hostname/Cargo.toml index e135f99fd..dd8825f8f 100644 --- a/src/hostname/Cargo.toml +++ b/src/hostname/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_hostname" path = "hostname.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/hostname/hostname.rs b/src/hostname/hostname.rs index bd816413e..9cffe9a89 100644 --- a/src/hostname/hostname.rs +++ b/src/hostname/hostname.rs @@ -13,21 +13,20 @@ * https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt */ -extern crate getopts; extern crate libc; #[macro_use] extern crate uucore; -use getopts::Options; use std::collections::hash_set::HashSet; use std::iter::repeat; use std::str; use std::io::Write; use std::net::ToSocketAddrs; -static NAME: &'static str = "hostname"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTION]... [HOSTNAME]"; +static SUMMARY: &'static str = "Print or set the system's host name."; +static LONG_HELP: &'static str = ""; extern { fn gethostname(name: *mut libc::c_char, namelen: libc::size_t) -> libc::c_int; @@ -44,26 +43,12 @@ extern { } pub fn uumain(args: Vec) -> i32 { - let program = &args[0]; - - let mut opts = Options::new(); - opts.optflag("d", "domain", "Display the name of the DNS domain if possible"); - opts.optflag("i", "ip-address", "Display the network address(es) of the host"); - opts.optflag("f", "fqdn", "Display the FQDN (Fully Qualified Domain Name) (default)"); // TODO: support --long - opts.optflag("s", "short", "Display the short hostname (the portion before the first dot) if possible"); - opts.optflag("h", "help", "Show help"); - opts.optflag("V", "version", "Show program's version"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => { m } - _ => { help_menu(program, opts); return 0; } - }; - - if matches.opt_present("h") { - help_menu(program, opts); - return 0 - } - if matches.opt_present("V") { version(); return 0 } + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optflag("d", "domain", "Display the name of the DNS domain if possible") + .optflag("i", "ip-address", "Display the network address(es) of the host") + .optflag("f", "fqdn", "Display the FQDN (Fully Qualified Domain Name) (default)") // TODO: support --long + .optflag("s", "short", "Display the short hostname (the portion before the first dot) if possible") + .parse(args); match matches.free.len() { 0 => { @@ -120,25 +105,12 @@ pub fn uumain(args: Vec) -> i32 { } } 1 => xsethostname(matches.free.last().unwrap()), - _ => help_menu(program, opts) + _ => crash!(1, "{}", msg_wrong_number_of_arguments!(0, 1)) }; 0 } -fn version() { - println!("{} {}", NAME, VERSION); -} - -fn help_menu(program: &str, options: Options) { - version(); - println!(""); - println!("Usage:"); - println!(" {} [OPTION]... [HOSTNAME]", program); - println!(""); - print!("{}", options.usage("Print or set the system's host name.")); -} - fn xgethostname() -> String { let namelen = 256usize; let mut name : Vec = repeat(0).take(namelen).collect(); diff --git a/src/install/install.rs b/src/install/install.rs index 7aa97ae3d..2f00d6281 100644 --- a/src/install/install.rs +++ b/src/install/install.rs @@ -23,10 +23,13 @@ use std::path::{Path, PathBuf}; use std::result::Result; static NAME: &'static str = "install"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SUMMARY: &'static str = "Copy SOURCE to DEST or multiple SOURCE(s) to the existing + DIRECTORY, while setting permission modes and owner/group"; +static LONG_HELP: &'static str = ""; const DEFAULT_MODE: libc::mode_t = 755; +#[allow(dead_code)] pub struct Behaviour { main_function: MainFunction, specified_mode: Option, @@ -36,10 +39,6 @@ pub struct Behaviour { #[derive(Clone, Eq, PartialEq)] pub enum MainFunction { - /// Display version information. - Version, - /// Display help, including command line arguments. - Help, /// Create directories Directory, /// Install files to locations (primary functionality) @@ -61,18 +60,7 @@ impl Behaviour { /// Returns a program return code. /// pub fn uumain(args: Vec) -> i32 { - let opts = opts(); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => { - show_error!("Invalid options\n{}", f); - return 1; - } - }; - - let usage = opts.usage("Copy SOURCE to DEST or multiple SOURCE(s) to the existing\n \ - DIRECTORY, while setting permission modes and owner/group"); + let matches = parse_opts(args); if let Err(s) = check_unimplemented(&matches) { show_error!("Unimplemented feature: {}", s); @@ -97,14 +85,6 @@ pub fn uumain(args: Vec) -> i32 { }; match behaviour.main_function { - MainFunction::Version => { - println!("{} {}", NAME, VERSION); - 0 - }, - MainFunction::Help => { - help(&usage); - 0 - }, MainFunction::Directory => { directory(&paths[..], behaviour) }, @@ -118,74 +98,54 @@ pub fn uumain(args: Vec) -> i32 { /// /// Returns a getopts::Options struct. /// -fn opts() -> getopts::Options { - let mut opts = getopts::Options::new(); - +fn parse_opts(args: Vec) -> getopts::Matches { + let syntax = format!("SOURCE DEST + {} SOURCE... DIRECTORY", NAME); + new_coreopts!(&syntax, SUMMARY, LONG_HELP) // TODO implement flag - opts.optflagopt("", "backup", "(unimplemented) make a backup of each existing destination\n \ - file", "CONTROL"); - + .optflagopt("", "backup", "(unimplemented) make a backup of each existing destination\n \ + file", "CONTROL") // TODO implement flag - opts.optflag("b", "", "(unimplemented) like --backup but does not accept an argument"); - + .optflag("b", "", "(unimplemented) like --backup but does not accept an argument") // TODO implement flag - opts.optflag("C", "compare", "(unimplemented) compare each pair of source and destination\n \ - files, and in some cases, do not modify the destination at all"); - - opts.optflag("d", "directory", "treat all arguments as directory names;\n \ - create all components of the specified directories"); - - + .optflag("C", "compare", "(unimplemented) compare each pair of source and destination\n \ + files, and in some cases, do not modify the destination at all") + .optflag("d", "directory", "treat all arguments as directory names\n \ + create all components of the specified directories") // TODO implement flag - opts.optflag("D", "", "(unimplemented) create all leading components of DEST except the\n \ - last, then copy SOURCE to DEST"); - + .optflag("D", "", "(unimplemented) create all leading components of DEST except the\n \ + last, then copy SOURCE to DEST") // TODO implement flag - opts.optflagopt("g", "group", "(unimplemented) set group ownership, instead of process'\n \ - current group", "GROUP"); - - opts.optflagopt("m", "mode", "set permission mode (as in chmod), instead\n \ - of rwxr-xr-x", "MODE"); - + .optflagopt("g", "group", "(unimplemented) set group ownership, instead of process'\n \ + current group", "GROUP") + .optflagopt("m", "mode", "set permission mode (as in chmod), instead\n \ + of rwxr-xr-x", "MODE") // TODO implement flag - opts.optflagopt("o", "owner", "(unimplemented) set ownership (super-user only)", - "OWNER"); - + .optflagopt("o", "owner", "(unimplemented) set ownership (super-user only)", + "OWNER") // TODO implement flag - opts.optflag("p", "preserve-timestamps", "(unimplemented) apply access/modification times\n \ - of SOURCE files to corresponding destination files"); - + .optflag("p", "preserve-timestamps", "(unimplemented) apply access/modification times\n \ + of SOURCE files to corresponding destination files") // TODO implement flag - opts.optflag("s", "strip", "(unimplemented) strip symbol tables"); - + .optflag("s", "strip", "(unimplemented) strip symbol tables") // TODO implement flag - opts.optflagopt("", "strip-program", "(unimplemented) program used to strip binaries", - "PROGRAM"); - + .optflagopt("", "strip-program", "(unimplemented) program used to strip binaries", + "PROGRAM") // TODO implement flag - opts.optopt("S", "suffix", "(unimplemented) override the usual backup suffix", "SUFFIX"); - + .optopt("S", "suffix", "(unimplemented) override the usual backup suffix", "SUFFIX") // TODO implement flag - opts.optopt("t", "target-directory", "(unimplemented) move all SOURCE arguments into\n \ - DIRECTORY", "DIRECTORY"); - + .optopt("t", "target-directory", "(unimplemented) move all SOURCE arguments into\n \ + DIRECTORY", "DIRECTORY") // TODO implement flag - opts.optflag("T", "no-target-directory", "(unimplemented) treat DEST as a normal file"); - + .optflag("T", "no-target-directory", "(unimplemented) treat DEST as a normal file") // TODO implement flag - opts.optflag("v", "verbose", "(unimplemented) explain what is being done"); - + .optflag("v", "verbose", "(unimplemented) explain what is being done") // TODO implement flag - opts.optflag("P", "preserve-context", "(unimplemented) preserve security context"); - + .optflag("P", "preserve-context", "(unimplemented) preserve security context") // TODO implement flag - opts.optflagopt("Z", "context", "(unimplemented) set security context of files and\n \ - directories", "CONTEXT"); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - opts + .optflagopt("Z", "context", "(unimplemented) set security context of files and\n \ + directories", "CONTEXT") + .parse(args) } /// Check for unimplemented command line arguments. @@ -241,11 +201,7 @@ fn check_unimplemented(matches: &getopts::Matches) -> Result<(), &str> { /// In event of failure, returns an integer intended as a program return code. /// fn behaviour(matches: &getopts::Matches) -> Result { - let main_function = if matches.opt_present("version") { - MainFunction::Version - } else if matches.opt_present("help") { - MainFunction::Help - } else if matches.opt_present("directory") { + let main_function = if matches.opt_present("directory") { MainFunction::Directory } else { MainFunction::Standard @@ -295,15 +251,6 @@ fn behaviour(matches: &getopts::Matches) -> Result { }) } -/// Print utility help to stdout. -/// -fn help(usage: &str) { - println!("{0} {1}\n\n\ - Usage: {0} SOURCE DEST\n \ - or: {0} SOURCE... DIRECTORY\n\n\ - {2}", NAME, VERSION, usage); -} - /// Creates directories. /// /// GNU man pages describe this functionality as creating 'all components of diff --git a/src/kill/Cargo.toml b/src/kill/Cargo.toml index 711d6dfc7..f29aed1d5 100644 --- a/src/kill/Cargo.toml +++ b/src/kill/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_kill" path = "kill.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/kill/kill.rs b/src/kill/kill.rs index 8cab4e2e5..1c7e3639a 100644 --- a/src/kill/kill.rs +++ b/src/kill/kill.rs @@ -9,7 +9,6 @@ * that was distributed with this source code. */ -extern crate getopts; extern crate libc; #[macro_use] @@ -19,8 +18,9 @@ use libc::{c_int, pid_t}; use std::io::{Error, Write}; use uucore::signals::ALL_SIGNALS; -static NAME: &'static str = "kill"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[options] [...]"; +static SUMMARY: &'static str = ""; +static LONG_HELP: &'static str = ""; static EXIT_OK: i32 = 0; static EXIT_ERR: i32 = 1; @@ -30,34 +30,17 @@ pub enum Mode { Kill, Table, List, - Help, - Version, } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - opts.optopt("s", "signal", "specify the to be sent", "SIGNAL"); - opts.optflagopt("l", "list", "list all signal names, or convert one to a name", "LIST"); - opts.optflag("L", "table", "list all signal names in a nice table"); - let (args, obs_signal) = handle_obsolete(args); + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .optopt("s", "signal", "specify the to be sent", "SIGNAL") + .optflagopt("l", "list", "list all signal names, or convert one to a name", "LIST") + .optflag("L", "table", "list all signal names in a nice table") + .parse(args); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(_) => { - help(&opts); - return EXIT_ERR; - }, - }; - - let mode = if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("help") { - Mode::Help - } else if matches.opt_present("table") { + let mode = if matches.opt_present("table") { Mode::Table } else if matches.opt_present("list") { Mode::List @@ -69,17 +52,11 @@ pub fn uumain(args: Vec) -> i32 { Mode::Kill => return kill(&matches.opt_str("signal").unwrap_or(obs_signal.unwrap_or("9".to_owned())), matches.free), Mode::Table => table(), Mode::List => list(matches.opt_str("list")), - Mode::Help => help(&opts), - Mode::Version => version(), } 0 } -fn version() { - println!("{} {}", NAME, VERSION); -} - fn handle_obsolete(mut args: Vec) -> (Vec, Option) { let mut i = 0; while i < args.len() { @@ -156,15 +133,6 @@ fn list(arg: Option) { }; } -fn help(opts: &getopts::Options) { - let msg = format!("{0} {1} - -Usage: - {0} [options] [...]", NAME, VERSION); - - println!("{}", opts.usage(&msg)); -} - fn kill(signalname: &str, pids: std::vec::Vec) -> i32 { let mut status = 0; let optional_signal_value = uucore::signals::signal_by_name_or_value(signalname); diff --git a/src/link/Cargo.toml b/src/link/Cargo.toml index 648cab96e..f57088ad2 100644 --- a/src/link/Cargo.toml +++ b/src/link/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_link" path = "link.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/link/link.rs b/src/link/link.rs index 9c8a5e598..9b15728ea 100644 --- a/src/link/link.rs +++ b/src/link/link.rs @@ -9,8 +9,6 @@ * file that was distributed with this source code. */ -extern crate getopts; - #[macro_use] extern crate uucore; @@ -19,8 +17,9 @@ use std::io::Write; use std::path::Path; use std::io::Error; -static NAME: &'static str = "link"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = "[OPTIONS] FILE1 FILE2"; +static SUMMARY: &'static str = "Create a link named FILE2 to FILE1"; +static LONG_HELP: &'static str = ""; pub fn normalize_error_message(e: Error) -> String { match e.raw_os_error() { @@ -30,34 +29,10 @@ pub fn normalize_error_message(e: Error) -> String { } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(err) => panic!("{}", err), - }; - - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } - - if matches.opt_present("help") || matches.free.len() != 2 { - let msg = format!("{0} {1} - -Usage: - {0} [OPTIONS] FILE1 FILE2 - -Create a link named FILE2 to FILE1.", NAME, VERSION); - - println!("{}", opts.usage(&msg)); - if matches.free.len() != 2 { - return 1; - } - return 0; + let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) + .parse(args); + if matches.free.len() != 2 { + crash!(1, "{}", msg_wrong_number_of_arguments!(2)); } let old = Path::new(&matches.free[0]); diff --git a/src/ln/Cargo.toml b/src/ln/Cargo.toml index 7d4c19d66..ccce5bb02 100644 --- a/src/ln/Cargo.toml +++ b/src/ln/Cargo.toml @@ -8,7 +8,6 @@ name = "uu_ln" path = "ln.rs" [dependencies] -getopts = "*" libc = "*" uucore = { path="../uucore" } diff --git a/src/ln/ln.rs b/src/ln/ln.rs index 51192ddca..03c8170aa 100644 --- a/src/ln/ln.rs +++ b/src/ln/ln.rs @@ -9,7 +9,6 @@ * file that was distributed with this source code. */ -extern crate getopts; #[macro_use] extern crate uucore; @@ -20,8 +19,18 @@ use std::io::{BufRead, BufReader, Result, stdin, Write}; #[cfg(windows)] use std::os::windows::fs::symlink_file; use std::path::{Path, PathBuf}; -static NAME: &'static str = "ln"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static NAME: &'static str = "ln"; +static SUMMARY: &'static str = ""; +static LONG_HELP: &'static str = " + In the 1st form, create a link to TARGET with the name LINK_NAME. + In the 2nd form, create a link to TARGET in the current directory. + In the 3rd and 4th forms, create links to each TARGET in DIRECTORY. + Create hard links by default, symbolic links with --symbolic. + By default, each destination (name of new link) should not already exist. + When creating hard links, each TARGET must exist. Symbolic links + can hold arbitrary text; if later resolved, a relative link is + interpreted in relation to its parent directory. +"; pub struct Settings { overwrite: OverwriteMode, @@ -49,29 +58,26 @@ pub enum BackupMode { } pub fn uumain(args: Vec) -> i32 { - let mut opts = getopts::Options::new(); - - opts.optflag("b", "", "make a backup of each file that would otherwise be overwritten or removed"); - opts.optflagopt("", "backup", "make a backup of each file that would otherwise be overwritten or removed", "METHOD"); + let syntax = format!("[OPTION]... [-T] TARGET LINK_NAME (1st form) + {0} [OPTION]... TARGET (2nd form) + {0} [OPTION]... TARGET... DIRECTORY (3rd form) + {0} [OPTION]... -t DIRECTORY TARGET... (4th form)", NAME); + let matches = new_coreopts!(&syntax, SUMMARY, LONG_HELP) + .optflag("b", "", "make a backup of each file that would otherwise be overwritten or removed") + .optflagopt("", "backup", "make a backup of each file that would otherwise be overwritten or removed", "METHOD") // TODO: opts.optflag("d", "directory", "allow users with appropriate privileges to attempt to make hard links to directories"); - opts.optflag("f", "force", "remove existing destination files"); - opts.optflag("i", "interactive", "prompt whether to remove existing destination files"); + .optflag("f", "force", "remove existing destination files") + .optflag("i", "interactive", "prompt whether to remove existing destination files") // TODO: opts.optflag("L", "logical", "dereference TARGETs that are symbolic links"); // TODO: opts.optflag("n", "no-dereference", "treat LINK_NAME as a normal file if it is a symbolic link to a directory"); // TODO: opts.optflag("P", "physical", "make hard links directly to symbolic links"); // TODO: opts.optflag("r", "relative", "create symbolic links relative to link location"); - opts.optflag("s", "symbolic", "make symbolic links instead of hard links"); - opts.optopt("S", "suffix", "override the usual backup suffix", "SUFFIX"); - opts.optopt("t", "target-directory", "specify the DIRECTORY in which to create the links", "DIRECTORY"); - opts.optflag("T", "no-target-directory", "treat LINK_NAME as a normal file always"); - opts.optflag("v", "verbose", "print name of each linked file"); - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => crash!(1, "{}", e), - }; + .optflag("s", "symbolic", "make symbolic links instead of hard links") + .optopt("S", "suffix", "override the usual backup suffix", "SUFFIX") + .optopt("t", "target-directory", "specify the DIRECTORY in which to create the links", "DIRECTORY") + .optflag("T", "no-target-directory", "treat LINK_NAME as a normal file always") + .optflag("v", "verbose", "print name of each linked file") + .parse(args); let overwrite_mode = if matches.opt_present("force") { OverwriteMode::Force @@ -133,31 +139,7 @@ pub fn uumain(args: Vec) -> i32 { let string_to_path = |s: &String| { PathBuf::from(s) }; let paths: Vec = matches.free.iter().map(string_to_path).collect(); - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - 0 - } else if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: {0} [OPTION]... [-T] TARGET LINK_NAME (1st form) - or: {0} [OPTION]... TARGET (2nd form) - or: {0} [OPTION]... TARGET... DIRECTORY (3rd form) - or: {0} [OPTION]... -t DIRECTORY TARGET... (4th form) - -In the 1st form, create a link to TARGET with the name LINK_NAME. -In the 2nd form, create a link to TARGET in the current directory. -In the 3rd and 4th forms, create links to each TARGET in DIRECTORY. -Create hard links by default, symbolic links with --symbolic. -By default, each destination (name of new link) should not already exist. -When creating hard links, each TARGET must exist. Symbolic links -can hold arbitrary text; if later resolved, a relative link is -interpreted in relation to its parent directory.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - 0 - } else { - exec(&paths[..], &settings) - } + exec(&paths[..], &settings) } fn exec(files: &[PathBuf], settings: &Settings) -> i32 { diff --git a/src/logname/logname.rs b/src/logname/logname.rs index b5b245456..7b009b433 100644 --- a/src/logname/logname.rs +++ b/src/logname/logname.rs @@ -11,7 +11,6 @@ /* last synced with: logname (GNU coreutils) 8.22 */ -extern crate getopts; extern crate libc; #[macro_use] @@ -36,38 +35,12 @@ fn get_userlogin() -> Option { } } -static NAME: &'static str = "logname"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static SYNTAX: &'static str = ""; +static SUMMARY: &'static str = "Print user's login name"; +static LONG_HELP: &'static str = ""; pub fn uumain(args: Vec) -> i32 { - // - // Argument parsing - // - let mut opts = getopts::Options::new(); - - opts.optflag("h", "help", "display this help and exit"); - opts.optflag("V", "version", "output version information and exit"); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(f) => crash!(1, "Invalid options\n{}", f) - }; - - if matches.opt_present("help") { - let msg = format!("{0} {1} - -Usage: - {0} - -Print user's login name.", NAME, VERSION); - - print!("{}", opts.usage(&msg)); - return 0; - } - if matches.opt_present("version") { - println!("{} {}", NAME, VERSION); - return 0; - } + new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args); exec(); @@ -77,6 +50,6 @@ Print user's login name.", NAME, VERSION); fn exec() { match get_userlogin() { Some(userlogin) => println!("{}", userlogin), - None => println!("{}: no login name", NAME) + None => show_error!("no login name") } } diff --git a/src/ls/ls.rs b/src/ls/ls.rs index ac6c3fbc2..f73cf4326 100644 --- a/src/ls/ls.rs +++ b/src/ls/ls.rs @@ -27,7 +27,6 @@ extern crate uucore; use uucore::libc::{S_ISUID, S_ISGID, S_ISVTX, S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH, mode_t}; -use getopts::Options; use std::fs; use std::fs::{DirEntry, FileType, Metadata}; use std::path::{Path, PathBuf}; @@ -44,15 +43,13 @@ use unicode_width::UnicodeWidthStr; #[cfg(windows)] use std::os::windows::fs::MetadataExt; -#[derive(Copy, Clone, PartialEq)] -enum Mode { - Help, - Version, - List, -} - -static NAME: &'static str = "ls"; -static VERSION: &'static str = env!("CARGO_PKG_VERSION"); +static NAME: &'static str = "ls"; +static SUMMARY: &'static str = ""; +static LONG_HELP: &'static str = " + By default, ls will list the files and contents of any directories on + the command line, expect that it will ignore files and directories + whose names start with '.' +"; static DEFAULT_COLORS: &'static str = "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"; @@ -76,105 +73,65 @@ lazy_static! { } pub fn uumain(args: Vec) -> i32 { - let mut opts = Options::new(); - - opts.optflag("", "help", "display this help and exit"); - opts.optflag("", "version", "output version information and exit"); - - opts.optflag("a", + let syntax = format!("[OPTION]... DIRECTORY + {0} [OPTION]... [FILE]...", NAME); + let matches = new_coreopts!(&syntax, SUMMARY, LONG_HELP) + .optflag("a", "all", - "Do not ignore hidden files (files with names that start with '.')."); - opts.optflag("A", + "Do not ignore hidden files (files with names that start with '.').") + .optflag("A", "almost-all", "In a directory, do not ignore all file names that start with '.', only ignore \ - '.' and '..'."); - opts.optflag("c", + '.' and '..'.") + .optflag("c", "", "If the long listing format (e.g., -l, -o) is being used, print the status \ change time (the ‘ctime’ in the inode) instead of the modification time. When \ explicitly sorting by time (--sort=time or -t) or when not using a long listing \ - format, sort according to the status change time."); - opts.optflag("d", + format, sort according to the status change time.") + .optflag("d", "directory", "Only list the names of directories, rather than listing directory contents. \ This will not follow symbolic links unless one of `--dereference-command-line \ (-H)`, `--dereference (-L)`, or `--dereference-command-line-symlink-to-dir` is \ - specified."); - opts.optflag("F", + specified.") + .optflag("F", "classify", "Append a character to each file name indicating the file type. Also, for \ regular files that are executable, append '*'. The file type indicators are \ '/' for directories, '@' for symbolic links, '|' for FIFOs, '=' for sockets, \ - '>' for doors, and nothing for regular files."); - opts.optflag("h", + '>' for doors, and nothing for regular files.") + .optflag("h", "human-readable", - "Print human readable file sizes (e.g. 1K 234M 56G)."); - opts.optflag("L", + "Print human readable file sizes (e.g. 1K 234M 56G).") + .optflag("L", "dereference", "When showing file information for a symbolic link, show information for the \ - file the link references rather than the link itself."); - opts.optflag("l", "long", "Display detailed information."); - opts.optflag("r", + file the link references rather than the link itself.") + .optflag("l", "long", "Display detailed information.") + .optflag("r", "reverse", "Reverse whatever the sorting method is--e.g., list files in reverse \ - alphabetical order, youngest first, smallest first, or whatever."); - opts.optflag("R", + alphabetical order, youngest first, smallest first, or whatever.") + .optflag("R", "recursive", - "List the contents of all directories recursively."); - opts.optflag("S", "", "Sort by file size, largest first."); - opts.optflag("t", + "List the contents of all directories recursively.") + .optflag("S", "", "Sort by file size, largest first.") + .optflag("t", "", - "Sort by modification time (the 'mtime' in the inode), newest first."); - opts.optflag("U", + "Sort by modification time (the 'mtime' in the inode), newest first.") + .optflag("U", "", "Do not sort; list the files in whatever order they are stored in the \ directory. This is especially useful when listing very large directories, \ - since not doing any sorting can be noticeably faster."); - opts.optflag("", "color", "Color output based on file type."); - - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { - disp_err!("{}", e); - return 1; - } - }; - - let mode = if matches.opt_present("version") { - Mode::Version - } else if matches.opt_present("help") { - Mode::Help - } else { - Mode::List - }; - - match mode { - Mode::Version => version(), - Mode::Help => help(), - Mode::List => list(matches), - } + since not doing any sorting can be noticeably faster.") + .optflag("", "color", "Color output based on file type.") + .parse(args); + list(matches); 0 } -fn version() { - println!("{} {}", NAME, VERSION); -} - -fn help() { - let msg = format!("{0} {1}\n\n\ - Usage: {0} [OPTION]... DIRECTORY\n \ - or: {0} [OPTION]... [FILE]...\n \ - \n \ - By default, ls will list the files and contents of any directories on \ - the command line, expect that it will ignore files and directories \ - whose names start with '.'. \n\ - \n", - NAME, - VERSION); - println!("{}", msg); -} - fn list(options: getopts::Matches) { let locs: Vec = if options.free.is_empty() { vec![String::from(".")] diff --git a/tests/test_base32.rs b/tests/test_base32.rs index 51abe7e97..5febba29d 100644 --- a/tests/test_base32.rs +++ b/tests/test_base32.rs @@ -76,7 +76,7 @@ fn test_wrap_no_arg() { new_ucmd() .arg(wrap_param) .fails() - .stderr_only(format!("base32: Argument to option '{}' missing.\nTry 'base32 --help' for more information.\n", + .stderr_only(format!("base32: error: Argument to option '{}' missing.\n", if wrap_param == "-w" { "w" } else { "wrap" })); } } diff --git a/tests/test_base64.rs b/tests/test_base64.rs index 3425923bb..24ac408b3 100644 --- a/tests/test_base64.rs +++ b/tests/test_base64.rs @@ -68,7 +68,7 @@ fn test_wrap_no_arg() { new_ucmd() .arg(wrap_param) .fails() - .stderr_only(format!("base64: Argument to option '{}' missing.\nTry 'base64 --help' for more information.\n", + .stderr_only(format!("base64: error: Argument to option '{}' missing.\n", if wrap_param == "-w" { "w" } else { "wrap" })); } } diff --git a/tests/test_install.rs b/tests/test_install.rs index e81f71502..cd003c0d0 100644 --- a/tests/test_install.rs +++ b/tests/test_install.rs @@ -13,7 +13,7 @@ fn test_install_help() { let (_, mut ucmd) = at_and_ucmd(); assert!( - ucmd.arg("--help").succeeds().no_stderr().stdout.contains("Usage:")); + ucmd.arg("--help").succeeds().no_stderr().stdout.contains("Options:")); } #[test]