Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More implement arguments plain and from line #4950

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 54 additions & 28 deletions src/uu/more/src/more.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ pub mod options {
pub const FILES: &str = "files";
}

const MULTI_FILE_TOP_PROMPT: &str = "::::::::::::::\n{}\n::::::::::::::\n";
const MULTI_FILE_TOP_PROMPT: &str = "\r::::::::::::::\n\r{}\n\r::::::::::::::\n";

struct Options {
clean_print: bool,
from_line: usize,
lines: Option<u16>,
print_over: bool,
silent: bool,
Expand All @@ -72,8 +73,13 @@ impl Options {
(None, Some(number)) if number > 0 => Some(number + 1),
(_, _) => None,
};
let from_line = match matches.get_one::<usize>(options::FROM_LINE).copied() {
Some(number) if number > 1 => number - 1,
_ => 0,
};
Self {
clean_print: matches.get_flag(options::CLEAN_PRINT),
from_line,
lines,
print_over: matches.get_flag(options::PRINT_OVER),
silent: matches.get_flag(options::SILENT),
Expand All @@ -90,7 +96,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
Err(e) => return Err(e.into()),
};

let options = Options::from(&matches);
let mut options = Options::from(&matches);

let mut buff = String::new();

Expand All @@ -115,9 +121,6 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
format!("cannot open {}: No such file or directory", file.quote()),
));
}
if length > 1 {
buff.push_str(&MULTI_FILE_TOP_PROMPT.replace("{}", file.to_str().unwrap()));
}
let opened_file = match File::open(file) {
Err(why) => {
terminal::disable_raw_mode().unwrap();
Expand All @@ -130,14 +133,21 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
};
let mut reader = BufReader::new(opened_file);
reader.read_to_string(&mut buff).unwrap();
more(&buff, &mut stdout, next_file.copied(), &options)?;
more(
&buff,
&mut stdout,
length > 1,
file.to_str(),
next_file.copied(),
&mut options,
)?;
buff.clear();
}
reset_term(&mut stdout);
} else if !std::io::stdin().is_terminal() {
stdin().read_to_string(&mut buff).unwrap();
let mut stdout = setup_term();
more(&buff, &mut stdout, None, &options)?;
more(&buff, &mut stdout, false, None, None, &mut options)?;
reset_term(&mut stdout);
} else {
return Err(UUsageError::new(1, "bad usage"));
Expand Down Expand Up @@ -179,6 +189,22 @@ pub fn uu_app() -> Command {
.help("Squeeze multiple blank lines into one")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::PLAIN)
Ideflop marked this conversation as resolved.
Show resolved Hide resolved
.short('u')
.long(options::PLAIN)
.action(ArgAction::SetTrue)
.hide(true),
)
.arg(
Arg::new(options::FROM_LINE)
.short('F')
.long(options::FROM_LINE)
.num_args(1)
.value_name("number")
.value_parser(value_parser!(usize))
.help("Display file beginning from line number"),
)
.arg(
Arg::new(options::LINES)
.short('n')
Expand All @@ -191,7 +217,6 @@ pub fn uu_app() -> Command {
.arg(
Arg::new(options::NUMBER)
.long(options::NUMBER)
.required(false)
.num_args(1)
.value_parser(value_parser!(u16).range(0..))
.help("Same as --lines"),
Expand All @@ -210,21 +235,6 @@ pub fn uu_app() -> Command {
.long(options::NO_PAUSE)
.help("Suppress pause after form feed"),
)
.arg(
Arg::new(options::PLAIN)
.short('u')
.long(options::PLAIN)
.help("Suppress underlining and bold"),
)
.arg(
Arg::new(options::FROM_LINE)
.short('F')
.allow_hyphen_values(true)
.required(false)
.takes_value(true)
.value_name("number")
.help("Display file beginning from line number"),
)
.arg(
Arg::new(options::PATTERN)
.short('P')
Expand Down Expand Up @@ -273,8 +283,10 @@ fn reset_term(_: &mut usize) {}
fn more(
buff: &str,
stdout: &mut Stdout,
multiple_file: bool,
file: Option<&str>,
next_file: Option<&str>,
options: &Options,
options: &mut Options,
) -> UResult<()> {
let (cols, mut rows) = terminal::size().unwrap();
if let Some(number) = options.lines {
Expand All @@ -284,8 +296,23 @@ fn more(
let lines = break_buff(buff, usize::from(cols));

let mut pager = Pager::new(rows, lines, next_file, options);

if multiple_file {
execute!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap();
stdout.write_all(
MULTI_FILE_TOP_PROMPT
.replace("{}", file.unwrap_or_default())
.as_bytes(),
)?;
pager.content_rows -= 3;
}
pager.draw(stdout, None);
if pager.should_close() {
if multiple_file {
options.from_line = 0;
pager.content_rows += 3;
}

if pager.should_close() && next_file.is_none() {
return Ok(());
}

Expand Down Expand Up @@ -406,7 +433,7 @@ impl<'a> Pager<'a> {
fn new(rows: u16, lines: Vec<String>, next_file: Option<&'a str>, options: &Options) -> Self {
let line_count = lines.len();
Self {
upper_mark: 0,
upper_mark: options.from_line,
content_rows: rows.saturating_sub(1),
lines,
next_file,
Expand Down Expand Up @@ -472,10 +499,10 @@ impl<'a> Pager<'a> {
}

fn draw(&mut self, stdout: &mut std::io::Stdout, wrong_key: Option<char>) {
self.draw_lines(stdout);
let lower_mark = self
.line_count
.min(self.upper_mark.saturating_add(self.content_rows.into()));
self.draw_lines(stdout);
self.draw_prompt(stdout, lower_mark, wrong_key);
stdout.flush().unwrap();
}
Expand Down Expand Up @@ -535,7 +562,6 @@ impl<'a> Pager<'a> {
};

let status = format!("--More--({status_inner})");

let banner = match (self.silent, wrong_key) {
(true, Some(key)) => format!(
"{status} [Unknown key: '{key}'. Press 'h' for instructions. (unimplemented)]"
Expand Down
42 changes: 42 additions & 0 deletions tests/by-util/test_more.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ fn test_valid_arg() {
new_ucmd!().arg("-s").succeeds();
new_ucmd!().arg("--squeeze").succeeds();

new_ucmd!().arg("-u").succeeds();
new_ucmd!().arg("--plain").succeeds();

new_ucmd!().arg("-n").arg("10").succeeds();
new_ucmd!().arg("--lines").arg("0").succeeds();
new_ucmd!().arg("--number").arg("0").succeeds();

new_ucmd!().arg("-F").arg("10").succeeds();
new_ucmd!().arg("--from-line").arg("0").succeeds();
}
}

Expand All @@ -34,6 +40,42 @@ fn test_invalid_arg() {

new_ucmd!().arg("--lines").arg("-10").fails();
new_ucmd!().arg("--number").arg("-10").fails();

new_ucmd!().arg("--from-line").arg("-10").fails();
}
}

#[test]
fn test_argument_from_file() {
if std::io::stdout().is_terminal() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;

let file = "test_file";

at.write(file, "1\n2");

// output all lines
scene
.ucmd()
.arg("-F")
.arg("0")
.arg(file)
.succeeds()
.no_stderr()
.stdout_contains("1")
.stdout_contains("2");

// output only the second line
scene
.ucmd()
.arg("-F")
.arg("2")
.arg(file)
.succeeds()
.no_stderr()
.stdout_contains("2")
.stdout_does_not_contain("1");
}
}

Expand Down