Skip to content

Commit c3fe5bc

Browse files
committed
feat(more): parse extra args
1 parent fb6a2bb commit c3fe5bc

File tree

3 files changed

+163
-13
lines changed

3 files changed

+163
-13
lines changed

src/uu/more/src/more.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use uucore::{display::Quotable, show};
2929

3030
use uucore::translate;
3131

32+
mod parse;
33+
3234
#[derive(Debug)]
3335
enum MoreError {
3436
IsDirectory(PathBuf),
@@ -152,6 +154,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
152154
print!("\r");
153155
println!("{panic_info}");
154156
}));
157+
let args = parse::preprocess_args(args);
155158
let matches = uucore::clap_localization::handle_clap_result(uu_app(), args)?;
156159
let mut options = Options::from(&matches);
157160
if let Some(files) = matches.get_many::<OsString>(options::FILES) {

src/uu/more/src/parse.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// This file is part of the uutils coreutils package.
2+
//
3+
// For the full copyright and license information, please view the LICENSE
4+
// file that was distributed with this source code.
5+
6+
use std::ffi::OsString;
7+
8+
#[derive(Debug, PartialEq, Eq)]
9+
pub enum ExtraArg {
10+
/// `-number` (also available as `--lines`)
11+
Lines(u16),
12+
/// `+number` (also available as `--from-line`)
13+
FromLine(usize),
14+
/// `+/string` (also available as `--pattern`)
15+
Pattern(String),
16+
}
17+
18+
pub fn parse_extra_arg(src: &str) -> Option<ExtraArg> {
19+
if let Some(rest) = src.strip_prefix("+/") {
20+
if !rest.is_empty() {
21+
return Some(ExtraArg::Pattern(rest.to_string()));
22+
}
23+
} else if let Some(rest) = src.strip_prefix('+') {
24+
if let Ok(n) = rest.parse::<usize>() {
25+
return Some(ExtraArg::FromLine(n));
26+
}
27+
} else if let Some(rest) = src.strip_prefix('-') {
28+
if let Ok(n) = rest.parse::<u16>() {
29+
return Some(ExtraArg::Lines(n));
30+
}
31+
}
32+
None
33+
}
34+
35+
fn expand_extra_arg(result: &mut Vec<OsString>, arg: ExtraArg) {
36+
match arg {
37+
ExtraArg::Lines(n) => {
38+
result.push("--lines".into());
39+
result.push(n.to_string().into());
40+
}
41+
ExtraArg::FromLine(n) => {
42+
result.push("--from-line".into());
43+
result.push(n.to_string().into());
44+
}
45+
ExtraArg::Pattern(p) => {
46+
result.push("--pattern".into());
47+
result.push(p.into());
48+
}
49+
}
50+
}
51+
52+
pub fn preprocess_args(args: impl Iterator<Item = OsString>) -> Vec<OsString> {
53+
let mut result = Vec::new();
54+
for (i, arg) in args.enumerate() {
55+
if let Some(extra) = arg.to_str().and_then(parse_extra_arg) {
56+
if i == 0 {
57+
result.push(uucore::util_name().into());
58+
}
59+
expand_extra_arg(&mut result, extra);
60+
} else {
61+
result.push(arg);
62+
}
63+
}
64+
result
65+
}
66+
67+
#[cfg(test)]
68+
mod tests {
69+
use super::*;
70+
71+
#[test]
72+
fn test_parse_minus_number() {
73+
assert_eq!(parse_extra_arg("-10"), Some(ExtraArg::Lines(10)));
74+
assert_eq!(parse_extra_arg("-1"), Some(ExtraArg::Lines(1)));
75+
assert_eq!(parse_extra_arg("-abc"), None);
76+
assert_eq!(parse_extra_arg("-"), None);
77+
}
78+
79+
#[test]
80+
fn test_parse_plus_number() {
81+
assert_eq!(parse_extra_arg("+5"), Some(ExtraArg::FromLine(5)));
82+
assert_eq!(parse_extra_arg("+100"), Some(ExtraArg::FromLine(100)));
83+
assert_eq!(parse_extra_arg("+abc"), None);
84+
}
85+
86+
#[test]
87+
fn test_parse_plus_pattern() {
88+
assert_eq!(
89+
parse_extra_arg("+/foo"),
90+
Some(ExtraArg::Pattern("foo".into()))
91+
);
92+
assert_eq!(
93+
parse_extra_arg("+/hello world"),
94+
Some(ExtraArg::Pattern("hello world".into()))
95+
);
96+
assert_eq!(parse_extra_arg("+/"), None);
97+
}
98+
99+
#[test]
100+
fn test_preprocess_args() {
101+
// Test -number
102+
let args = ["more", "-5"];
103+
let result = preprocess_args(args.iter().map(OsString::from));
104+
assert_eq!(
105+
result,
106+
vec![
107+
OsString::from("more"),
108+
OsString::from("--lines"),
109+
OsString::from("5")
110+
]
111+
);
112+
113+
// Test +number
114+
let args = ["more", "+10"];
115+
let result = preprocess_args(args.iter().map(OsString::from));
116+
assert_eq!(
117+
result,
118+
vec![
119+
OsString::from("more"),
120+
OsString::from("--from-line"),
121+
OsString::from("10")
122+
]
123+
);
124+
125+
// Test +/pattern
126+
let args = ["more", "+/hello"];
127+
let result = preprocess_args(args.iter().map(OsString::from));
128+
assert_eq!(
129+
result,
130+
vec![
131+
OsString::from("more"),
132+
OsString::from("--pattern"),
133+
OsString::from("hello")
134+
]
135+
);
136+
137+
// Test regular args unchanged
138+
let args = ["more", "file.txt"];
139+
let result = preprocess_args(args.iter().map(OsString::from));
140+
assert_eq!(result, args.iter().map(OsString::from).collect::<Vec<_>>());
141+
}
142+
}

tests/by-util/test_more.rs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,29 @@ fn test_no_arg() {
6464
#[cfg(unix)]
6565
fn test_valid_arg() {
6666
let args_list: Vec<&[&str]> = vec![
67-
&["-c"],
68-
&["--clean-print"],
67+
&["-d"],
68+
&["--silent"],
69+
&["-l"],
70+
&["--logical"],
71+
&["-e"],
72+
&["--exit-on-eof"],
73+
&["-f"],
74+
&["--no-pause"],
6975
&["-p"],
7076
&["--print-over"],
77+
&["-c"],
78+
&["--clean-print"],
7179
&["-s"],
7280
&["--squeeze"],
7381
&["-u"],
7482
&["--plain"],
7583
&["-n", "10"],
7684
&["--lines", "0"],
77-
&["--number", "0"],
78-
&["-F", "10"],
79-
&["--from-line", "0"],
80-
&["-P", "something"],
81-
&["--pattern", "-1"],
85+
&["-0"],
86+
&["+10"],
87+
&["+0"],
88+
&["+/something"],
89+
&["+/-1"],
8290
];
8391
for args in args_list {
8492
test_alive(args);
@@ -234,11 +242,8 @@ fn test_squeeze_blank_lines() {
234242
#[test]
235243
#[cfg(unix)]
236244
fn test_pattern_search() {
237-
let (child, controller, output) = run_more_with_pty(
238-
&["-P", "target"],
239-
"test.txt",
240-
"foo\nbar\nbaz\ntarget\nend\n",
241-
);
245+
let (child, controller, output) =
246+
run_more_with_pty(&["+/target"], "test.txt", "foo\nbar\nbaz\ntarget\nend\n");
242247
assert!(output.contains("target"));
243248
assert!(!output.contains("foo"));
244249
quit_more(&controller, child);
@@ -248,7 +253,7 @@ fn test_pattern_search() {
248253
#[cfg(unix)]
249254
fn test_from_line_option() {
250255
let (child, controller, output) =
251-
run_more_with_pty(&["-F", "2"], "test.txt", "line1\nline2\nline3\nline4\n");
256+
run_more_with_pty(&["+2"], "test.txt", "line1\nline2\nline3\nline4\n");
252257
assert!(output.contains("line2"));
253258
assert!(!output.contains("line1"));
254259
quit_more(&controller, child);

0 commit comments

Comments
 (0)