Implement rev
(#56)
* Implement `rev` * Use uucore facility for error reporting
This commit is contained in:
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -644,6 +644,7 @@ dependencies = [
|
|||||||
"uu_ctrlaltdel",
|
"uu_ctrlaltdel",
|
||||||
"uu_lscpu",
|
"uu_lscpu",
|
||||||
"uu_mountpoint",
|
"uu_mountpoint",
|
||||||
|
"uu_rev",
|
||||||
"uucore",
|
"uucore",
|
||||||
"xattr",
|
"xattr",
|
||||||
]
|
]
|
||||||
@@ -674,6 +675,14 @@ dependencies = [
|
|||||||
"uucore",
|
"uucore",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uu_rev"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"uucore",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uucore"
|
name = "uucore"
|
||||||
version = "0.0.27"
|
version = "0.0.27"
|
||||||
|
@@ -28,6 +28,7 @@ feat_common_core = [
|
|||||||
"mountpoint",
|
"mountpoint",
|
||||||
"lscpu",
|
"lscpu",
|
||||||
"ctrlaltdel",
|
"ctrlaltdel",
|
||||||
|
"rev",
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
@@ -58,6 +59,7 @@ textwrap = { workspace = true }
|
|||||||
lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" }
|
lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" }
|
||||||
mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" }
|
mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" }
|
||||||
ctrlaltdel = { optional = true, version = "0.0.1", package = "uu_ctrlaltdel", path = "src/uu/ctrlaltdel" }
|
ctrlaltdel = { optional = true, version = "0.0.1", package = "uu_ctrlaltdel", path = "src/uu/ctrlaltdel" }
|
||||||
|
rev = { optional = true, version = "0.0.1", package = "uu_rev", path = "src/uu/rev" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "1"
|
pretty_assertions = "1"
|
||||||
|
17
src/uu/rev/Cargo.toml
Normal file
17
src/uu/rev/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "uu_rev"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
uucore = { workspace = true }
|
||||||
|
clap = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "src/rev.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "rev"
|
||||||
|
path = "src/main.rs"
|
7
src/uu/rev/rev.md
Normal file
7
src/uu/rev/rev.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# rev
|
||||||
|
|
||||||
|
```
|
||||||
|
rev [options] [file ...]
|
||||||
|
```
|
||||||
|
|
||||||
|
Reverse lines characterwise.
|
1
src/uu/rev/src/main.rs
Normal file
1
src/uu/rev/src/main.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uucore::bin!(uu_rev);
|
81
src/uu/rev/src/rev.rs
Normal file
81
src/uu/rev/src/rev.rs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// This file is part of the uutils util-linux package.
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE
|
||||||
|
// file that was distributed with this source code.
|
||||||
|
|
||||||
|
use clap::{crate_version, Command};
|
||||||
|
use clap::{Arg, ArgAction};
|
||||||
|
use std::env;
|
||||||
|
use std::io::{BufRead, BufReader, Read, Write};
|
||||||
|
use uucore::{error::UResult, format_usage, help_about, help_usage};
|
||||||
|
|
||||||
|
const ABOUT: &str = help_about!("rev.md");
|
||||||
|
const USAGE: &str = help_usage!("rev.md");
|
||||||
|
|
||||||
|
#[uucore::main]
|
||||||
|
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
||||||
|
let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
|
||||||
|
let files = matches.get_many::<String>("file");
|
||||||
|
|
||||||
|
match files {
|
||||||
|
Some(files) => {
|
||||||
|
for path in files {
|
||||||
|
let file = match std::fs::File::open(path) {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => {
|
||||||
|
uucore::error::set_exit_code(1);
|
||||||
|
uucore::show_error!("cannot open {}: {}", path, err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Err(err) = rev_stream(file) {
|
||||||
|
uucore::error::set_exit_code(1);
|
||||||
|
uucore::show_error!("cannot read {}: {}", path, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let stdin = std::io::stdin().lock();
|
||||||
|
let _ = rev_stream(stdin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rev_stream(stream: impl Read) -> std::io::Result<()> {
|
||||||
|
let mut stdout = std::io::stdout().lock();
|
||||||
|
let mut stream = BufReader::new(stream);
|
||||||
|
let mut buf = Vec::with_capacity(4096);
|
||||||
|
loop {
|
||||||
|
buf.clear();
|
||||||
|
stream.read_until(b'\n', &mut buf)?;
|
||||||
|
if buf.last().copied() != Some(b'\n') {
|
||||||
|
buf.reverse();
|
||||||
|
stdout.write_all(&buf)?;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
buf.pop();
|
||||||
|
buf.reverse();
|
||||||
|
buf.push(b'\n');
|
||||||
|
stdout.write_all(&buf)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn uu_app() -> Command {
|
||||||
|
Command::new(uucore::util_name())
|
||||||
|
.version(crate_version!())
|
||||||
|
.about(ABOUT)
|
||||||
|
.override_usage(format_usage(USAGE))
|
||||||
|
.infer_long_args(true)
|
||||||
|
.arg(
|
||||||
|
Arg::new("file")
|
||||||
|
.value_name("FILE")
|
||||||
|
.help("Paths of files to reverse")
|
||||||
|
.index(1)
|
||||||
|
.action(ArgAction::Set)
|
||||||
|
.num_args(1..),
|
||||||
|
)
|
||||||
|
}
|
12
tests/by-util/test_rev.rs
Normal file
12
tests/by-util/test_rev.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// This file is part of the uutils util-linux package.
|
||||||
|
//
|
||||||
|
// For the full copyright and license information, please view the LICENSE
|
||||||
|
// file that was distributed with this source code.
|
||||||
|
// spell-checker:ignore (words) symdir somefakedir
|
||||||
|
|
||||||
|
use crate::common::util::TestScenario;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_arg() {
|
||||||
|
new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
|
||||||
|
}
|
@@ -16,3 +16,7 @@ mod test_mountpoint;
|
|||||||
#[cfg(feature = "ctrlaltdel")]
|
#[cfg(feature = "ctrlaltdel")]
|
||||||
#[path = "by-util/test_ctrlaltdel.rs"]
|
#[path = "by-util/test_ctrlaltdel.rs"]
|
||||||
mod test_ctrlaltdel;
|
mod test_ctrlaltdel;
|
||||||
|
|
||||||
|
#[cfg(feature = "rev")]
|
||||||
|
#[path = "by-util/test_rev.rs"]
|
||||||
|
mod test_rev;
|
||||||
|
Reference in New Issue
Block a user