mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #4914 from Ideflop/more_implement_arguments_lines_and_number
more: implement arguments -n/--lines and --number
This commit is contained in:
commit
e8effd0d0a
2 changed files with 65 additions and 23 deletions
|
@ -14,10 +14,10 @@ use std::{
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
|
use clap::{crate_version, value_parser, Arg, ArgAction, ArgMatches, Command};
|
||||||
use crossterm::event::KeyEventKind;
|
use crossterm::event::KeyEventKind;
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
cursor::MoveTo,
|
cursor::{MoveTo, MoveUp},
|
||||||
event::{self, Event, KeyCode, KeyEvent, KeyModifiers},
|
event::{self, Event, KeyCode, KeyEvent, KeyModifiers},
|
||||||
execute, queue,
|
execute, queue,
|
||||||
style::Attribute,
|
style::Attribute,
|
||||||
|
@ -53,16 +53,28 @@ pub mod options {
|
||||||
const MULTI_FILE_TOP_PROMPT: &str = "::::::::::::::\n{}\n::::::::::::::\n";
|
const MULTI_FILE_TOP_PROMPT: &str = "::::::::::::::\n{}\n::::::::::::::\n";
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
silent: bool,
|
|
||||||
clean_print: bool,
|
clean_print: bool,
|
||||||
|
lines: Option<u16>,
|
||||||
print_over: bool,
|
print_over: bool,
|
||||||
|
silent: bool,
|
||||||
squeeze: bool,
|
squeeze: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Options {
|
impl Options {
|
||||||
fn from(matches: &ArgMatches) -> Self {
|
fn from(matches: &ArgMatches) -> Self {
|
||||||
|
let lines = match (
|
||||||
|
matches.get_one::<u16>(options::LINES).copied(),
|
||||||
|
matches.get_one::<u16>(options::NUMBER).copied(),
|
||||||
|
) {
|
||||||
|
// We add 1 to the number of lines to display because the last line
|
||||||
|
// is used for the banner
|
||||||
|
(Some(number), _) if number > 0 => Some(number + 1),
|
||||||
|
(None, Some(number)) if number > 0 => Some(number + 1),
|
||||||
|
(_, _) => None,
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
clean_print: matches.get_flag(options::CLEAN_PRINT),
|
clean_print: matches.get_flag(options::CLEAN_PRINT),
|
||||||
|
lines,
|
||||||
print_over: matches.get_flag(options::PRINT_OVER),
|
print_over: matches.get_flag(options::PRINT_OVER),
|
||||||
silent: matches.get_flag(options::SILENT),
|
silent: matches.get_flag(options::SILENT),
|
||||||
squeeze: matches.get_flag(options::SQUEEZE),
|
squeeze: matches.get_flag(options::SQUEEZE),
|
||||||
|
@ -167,6 +179,23 @@ pub fn uu_app() -> Command {
|
||||||
.help("Squeeze multiple blank lines into one")
|
.help("Squeeze multiple blank lines into one")
|
||||||
.action(ArgAction::SetTrue),
|
.action(ArgAction::SetTrue),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::LINES)
|
||||||
|
.short('n')
|
||||||
|
.long(options::LINES)
|
||||||
|
.value_name("number")
|
||||||
|
.num_args(1)
|
||||||
|
.value_parser(value_parser!(u16).range(0..))
|
||||||
|
.help("The number of lines per screen full"),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new(options::NUMBER)
|
||||||
|
.long(options::NUMBER)
|
||||||
|
.required(false)
|
||||||
|
.num_args(1)
|
||||||
|
.value_parser(value_parser!(u16).range(0..))
|
||||||
|
.help("Same as --lines"),
|
||||||
|
)
|
||||||
// The commented arguments below are unimplemented:
|
// The commented arguments below are unimplemented:
|
||||||
/*
|
/*
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -187,22 +216,6 @@ pub fn uu_app() -> Command {
|
||||||
.long(options::PLAIN)
|
.long(options::PLAIN)
|
||||||
.help("Suppress underlining and bold"),
|
.help("Suppress underlining and bold"),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
Arg::new(options::LINES)
|
|
||||||
.short('n')
|
|
||||||
.long(options::LINES)
|
|
||||||
.value_name("number")
|
|
||||||
.takes_value(true)
|
|
||||||
.help("The number of lines per screen full"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::new(options::NUMBER)
|
|
||||||
.allow_hyphen_values(true)
|
|
||||||
.long(options::NUMBER)
|
|
||||||
.required(false)
|
|
||||||
.takes_value(true)
|
|
||||||
.help("Same as --lines"),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new(options::FROM_LINE)
|
Arg::new(options::FROM_LINE)
|
||||||
.short('F')
|
.short('F')
|
||||||
|
@ -263,7 +276,11 @@ fn more(
|
||||||
next_file: Option<&str>,
|
next_file: Option<&str>,
|
||||||
options: &Options,
|
options: &Options,
|
||||||
) -> UResult<()> {
|
) -> UResult<()> {
|
||||||
let (cols, rows) = terminal::size().unwrap();
|
let (cols, mut rows) = terminal::size().unwrap();
|
||||||
|
if let Some(number) = options.lines {
|
||||||
|
rows = number;
|
||||||
|
}
|
||||||
|
|
||||||
let lines = break_buff(buff, usize::from(cols));
|
let lines = break_buff(buff, usize::from(cols));
|
||||||
|
|
||||||
let mut pager = Pager::new(rows, lines, next_file, options);
|
let mut pager = Pager::new(rows, lines, next_file, options);
|
||||||
|
@ -327,6 +344,7 @@ fn more(
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
pager.page_up();
|
pager.page_up();
|
||||||
|
paging_add_back_message(options, stdout)?;
|
||||||
}
|
}
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
code: KeyCode::Char('j'),
|
code: KeyCode::Char('j'),
|
||||||
|
@ -347,7 +365,7 @@ fn more(
|
||||||
pager.prev_line();
|
pager.prev_line();
|
||||||
}
|
}
|
||||||
Event::Resize(col, row) => {
|
Event::Resize(col, row) => {
|
||||||
pager.page_resize(col, row);
|
pager.page_resize(col, row, options.lines);
|
||||||
}
|
}
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
code: KeyCode::Char(k),
|
code: KeyCode::Char(k),
|
||||||
|
@ -447,8 +465,10 @@ impl<'a> Pager<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Deal with column size changes.
|
// TODO: Deal with column size changes.
|
||||||
fn page_resize(&mut self, _: u16, row: u16) {
|
fn page_resize(&mut self, _: u16, row: u16, option_line: Option<u16>) {
|
||||||
self.content_rows = row.saturating_sub(1);
|
if option_line.is_none() {
|
||||||
|
self.content_rows = row.saturating_sub(1);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&mut self, stdout: &mut std::io::Stdout, wrong_key: Option<char>) {
|
fn draw(&mut self, stdout: &mut std::io::Stdout, wrong_key: Option<char>) {
|
||||||
|
@ -536,6 +556,14 @@ impl<'a> Pager<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn paging_add_back_message(options: &Options, stdout: &mut std::io::Stdout) -> UResult<()> {
|
||||||
|
if options.lines.is_some() {
|
||||||
|
execute!(stdout, MoveUp(1))?;
|
||||||
|
stdout.write_all("\n\r...back 1 page\n".as_bytes())?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Break the lines on the cols of the terminal
|
// Break the lines on the cols of the terminal
|
||||||
fn break_buff(buff: &str, cols: usize) -> Vec<String> {
|
fn break_buff(buff: &str, cols: usize) -> Vec<String> {
|
||||||
let mut lines = Vec::with_capacity(buff.lines().count());
|
let mut lines = Vec::with_capacity(buff.lines().count());
|
||||||
|
|
|
@ -20,6 +20,20 @@ fn test_valid_arg() {
|
||||||
|
|
||||||
new_ucmd!().arg("-s").succeeds();
|
new_ucmd!().arg("-s").succeeds();
|
||||||
new_ucmd!().arg("--squeeze").succeeds();
|
new_ucmd!().arg("--squeeze").succeeds();
|
||||||
|
|
||||||
|
new_ucmd!().arg("-n").arg("10").succeeds();
|
||||||
|
new_ucmd!().arg("--lines").arg("0").succeeds();
|
||||||
|
new_ucmd!().arg("--number").arg("0").succeeds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_arg() {
|
||||||
|
if std::io::stdout().is_terminal() {
|
||||||
|
new_ucmd!().arg("--invalid").fails();
|
||||||
|
|
||||||
|
new_ucmd!().arg("--lines").arg("-10").fails();
|
||||||
|
new_ucmd!().arg("--number").arg("-10").fails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue