mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #951 from nathanross/message-templates
Add Message templates
This commit is contained in:
commit
3618d9df94
8 changed files with 183 additions and 56 deletions
|
@ -8,7 +8,6 @@ name = "uu_arch"
|
|||
path = "arch.rs"
|
||||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "*"
|
||||
uucore = { path="../uucore" }
|
||||
|
||||
|
|
|
@ -9,14 +9,12 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::io::Write;
|
||||
use std::mem::uninitialized;
|
||||
use uucore::c_types::utsname;
|
||||
|
||||
|
@ -44,28 +42,15 @@ static NAME: &'static str = "arch";
|
|||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = getopts::Options::new();
|
||||
let mut opts = uucore::coreopts::CoreOptions::new();
|
||||
let usage = opts.usage("Determine architecture name for current machine.");
|
||||
opts.help(format!("
|
||||
{0} {1}
|
||||
|
||||
opts.optflag("", "help", "display this help and exit");
|
||||
opts.optflag("", "version", "output version information and exit");
|
||||
{0}
|
||||
|
||||
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("help") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
println!("");
|
||||
println!("Usage:");
|
||||
println!(" {} [OPTIONS]...", NAME);
|
||||
println!("");
|
||||
print!("{}", opts.usage("Print machine architecture name."));
|
||||
return 0;
|
||||
} else if matches.opt_present("version") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
return 0;
|
||||
}
|
||||
{2}
|
||||
", NAME, VERSION, usage)).parse(args);
|
||||
|
||||
let machine_arch = unsafe { get_machine_arch() };
|
||||
let mut output = String::new();
|
||||
|
|
|
@ -8,7 +8,6 @@ name = "uu_cut"
|
|||
path = "cut.rs"
|
||||
|
||||
[dependencies]
|
||||
getopts = "*"
|
||||
libc = "*"
|
||||
uucore = { path="../uucore" }
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
extern crate getopts;
|
||||
extern crate libc;
|
||||
|
||||
#[macro_use]
|
||||
|
@ -379,7 +378,7 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> i32 {
|
|||
let path = Path::new(&filename[..]);
|
||||
|
||||
if !path.exists() {
|
||||
show_error!("{}: No such file or directory", filename);
|
||||
show_error!("{}", msg_args_nonexistent_file!(filename));
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -403,7 +402,7 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> i32 {
|
|||
}
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = getopts::Options::new();
|
||||
let mut opts = uucore::coreopts::CoreOptions::new();
|
||||
|
||||
opts.optopt("b", "bytes", "filter byte columns from the input source", "sequence");
|
||||
opts.optopt("c", "characters", "alias for character mode", "sequence");
|
||||
|
@ -413,19 +412,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
opts.optflag("", "complement", "invert the filter - instead of displaying only the filtered columns, display all but those columns");
|
||||
opts.optflag("s", "only-delimited", "in field mode, only print lines which contain the delimiter");
|
||||
opts.optopt("", "output-delimiter", "in field mode, replace the delimiter in output lines with this option's argument", "new delimiter");
|
||||
opts.optflag("", "help", "print usage information");
|
||||
opts.optflag("", "version", "print version information");
|
||||
|
||||
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") {
|
||||
print!("
|
||||
let usage = opts.usage("Prints specified byte or field columns from each line of stdin or the input files");
|
||||
opts.help(format!("
|
||||
{0} {1}
|
||||
|
||||
{0} [-d] [-s] [-z] [--output-delimiter] ((-f|-b|-c) {{sequence}}) {{sourcefile}}+
|
||||
|
@ -501,14 +489,8 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
it will replace the delimiter character in each line printed. This is
|
||||
useful for transforming tabular data - e.g. to convert a CSV to a
|
||||
TSV (tab-separated file)
|
||||
", NAME, VERSION, opts.usage("Prints specified byte or field columns from each line of stdin or the input files"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if matches.opt_present("version") {
|
||||
println!("{} {}", NAME, VERSION);
|
||||
return 0;
|
||||
}
|
||||
", NAME, VERSION, usage));
|
||||
let matches = opts.parse(args);
|
||||
|
||||
let complement = matches.opt_present("complement");
|
||||
|
||||
|
@ -542,7 +524,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
match matches.opt_str("delimiter") {
|
||||
Some(delim) => {
|
||||
if delim.chars().count() > 1 {
|
||||
Err("the delimiter must be a single character, or the empty string for null".to_owned())
|
||||
Err(msg_opt_invalid_should_be!("empty or 1 character long", "a value 2 characters or longer", "--delimiter", "-d").to_owned())
|
||||
} else {
|
||||
let delim = if delim.is_empty() {
|
||||
"\0".to_owned()
|
||||
|
@ -569,9 +551,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
)
|
||||
}
|
||||
(ref b, ref c, ref f) if b.is_some() || c.is_some() || f.is_some() => {
|
||||
Err("only one type of list may be specified".to_owned())
|
||||
Err(msg_expects_no_more_than_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)").to_owned())
|
||||
}
|
||||
_ => Err("you must specify a list of bytes, characters, or fields".to_owned())
|
||||
_ => Err(msg_expects_one_of!("--fields (-f)", "--chars (-c)", "--bytes (-b)").to_owned())
|
||||
};
|
||||
|
||||
let mode_parse = match mode_parse {
|
||||
|
@ -579,9 +561,9 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
Ok(mode) => {
|
||||
match mode {
|
||||
Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.opt_present("delimiter") =>
|
||||
Err("an input delimiter may be specified only when operating on fields".to_owned()),
|
||||
Err(msg_opt_only_usable_if!("printing a sequence of fields", "--delimiter", "-d").to_owned()),
|
||||
Mode::Bytes(_, _) | Mode::Characters(_, _) if matches.opt_present("only-delimited") =>
|
||||
Err("suppressing non-delimited lines makes sense only when operating on fields".to_owned()),
|
||||
Err(msg_opt_only_usable_if!("printing a sequence of fields", "--only-delimited", "-s").to_owned()),
|
||||
_ => Ok(mode),
|
||||
}
|
||||
}
|
||||
|
@ -590,9 +572,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
match mode_parse {
|
||||
Ok(mode) => cut_files(matches.free, mode),
|
||||
Err(err_msg) => {
|
||||
show_error!("{}\n\
|
||||
Try '{} --help' for more information",
|
||||
err_msg, args[0]);
|
||||
show_error!("{}", err_msg);
|
||||
1
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ authors = []
|
|||
[dependencies]
|
||||
libc = "*"
|
||||
winapi = "*"
|
||||
getopts = "*"
|
||||
data-encoding = "^1.1"
|
||||
|
||||
[lib]
|
||||
|
|
53
src/uucore/coreopts.rs
Normal file
53
src/uucore/coreopts.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
extern crate getopts;
|
||||
use std::io::Write;
|
||||
|
||||
pub struct CoreOptions {
|
||||
pub options : getopts::Options,
|
||||
longhelp : Option<String>
|
||||
}
|
||||
|
||||
impl<'a> CoreOptions {
|
||||
pub fn new() -> Self {
|
||||
let mut ret = CoreOptions {
|
||||
options : getopts::Options::new(),
|
||||
longhelp : None
|
||||
};
|
||||
ret.options
|
||||
.optflag("", "help", "print usage information")
|
||||
.optflag("", "version", "print name and version number");
|
||||
ret
|
||||
}
|
||||
pub fn optopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions {
|
||||
self.options.optopt(short_name, long_name, desc, hint);
|
||||
self
|
||||
}
|
||||
pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut CoreOptions {
|
||||
self.options.optflag(short_name, long_name, desc);
|
||||
self
|
||||
}
|
||||
pub fn help<T: Into<String>>(&mut self, longhelp : T) -> &mut CoreOptions {
|
||||
self.longhelp = Some(longhelp.into());
|
||||
self
|
||||
}
|
||||
pub fn usage(&self, summary : &str) -> String {
|
||||
self.options.usage(summary)
|
||||
}
|
||||
pub fn parse(&mut self, args : Vec<String>) -> getopts::Matches {
|
||||
let matches = match self.options.parse(&args[1..]) {
|
||||
Ok(m) => { Some(m) },
|
||||
Err(f) => {
|
||||
crash!(1, "{}", msg_invalid_input!(format!("{}", f)));
|
||||
}
|
||||
}.unwrap();
|
||||
if matches.opt_present("help") {
|
||||
exit!(match self.longhelp {
|
||||
Some(ref lhelp) => { print!("{}", lhelp); 0}
|
||||
None => 1
|
||||
});
|
||||
} else if matches.opt_present("version") {
|
||||
print!("{}", msg_version!());
|
||||
exit!(0);
|
||||
}
|
||||
matches
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ pub mod fs;
|
|||
pub mod parse_time;
|
||||
pub mod utf8;
|
||||
pub mod encoding;
|
||||
pub mod coreopts;
|
||||
|
||||
#[cfg(unix)] pub mod c_types;
|
||||
#[cfg(unix)] pub mod process;
|
||||
|
|
|
@ -239,3 +239,112 @@ macro_rules! safe_unwrap(
|
|||
}
|
||||
)
|
||||
);
|
||||
|
||||
//-- message templates
|
||||
|
||||
//-- message templates : general
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! snippet_list_join_oxford {
|
||||
($conjunction:expr, $valOne:expr, $valTwo:expr) => (
|
||||
format!("{}, {} {}", $valOne, $conjunction, $valTwo)
|
||||
);
|
||||
($conjunction:expr, $valOne:expr, $valTwo:expr $(, $remainingVals:expr)*) => (
|
||||
format!("{}, {}", $valOne, snippet_list_join_inner!($conjunction, $valTwo $(, $remainingVals)*))
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! snippet_list_join_or {
|
||||
($valOne:expr, $valTwo:expr) => (
|
||||
format!("{} or {}", $valOne, $valTwo)
|
||||
);
|
||||
($valOne:expr, $valTwo:expr $(, $remainingVals:expr)*) => (
|
||||
format!("{}, {}", $valOne, snippet_list_join_oxford!("or", $valTwo $(, $remainingVals)*))
|
||||
);
|
||||
}
|
||||
|
||||
//-- message templates : help and version
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_version {
|
||||
() => (
|
||||
format!("{} {}", executable!(), env!("CARGO_PKG_VERSION"))
|
||||
)
|
||||
}
|
||||
|
||||
//-- message templates : invalid input
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_invalid_input { ($reason: expr) => (
|
||||
format!("invalid input: {}", $reason) ); }
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! snippet_no_file_at_path { ($path:expr) => (
|
||||
format!("nonexistent path {}", $path) ); }
|
||||
|
||||
// -- message templates : invalid input : flag
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_invalid_opt_use {
|
||||
($about:expr, $flag:expr) => (
|
||||
msg_invalid_input!(format!("The '{}' option {}", $flag, $about))
|
||||
);
|
||||
($about:expr, $longflag:expr, $shortflag:expr) => {
|
||||
msg_invalid_input!(format!("The '{}' ('{}') option {}", $longflag, $shortflag, $about))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_opt_only_usable_if {
|
||||
($clause:expr, $flag:expr) => (
|
||||
msg_invalid_opt_use!(format!("only usable if {}", $clause), $flag)
|
||||
);
|
||||
($clause:expr, $longflag:expr, $shortflag:expr) => (
|
||||
msg_invalid_opt_use!(format!("only usable if {}", $clause), $longflag, $shortflag)
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_opt_invalid_should_be {
|
||||
($expects:expr, $received:expr, $flag:expr) => (
|
||||
msg_invalid_opt_use!(format!("expects {}, but was provided {}", $expects, $received), $flag)
|
||||
);
|
||||
($expects:expr, $received:expr, $longflag:expr, $shortflag:expr) => (
|
||||
msg_invalid_opt_use!(format!("expects {}, but was provided {}", $expects, $received), $longflag, $shortflag)
|
||||
);
|
||||
}
|
||||
|
||||
// -- message templates : invalid input : args
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_arg_invalid_value { ($expects:expr, $received:expr) => (
|
||||
msg_invalid_input!(format!("expects its argument to be {}, but was provided {}", $expects, $received)) ); }
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_args_invalid_value { ($expects:expr, $received:expr) => (
|
||||
msg_invalid_input!(format!("expects its arguments to be {}, but was provided {}", $expects, $received)) ); }
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_args_nonexistent_file { ($received:expr) => (
|
||||
msg_args_invalid_value!("paths to files", snippet_no_file_at_path!($received)));}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_wrong_number_of_arguments { ($received:expr) => (
|
||||
msg_args_invalid_value!("wrong number of arguments") ); }
|
||||
|
||||
// -- message templates : invalid input : input combinations
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_expects_one_of {
|
||||
($valOne:expr $(, $remainingVals:expr)*) => (
|
||||
msg_invalid_input!(format!("expects one of {}", snippet_list_join_or!($valOne $(, $remainingVals)*)))
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_expects_no_more_than_one_of {
|
||||
($valOne:expr $(, $remainingVals:expr)*) => (
|
||||
msg_invalid_input!(format!("expects no more than one of {}", snippet_list_join_or!($valOne $(, $remainingVals)*))) ;
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue