mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
parent
acb57ecbd0
commit
ab5b6dd844
3 changed files with 62 additions and 47 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -1325,9 +1325,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.65"
|
version = "1.0.67"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
|
checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
|
@ -2334,8 +2334,8 @@ name = "uu_tr"
|
||||||
version = "0.0.4"
|
version = "0.0.4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-set",
|
"bit-set",
|
||||||
|
"clap",
|
||||||
"fnv",
|
"fnv",
|
||||||
"getopts",
|
|
||||||
"uucore",
|
"uucore",
|
||||||
"uucore_procs",
|
"uucore_procs",
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,7 +17,7 @@ path = "src/tr.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bit-set = "0.5.0"
|
bit-set = "0.5.0"
|
||||||
fnv = "1.0.5"
|
fnv = "1.0.5"
|
||||||
getopts = "0.2.18"
|
clap = "2.33"
|
||||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,27 @@ extern crate uucore;
|
||||||
mod expand;
|
mod expand;
|
||||||
|
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
|
use clap::{App, Arg};
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use getopts::Options;
|
|
||||||
use std::io::{stdin, stdout, BufRead, BufWriter, Write};
|
use std::io::{stdin, stdout, BufRead, BufWriter, Write};
|
||||||
|
|
||||||
use crate::expand::ExpandSet;
|
use crate::expand::ExpandSet;
|
||||||
|
|
||||||
static NAME: &str = "tr";
|
static NAME: &str = "tr";
|
||||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
static ABOUT: &str = "translate or delete characters";
|
||||||
|
static LONG_HELP: &str = "Translate, squeeze, and/or delete characters from standard input,
|
||||||
|
writing to standard output.";
|
||||||
const BUFFER_LEN: usize = 1024;
|
const BUFFER_LEN: usize = 1024;
|
||||||
|
|
||||||
|
mod options {
|
||||||
|
pub const COMPLEMENT: &str = "complement";
|
||||||
|
pub const DELETE: &str = "delete";
|
||||||
|
pub const SQUEEZE: &str = "squeeze-repeats";
|
||||||
|
pub const TRUNCATE: &str = "truncate";
|
||||||
|
pub const SETS: &str = "sets";
|
||||||
|
}
|
||||||
|
|
||||||
trait SymbolTranslator {
|
trait SymbolTranslator {
|
||||||
fn translate(&self, c: char, prev_c: char) -> Option<char>;
|
fn translate(&self, c: char, prev_c: char) -> Option<char>;
|
||||||
}
|
}
|
||||||
|
@ -170,56 +181,60 @@ fn translate_input<T: SymbolTranslator>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(opts: &Options) {
|
fn get_usage() -> String {
|
||||||
println!("{} {}", NAME, VERSION);
|
format!("{} [OPTION]... SET1 [SET2]", executable!())
|
||||||
println!();
|
|
||||||
println!("Usage:");
|
|
||||||
println!(" {} [OPTIONS] SET1 [SET2]", NAME);
|
|
||||||
println!();
|
|
||||||
println!("{}", opts.usage("Translate or delete characters."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uumain(args: impl uucore::Args) -> i32 {
|
pub fn uumain(args: impl uucore::Args) -> i32 {
|
||||||
let args = args.collect_str();
|
let usage = get_usage();
|
||||||
|
|
||||||
let mut opts = Options::new();
|
let matches = App::new(executable!())
|
||||||
|
.version(VERSION)
|
||||||
|
.about(ABOUT)
|
||||||
|
.usage(&usage[..])
|
||||||
|
.after_help(LONG_HELP)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::COMPLEMENT)
|
||||||
|
.short("C")
|
||||||
|
.short("c")
|
||||||
|
.long(options::COMPLEMENT)
|
||||||
|
.help("use the complement of SET1"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::DELETE)
|
||||||
|
.short("d")
|
||||||
|
.long(options::DELETE)
|
||||||
|
.help("delete characters in SET1, do not translate"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::SQUEEZE)
|
||||||
|
.long(options::SQUEEZE)
|
||||||
|
.short("s")
|
||||||
|
.help(
|
||||||
|
"replace each sequence of a repeated character that is
|
||||||
|
listed in the last specified SET, with a single occurrence
|
||||||
|
of that character",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(options::TRUNCATE)
|
||||||
|
.long(options::TRUNCATE)
|
||||||
|
.short("t")
|
||||||
|
.help("first truncate SET1 to length of SET2"),
|
||||||
|
)
|
||||||
|
.arg(Arg::with_name(options::SETS).multiple(true))
|
||||||
|
.get_matches_from(args);
|
||||||
|
|
||||||
opts.optflag("c", "complement", "use the complement of SET1");
|
let dflag = matches.is_present(options::DELETE);
|
||||||
opts.optflag("C", "", "same as -c");
|
let cflag = matches.is_present(options::COMPLEMENT);
|
||||||
opts.optflag("d", "delete", "delete characters in SET1");
|
let sflag = matches.is_present(options::SQUEEZE);
|
||||||
opts.optflag("h", "help", "display this help and exit");
|
let tflag = matches.is_present(options::TRUNCATE);
|
||||||
opts.optflag("s", "squeeze", "replace each sequence of a repeated character that is listed in the last specified SET, with a single occurrence of that character");
|
|
||||||
opts.optflag(
|
|
||||||
"t",
|
|
||||||
"truncate-set1",
|
|
||||||
"first truncate SET1 to length of SET2",
|
|
||||||
);
|
|
||||||
opts.optflag("V", "version", "output version information and exit");
|
|
||||||
|
|
||||||
let matches = match opts.parse(&args[1..]) {
|
let sets: Vec<String> = match matches.values_of(options::SETS) {
|
||||||
Ok(m) => m,
|
Some(v) => v.map(|v| v.to_string()).collect(),
|
||||||
Err(err) => {
|
None => vec![],
|
||||||
show_error!("{}", err);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if matches.opt_present("help") {
|
|
||||||
usage(&opts);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if matches.opt_present("version") {
|
|
||||||
println!("{} {}", NAME, VERSION);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dflag = matches.opt_present("d");
|
|
||||||
let cflag = matches.opts_present(&["c".to_owned(), "C".to_owned()]);
|
|
||||||
let sflag = matches.opt_present("s");
|
|
||||||
let tflag = matches.opt_present("t");
|
|
||||||
let sets = matches.free;
|
|
||||||
|
|
||||||
if sets.is_empty() {
|
if sets.is_empty() {
|
||||||
show_error!(
|
show_error!(
|
||||||
"missing operand\nTry `{} --help` for more information.",
|
"missing operand\nTry `{} --help` for more information.",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue