1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

tee: move from getopts to clap (#1814)

This commit is contained in:
Jan Scheer 2021-03-19 22:58:50 +01:00 committed by GitHub
parent e76ce1e908
commit 0e217e202a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 70 deletions

View file

@ -15,7 +15,7 @@ edition = "2018"
path = "src/tee.rs"
[dependencies]
getopts = "0.2.18"
clap = "2.33.3"
libc = "0.2.42"
uucore = { version=">=0.0.7", package="uucore", path="../../uucore", features=["libc"] }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }

View file

@ -5,6 +5,10 @@
// * For the full copyright and license information, please view the LICENSE
// * file that was distributed with this source code.
#[macro_use]
extern crate uucore;
use clap::{App, Arg};
use std::fs::OpenOptions;
use std::io::{copy, sink, stdin, stdout, Error, ErrorKind, Read, Result, Write};
use std::path::{Path, PathBuf};
@ -12,80 +16,61 @@ use std::path::{Path, PathBuf};
#[cfg(unix)]
use uucore::libc;
static NAME: &str = "tee";
static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Copy standard input to each FILE, and also to standard output.";
pub fn uumain(args: impl uucore::Args) -> i32 {
let args = args.collect_str();
match options(&args).and_then(exec) {
Ok(_) => 0,
Err(_) => 1,
}
mod options {
pub const APPEND: &str = "append";
pub const IGNORE_INTERRUPTS: &str = "ignore-interrupts";
pub const FILE: &str = "file";
}
#[allow(dead_code)]
struct Options {
program: String,
append: bool,
ignore_interrupts: bool,
print_and_exit: Option<String>,
files: Vec<String>,
}
fn options(args: &[String]) -> Result<Options> {
let mut opts = getopts::Options::new();
opts.optflag("a", "append", "append to the given FILEs, do not overwrite");
opts.optflag(
"i",
"ignore-interrupts",
"ignore interrupt signals (ignored on non-Unix platforms)",
);
opts.optflag("h", "help", "display this help and exit");
opts.optflag("V", "version", "output version information and exit");
opts.parse(&args[1..])
.map_err(|e| Error::new(ErrorKind::Other, format!("{}", e)))
.map(|m| {
let version = format!("{} {}", NAME, VERSION);
let arguments = "[OPTION]... [FILE]...";
let brief = "Copy standard input to each FILE, and also to standard output.";
let comment = "If a FILE is -, it refers to a file named - .";
let help = format!(
"{}\n\nUsage:\n {} {}\n\n{}\n{}",
version,
NAME,
arguments,
opts.usage(brief),
comment
);
let names: Vec<String> = m.free.clone().into_iter().collect();
let to_print = if m.opt_present("help") {
Some(help)
} else if m.opt_present("version") {
Some(version)
} else {
None
};
Options {
program: NAME.to_owned(),
append: m.opt_present("append"),
ignore_interrupts: m.opt_present("ignore-interrupts"),
print_and_exit: to_print,
files: names,
}
})
.map_err(|message| warn(format!("{}", message).as_ref()))
fn get_usage() -> String {
format!("{0} [OPTION]... [FILE]...", executable!())
}
fn exec(options: Options) -> Result<()> {
match options.print_and_exit {
Some(text) => {
println!("{}", text);
Ok(())
}
None => tee(options),
pub fn uumain(args: impl uucore::Args) -> i32 {
let usage = get_usage();
let matches = App::new(executable!())
.version(VERSION)
.about(ABOUT)
.usage(&usage[..])
.after_help("If a FILE is -, it refers to a file named - .")
.arg(
Arg::with_name(options::APPEND)
.long(options::APPEND)
.short("a")
.help("append to the given FILEs, do not overwrite"),
)
.arg(
Arg::with_name(options::IGNORE_INTERRUPTS)
.long(options::IGNORE_INTERRUPTS)
.short("i")
.help("ignore interrupt signals (ignored on non-Unix platforms)"),
)
.arg(Arg::with_name(options::FILE).multiple(true))
.get_matches_from(args);
let options = Options {
append: matches.is_present(options::APPEND),
ignore_interrupts: matches.is_present(options::IGNORE_INTERRUPTS),
files: matches
.values_of(options::FILE)
.map(|v| v.map(ToString::to_string).collect())
.unwrap_or_default(),
};
match tee(options) {
Ok(_) => 0,
Err(_) => 1,
}
}
@ -173,7 +158,7 @@ impl Write for NamedWriter {
match self.inner.write(buf) {
Err(f) => {
self.inner = Box::new(sink()) as Box<dyn Write>;
warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
show_warning!("{}: {}", self.path.display(), f.to_string());
Err(f)
}
okay => okay,
@ -184,7 +169,7 @@ impl Write for NamedWriter {
match self.inner.flush() {
Err(f) => {
self.inner = Box::new(sink()) as Box<dyn Write>;
warn(format!("{}: {}", self.path.display(), f.to_string()).as_ref());
show_warning!("{}: {}", self.path.display(), f.to_string());
Err(f)
}
okay => okay,
@ -200,15 +185,10 @@ impl Read for NamedReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
match self.inner.read(buf) {
Err(f) => {
warn(format!("{}: {}", Path::new("stdin").display(), f.to_string()).as_ref());
show_warning!("{}: {}", Path::new("stdin").display(), f.to_string());
Err(f)
}
okay => okay,
}
}
}
fn warn(message: &str) -> Error {
eprintln!("{}: {}", NAME, message);
Error::new(ErrorKind::Other, format!("{}: {}", NAME, message))
}