1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

more: add arguments print over and clean print

This commit is contained in:
Ideflop 2023-05-17 20:38:03 +02:00
parent d769871374
commit b676875c0c
2 changed files with 67 additions and 23 deletions

View file

@ -14,13 +14,14 @@ use std::{
time::Duration,
};
use clap::{crate_version, Arg, ArgAction, Command};
use clap::{crate_version, Arg, ArgAction, ArgMatches, Command};
use crossterm::event::KeyEventKind;
use crossterm::{
cursor::MoveTo,
event::{self, Event, KeyCode, KeyEvent, KeyModifiers},
execute, queue,
style::Attribute,
terminal,
terminal::{self, Clear, ClearType},
};
use is_terminal::IsTerminal;
@ -51,12 +52,34 @@ pub mod options {
const MULTI_FILE_TOP_PROMPT: &str = "::::::::::::::\n{}\n::::::::::::::\n";
struct Options {
silent: bool,
clean_print: bool,
print_over: bool,
}
impl Options {
fn from(matches: &ArgMatches) -> Self {
Self {
silent: matches.get_flag(options::SILENT),
clean_print: matches.get_flag(options::CLEAN_PRINT),
print_over: matches.get_flag(options::PRINT_OVER),
}
}
}
#[uucore::main]
pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().get_matches_from(args);
let args = args.collect_lossy();
let matches = match uu_app().try_get_matches_from(&args) {
Ok(m) => m,
Err(e) => return Err(e.into()),
};
let options = Options::from(&matches);
let mut buff = String::new();
let silent = matches.get_flag(options::SILENT);
if let Some(files) = matches.get_many::<String>(options::FILES) {
let mut stdout = setup_term();
let length = files.len();
@ -83,14 +106,14 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
let mut reader = BufReader::new(File::open(file).unwrap());
reader.read_to_string(&mut buff).unwrap();
more(&buff, &mut stdout, next_file.copied(), silent)?;
more(&buff, &mut stdout, next_file.copied(), &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, silent)?;
more(&buff, &mut stdout, None, &options)?;
reset_term(&mut stdout);
} else {
return Err(UUsageError::new(1, "bad usage"));
@ -104,6 +127,13 @@ pub fn uu_app() -> Command {
.override_usage(format_usage(USAGE))
.version(crate_version!())
.infer_long_args(true)
.arg(
Arg::new(options::PRINT_OVER)
.short('c')
.long(options::PRINT_OVER)
.help("Do not scroll, display text and clean line ends")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::SILENT)
.short('d')
@ -111,6 +141,13 @@ pub fn uu_app() -> Command {
.help("Display help instead of ringing bell")
.action(ArgAction::SetTrue),
)
.arg(
Arg::new(options::CLEAN_PRINT)
.short('p')
.long(options::CLEAN_PRINT)
.help("Do not scroll, clean screen and display text")
.action(ArgAction::SetTrue),
)
// The commented arguments below are unimplemented:
/*
.arg(
@ -125,18 +162,6 @@ pub fn uu_app() -> Command {
.long(options::NO_PAUSE)
.help("Suppress pause after form feed"),
)
.arg(
Arg::new(options::PRINT_OVER)
.short('c')
.long(options::PRINT_OVER)
.help("Do not scroll, display text and clean line ends"),
)
.arg(
Arg::new(options::CLEAN_PRINT)
.short('p')
.long(options::CLEAN_PRINT)
.help("Do not scroll, clean screen and display text"),
)
.arg(
Arg::new(options::SQUEEZE)
.short('s')
@ -209,7 +234,7 @@ fn setup_term() -> usize {
fn reset_term(stdout: &mut std::io::Stdout) {
terminal::disable_raw_mode().unwrap();
// Clear the prompt
queue!(stdout, terminal::Clear(terminal::ClearType::CurrentLine)).unwrap();
queue!(stdout, terminal::Clear(ClearType::CurrentLine)).unwrap();
// Move cursor to the beginning without printing new line
print!("\r");
stdout.flush().unwrap();
@ -219,11 +244,16 @@ fn reset_term(stdout: &mut std::io::Stdout) {
#[inline(always)]
fn reset_term(_: &mut usize) {}
fn more(buff: &str, stdout: &mut Stdout, next_file: Option<&str>, silent: bool) -> UResult<()> {
fn more(
buff: &str,
stdout: &mut Stdout,
next_file: Option<&str>,
options: &Options,
) -> UResult<()> {
let (cols, rows) = terminal::size().unwrap();
let lines = break_buff(buff, usize::from(cols));
let mut pager = Pager::new(rows, lines, next_file, silent);
let mut pager = Pager::new(rows, lines, next_file, options);
pager.draw(stdout, None);
if pager.should_close() {
return Ok(());
@ -303,6 +333,11 @@ fn more(buff: &str, stdout: &mut Stdout, next_file: Option<&str>, silent: bool)
_ => continue,
}
if options.clean_print {
execute!(std::io::stdout(), Clear(ClearType::Purge), MoveTo(0, 0)).unwrap();
} else if options.print_over {
execute!(std::io::stdout(), Clear(ClearType::All), MoveTo(0, 0)).unwrap();
}
pager.draw(stdout, wrong_key);
}
}
@ -320,7 +355,7 @@ struct Pager<'a> {
}
impl<'a> Pager<'a> {
fn new(rows: u16, lines: Vec<String>, next_file: Option<&'a str>, silent: bool) -> Self {
fn new(rows: u16, lines: Vec<String>, next_file: Option<&'a str>, options: &Options) -> Self {
let line_count = lines.len();
Self {
upper_mark: 0,
@ -328,7 +363,7 @@ impl<'a> Pager<'a> {
lines,
next_file,
line_count,
silent,
silent: options.silent,
}
}

View file

@ -10,6 +10,15 @@ fn test_more_no_arg() {
}
}
#[test]
fn test_valid_arg() {
new_ucmd!().arg("-c").succeeds().code_is(0);
new_ucmd!().arg("--print-over").succeeds().code_is(0);
new_ucmd!().arg("-p").succeeds().code_is(0);
new_ucmd!().arg("--clean-print").succeeds().code_is(0);
}
#[test]
fn test_more_dir_arg() {
// Run the test only if there's a valid terminal, else do nothing