mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Merge pull request #961 from nathanross/coreopts-further-refinement
Coreopts further refinement
This commit is contained in:
commit
9b82387960
7 changed files with 189 additions and 191 deletions
|
@ -18,6 +18,10 @@ use std::ffi::CStr;
|
|||
use std::mem::uninitialized;
|
||||
use uucore::c_types::utsname;
|
||||
|
||||
static SYNTAX: &'static str = "";
|
||||
static SUMMARY: &'static str = "Determine architecture name for current machine.";
|
||||
static LONG_HELP: &'static str = "";
|
||||
|
||||
struct Arch {
|
||||
arch_name: String
|
||||
}
|
||||
|
@ -38,19 +42,8 @@ unsafe fn get_machine_arch() -> Arch {
|
|||
}
|
||||
}
|
||||
|
||||
static NAME: &'static str = "arch";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = uucore::coreopts::CoreOptions::new(NAME);
|
||||
let usage = opts.usage("Determine architecture name for current machine.");
|
||||
opts.help(format!("
|
||||
{0} {1}
|
||||
|
||||
{0}
|
||||
|
||||
{2}
|
||||
", NAME, VERSION, usage)).parse(args);
|
||||
new_coreopts!(SYNTAX, SUMMARY, LONG_HELP).parse(args);
|
||||
|
||||
let machine_arch = unsafe { get_machine_arch() };
|
||||
let mut output = String::new();
|
||||
|
|
175
src/cut/cut.rs
175
src/cut/cut.rs
|
@ -25,8 +25,87 @@ mod buffer;
|
|||
mod ranges;
|
||||
mod searcher;
|
||||
|
||||
static NAME: &'static str = "cut";
|
||||
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||
static SYNTAX: &'static str = "[-d] [-s] [-z] [--output-delimiter] ((-f|-b|-c) {{sequence}}) {{sourcefile}}+";
|
||||
static SUMMARY: &'static str = "Prints specified byte or field columns from each line of stdin or the input files";
|
||||
static LONG_HELP: &'static str = "
|
||||
Each call must specify a mode (what to use for columns),
|
||||
a sequence (which columns to print), and provide a data source
|
||||
|
||||
Specifying a mode
|
||||
|
||||
Use --bytes (-b) or --characters (-c) to specify byte mode
|
||||
|
||||
Use --fields (-f) to specify field mode, where each line is broken into
|
||||
fields identified by a delimiter character. For example for a typical CSV
|
||||
you could use this in combination with setting comma as the delimiter
|
||||
|
||||
Specifying a sequence
|
||||
|
||||
A sequence is a group of 1 or more numbers or inclusive ranges separated
|
||||
by a commas.
|
||||
|
||||
cut -f 2,5-7 some_file.txt
|
||||
will display the 2nd, 5th, 6th, and 7th field for each source line
|
||||
|
||||
Ranges can extend to the end of the row by excluding the the second number
|
||||
|
||||
cut -f 3- some_file.txt
|
||||
will display the 3rd field and all fields after for each source line
|
||||
|
||||
The first number of a range can be excluded, and this is effectively the
|
||||
same as using 1 as the first number: it causes the range to begin at the
|
||||
first column. Ranges can also display a single column
|
||||
|
||||
cut -f 1,3-5 some_file.txt
|
||||
will display the 1st, 3rd, 4th, and 5th field for each source line
|
||||
|
||||
The --complement option, when used, inverts the effect of the sequence
|
||||
|
||||
cut --complement -f 4-6 some_file.txt
|
||||
will display the every field but the 4th, 5th, and 6th
|
||||
|
||||
Specifying a data source
|
||||
|
||||
If no sourcefile arguments are specified, stdin is used as the source of
|
||||
lines to print
|
||||
|
||||
If sourcefile arguments are specified, stdin is ignored and all files are
|
||||
read in consecutively if a sourcefile is not successfully read, a warning
|
||||
will print to stderr, and the eventual status code will be 1, but cut
|
||||
will continue to read through proceeding sourcefiles
|
||||
|
||||
To print columns from both STDIN and a file argument, use - (dash) as a
|
||||
sourcefile argument to represent stdin.
|
||||
|
||||
Field Mode options
|
||||
|
||||
The fields in each line are identified by a delimiter (separator)
|
||||
|
||||
Set the delimiter
|
||||
Set the delimiter which separates fields in the file using the
|
||||
--delimiter (-d) option. Setting the delimiter is optional.
|
||||
If not set, a default delimiter of Tab will be used.
|
||||
|
||||
Optionally Filter based on delimiter
|
||||
If the --only-delimited (-s) flag is provided, only lines which
|
||||
contain the delimiter will be printed
|
||||
|
||||
Replace the delimiter
|
||||
If the --output-delimiter option is provided, the argument used for
|
||||
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)
|
||||
|
||||
Line endings
|
||||
|
||||
When the --zero-terminated (-z) option is used, cut sees \\0 (null) as the
|
||||
'line ending' character (both for the purposes of reading lines and
|
||||
separating printed lines) instead of \\n (newline). This is useful for
|
||||
tabular data where some of the cells may contain newlines
|
||||
|
||||
echo 'ab\\0cd' | cut -z -c 1
|
||||
will result in 'a\\0c\\0'
|
||||
";
|
||||
|
||||
struct Options {
|
||||
out_delim: Option<String>,
|
||||
|
@ -408,8 +487,7 @@ fn cut_files(mut filenames: Vec<String>, mode: Mode) -> i32 {
|
|||
}
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = uucore::coreopts::CoreOptions::new(NAME);
|
||||
|
||||
let mut opts = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP);
|
||||
opts.optopt("b", "bytes", "filter byte columns from the input source", "sequence");
|
||||
opts.optopt("c", "characters", "alias for character mode", "sequence");
|
||||
opts.optopt("d", "delimiter", "specify the delimiter character that separates fields in the input source. Defaults to Tab.", "delimiter");
|
||||
|
@ -419,95 +497,6 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
opts.optflag("s", "only-delimited", "in field mode, only print lines which contain the delimiter");
|
||||
opts.optflag("z", "zero-terminated", "instead of filtering columns based on line, filter columns based on \\0 (NULL character)");
|
||||
opts.optopt("", "output-delimiter", "in field mode, replace the delimiter in output lines with this option's argument", "new delimiter");
|
||||
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}}+
|
||||
|
||||
{2}
|
||||
|
||||
Reference
|
||||
|
||||
Each call must specify a mode (what to use for columns),
|
||||
a sequence (which columns to print), and provide a data source
|
||||
|
||||
Specifying a mode
|
||||
|
||||
Use --bytes (-b) or --characters (-c) to specify byte mode
|
||||
|
||||
Use --fields (-f) to specify field mode, where each line is broken into
|
||||
fields identified by a delimiter character. For example for a typical CSV
|
||||
you could use this in combination with setting comma as the delimiter
|
||||
|
||||
Specifying a sequence
|
||||
|
||||
A sequence is a group of 1 or more numbers or inclusive ranges separated
|
||||
by a commas.
|
||||
|
||||
cut -f 2,5-7 some_file.txt
|
||||
will display the 2nd, 5th, 6th, and 7th field for each source line
|
||||
|
||||
Ranges can extend to the end of the row by excluding the the second number
|
||||
|
||||
cut -f 3- some_file.txt
|
||||
will display the 3rd field and all fields after for each source line
|
||||
|
||||
The first number of a range can be excluded, and this is effectively the
|
||||
same as using 1 as the first number: it causes the range to begin at the
|
||||
first column. Ranges can also display a single column
|
||||
|
||||
cut -f 1,3-5 some_file.txt
|
||||
will display the 1st, 3rd, 4th, and 5th field for each source line
|
||||
|
||||
The --complement option, when used, inverts the effect of the sequence
|
||||
|
||||
cut --complement -f 4-6 some_file.txt
|
||||
will display the every field but the 4th, 5th, and 6th
|
||||
|
||||
Specifying a data source
|
||||
|
||||
If no sourcefile arguments are specified, stdin is used as the source of
|
||||
lines to print
|
||||
|
||||
If sourcefile arguments are specified, stdin is ignored and all files are
|
||||
read in consecutively if a sourcefile is not successfully read, a warning
|
||||
will print to stderr, and the eventual status code will be 1, but cut
|
||||
will continue to read through proceeding sourcefiles
|
||||
|
||||
To print columns from both STDIN and a file argument, use - (dash) as a
|
||||
sourcefile argument to represent stdin.
|
||||
|
||||
Field Mode options
|
||||
|
||||
The fields in each line are identified by a delimiter (separator)
|
||||
|
||||
Set the delimiter
|
||||
Set the delimiter which separates fields in the file using the
|
||||
--delimiter (-d) option. Setting the delimiter is optional.
|
||||
If not set, a default delimiter of Tab will be used.
|
||||
|
||||
Optionally Filter based on delimiter
|
||||
If the --only-delimited (-s) flag is provided, only lines which
|
||||
contain the delimiter will be printed
|
||||
|
||||
Replace the delimiter
|
||||
If the --output-delimiter option is provided, the argument used for
|
||||
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)
|
||||
|
||||
Line endings
|
||||
|
||||
When the --zero-terminated (-z) option is used, cut sees \\0 (null) as the
|
||||
'line ending' character (both for the purposes of reading lines and
|
||||
separating printed lines) instead of \\n (newline). This is useful for
|
||||
tabular data where some of the cells may contain newlines
|
||||
|
||||
echo 'ab\\0cd' | cut -z -c 1
|
||||
will result in 'a\\0c\\0'
|
||||
|
||||
", NAME, VERSION, usage));
|
||||
let matches = opts.parse(args);
|
||||
|
||||
let complement = matches.opt_present("complement");
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
extern crate uucore;
|
||||
use uucore::c_types::getpwnam;
|
||||
use uucore::utmpx::{self, time, Utmpx};
|
||||
use uucore::coreopts;
|
||||
use uucore::libc::{uid_t, gid_t, c_char, S_IWGRP};
|
||||
|
||||
use std::io::prelude::*;
|
||||
|
@ -29,12 +28,28 @@ use std::ffi::{CStr, CString};
|
|||
|
||||
use std::path::PathBuf;
|
||||
|
||||
static NAME: &'static str = "pinky";
|
||||
|
||||
static SYNTAX: &'static str = "[OPTION]... [USER]...";
|
||||
static SUMMARY: &'static str = "A lightweight 'finger' program; print user information.";
|
||||
|
||||
const BUFSIZE: usize = 1024;
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
let mut opts = coreopts::CoreOptions::new(NAME);
|
||||
let long_help = &format!("
|
||||
-l produce long format output for the specified USERs
|
||||
-b omit the user's home directory and shell in long format
|
||||
-h omit the user's project file in long format
|
||||
-p omit the user's plan file in long format
|
||||
-s do short format output, this is the default
|
||||
-f omit the line of column headings in short format
|
||||
-w omit the user's full name in short format
|
||||
-i omit the user's full name and remote host in short format
|
||||
-q omit the user's full name, remote host and idle time
|
||||
in short format
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
The utmp file will be {}", utmpx::DEFAULT_FILE);
|
||||
let mut opts = new_coreopts!(SYNTAX, SUMMARY, &long_help);
|
||||
opts.optflag("l",
|
||||
"l",
|
||||
"produce long format output for the specified USERs");
|
||||
|
@ -55,27 +70,6 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
opts.optflag("", "help", "display this help and exit");
|
||||
opts.optflag("", "version", "output version information and exit");
|
||||
|
||||
opts.help(format!(
|
||||
"Usage: {} [OPTION]... [USER]...
|
||||
|
||||
-l produce long format output for the specified USERs
|
||||
-b omit the user's home directory and shell in long format
|
||||
-h omit the user's project file in long format
|
||||
-p omit the user's plan file in long format
|
||||
-s do short format output, this is the default
|
||||
-f omit the line of column headings in short format
|
||||
-w omit the user's full name in short format
|
||||
-i omit the user's full name and remote host in short format
|
||||
-q omit the user's full name, remote host and idle time
|
||||
in short format
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
A lightweight 'finger' program; print user information.
|
||||
The utmp file will be {}",
|
||||
NAME,
|
||||
utmpx::DEFAULT_FILE));
|
||||
|
||||
let matches = opts.parse(args);
|
||||
|
||||
// If true, display the hours:minutes since each user has touched
|
||||
|
|
|
@ -1,36 +1,39 @@
|
|||
extern crate getopts;
|
||||
use std::io::Write;
|
||||
|
||||
pub struct CoreOptions {
|
||||
pub options : getopts::Options,
|
||||
pkgname: &'static str,
|
||||
longhelp : Option<String>
|
||||
pub struct HelpText<'a> {
|
||||
pub name : &'a str,
|
||||
pub version : &'a str,
|
||||
pub syntax : &'a str,
|
||||
pub summary : &'a str,
|
||||
pub long_help : &'a str,
|
||||
pub display_usage : bool
|
||||
}
|
||||
|
||||
impl<'a> CoreOptions {
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
pub struct CoreOptions<'a> {
|
||||
options : getopts::Options,
|
||||
help_text : HelpText<'a>
|
||||
}
|
||||
|
||||
impl<'a> CoreOptions<'a> {
|
||||
pub fn new(help_text: HelpText<'a>) -> Self {
|
||||
let mut ret = CoreOptions {
|
||||
options : getopts::Options::new(),
|
||||
pkgname: name,
|
||||
longhelp: None
|
||||
help_text : help_text
|
||||
};
|
||||
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 {
|
||||
pub fn optopt(&mut self, short_name: &str, long_name: &str, desc: &str, hint: &str) -> &mut CoreOptions<'a> {
|
||||
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 {
|
||||
pub fn optflag(&mut self, short_name: &str, long_name: &str, desc: &str) -> &mut CoreOptions<'a> {
|
||||
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)
|
||||
}
|
||||
|
@ -38,20 +41,50 @@ impl<'a> CoreOptions {
|
|||
let matches = match self.options.parse(&args[1..]) {
|
||||
Ok(m) => { Some(m) },
|
||||
Err(f) => {
|
||||
eprintln!("{}: {}", self.pkgname, f);
|
||||
eprintln!("Try '{} --help' for more information.", self.pkgname);
|
||||
exit!(1)
|
||||
crash!(1, "{}", f);
|
||||
}
|
||||
}.unwrap();
|
||||
if matches.opt_present("help") {
|
||||
exit!(match self.longhelp {
|
||||
Some(ref lhelp) => { println!("{}", lhelp); 0}
|
||||
None => 1
|
||||
});
|
||||
if matches.opt_present("help") {
|
||||
let usage_str = if self.help_text.display_usage {
|
||||
format!("\n {}\n\n Reference\n",
|
||||
self.options.usage(self.help_text.summary)
|
||||
).replace("Options:", " Options:")
|
||||
} else { String::new() };
|
||||
print!("
|
||||
{0} {1}
|
||||
|
||||
{0} {2}
|
||||
{3}{4}
|
||||
", self.help_text.name, self.help_text.version, self.help_text.syntax, usage_str, self.help_text.long_help);
|
||||
exit!(0);
|
||||
} else if matches.opt_present("version") {
|
||||
println!("{} {}", self.pkgname, env!("CARGO_PKG_VERSION"));
|
||||
println!("{} {}", self.help_text.name, self.help_text.version);
|
||||
exit!(0);
|
||||
}
|
||||
matches
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! new_coreopts {
|
||||
($syntax: expr, $summary: expr, $long_help: expr) => (
|
||||
uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
|
||||
name: executable!(),
|
||||
version: env!("CARGO_PKG_VERSION"),
|
||||
syntax: $syntax,
|
||||
summary: $summary,
|
||||
long_help: $long_help,
|
||||
display_usage: true
|
||||
})
|
||||
);
|
||||
($syntax: expr, $summary: expr, $long_help: expr, $display_usage: expr) => (
|
||||
uucore::coreopts::CoreOptions::new(uucore::coreopts::HelpText {
|
||||
name: executable!(),
|
||||
version: env!("CARGO_PKG_VERSION"),
|
||||
syntax: $syntax,
|
||||
summary: $summary,
|
||||
long_help: $long_help,
|
||||
display_usage: $display_usage
|
||||
})
|
||||
);
|
||||
}
|
|
@ -3,6 +3,7 @@ pub extern crate libc;
|
|||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
pub mod coreopts;
|
||||
|
||||
#[cfg(feature = "fs")]
|
||||
|
|
|
@ -264,15 +264,6 @@ macro_rules! snippet_list_join_or {
|
|||
);
|
||||
}
|
||||
|
||||
//-- message templates : help and version
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! msg_version {
|
||||
() => (
|
||||
format!("{} {}", executable!(), env!("CARGO_PKG_VERSION"))
|
||||
)
|
||||
}
|
||||
|
||||
//-- message templates : invalid input
|
||||
|
||||
#[macro_export]
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
use uucore::utmpx::{self, time, Utmpx};
|
||||
use uucore::coreopts;
|
||||
use uucore::libc::{STDIN_FILENO, time_t, ttyname, S_IWGRP};
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
@ -21,11 +20,35 @@ use std::ffi::CStr;
|
|||
use std::path::PathBuf;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
static NAME: &'static str = "who";
|
||||
static SYNTAX: &'static str = "[OPTION]... [ FILE | ARG1 ARG2 ]";
|
||||
static SUMMARY: &'static str = "Print information about users who are currently logged in.";
|
||||
static LONG_HELP: &'static str = "
|
||||
-a, --all same as -b -d --login -p -r -t -T -u
|
||||
-b, --boot time of last system boot
|
||||
-d, --dead print dead processes
|
||||
-H, --heading print line of column headings
|
||||
-l, --login print system login processes
|
||||
--lookup attempt to canonicalize hostnames via DNS
|
||||
-m only hostname and user associated with stdin
|
||||
-p, --process print active processes spawned by init
|
||||
-q, --count all login names and number of users logged on
|
||||
-r, --runlevel print current runlevel
|
||||
-s, --short print only name, line, and time (default)
|
||||
-t, --time print last system clock change
|
||||
-T, -w, --mesg add user's message status as +, - or ?
|
||||
-u, --users list users logged in
|
||||
--message same as -T
|
||||
--writable same as -T
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common.
|
||||
If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.
|
||||
";
|
||||
|
||||
pub fn uumain(args: Vec<String>) -> i32 {
|
||||
|
||||
let mut opts = coreopts::CoreOptions::new(NAME);
|
||||
let mut opts = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP);
|
||||
opts.optflag("a", "all", "same as -b -d --login -p -r -t -T -u");
|
||||
opts.optflag("b", "boot", "time of last system boot");
|
||||
opts.optflag("d", "dead", "print dead processes");
|
||||
|
@ -49,32 +72,6 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
|||
opts.optflag("", "help", "display this help and exit");
|
||||
opts.optflag("", "version", "output version information and exit");
|
||||
|
||||
opts.help(format!("Usage: {} [OPTION]... [ FILE | ARG1 ARG2 ]
|
||||
Print information about users who are currently logged in.
|
||||
|
||||
-a, --all same as -b -d --login -p -r -t -T -u
|
||||
-b, --boot time of last system boot
|
||||
-d, --dead print dead processes
|
||||
-H, --heading print line of column headings
|
||||
-l, --login print system login processes
|
||||
--lookup attempt to canonicalize hostnames via DNS
|
||||
-m only hostname and user associated with stdin
|
||||
-p, --process print active processes spawned by init
|
||||
-q, --count all login names and number of users logged on
|
||||
-r, --runlevel print current runlevel
|
||||
-s, --short print only name, line, and time (default)
|
||||
-t, --time print last system clock change
|
||||
-T, -w, --mesg add user's message status as +, - or ?
|
||||
-u, --users list users logged in
|
||||
--message same as -T
|
||||
--writable same as -T
|
||||
--help display this help and exit
|
||||
--version output version information and exit
|
||||
|
||||
If FILE is not specified, use /var/run/utmp. /var/log/wtmp as FILE is common.
|
||||
If ARG1 ARG2 given, -m presumed: 'am i' or 'mom likes' are usual.",
|
||||
NAME));
|
||||
|
||||
let matches = opts.parse(args);
|
||||
|
||||
// If true, attempt to canonicalize hostnames via a DNS lookup.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue