mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 13:37:48 +00:00
Merge pull request #2407 from hbina/hbina-more-terminal-resize
Improvements to `more`.
This commit is contained in:
commit
97ce44b102
1 changed files with 44 additions and 38 deletions
|
@ -210,14 +210,14 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>, silent: bo
|
||||||
let (cols, rows) = terminal::size().unwrap();
|
let (cols, rows) = terminal::size().unwrap();
|
||||||
let lines = break_buff(buff, usize::from(cols));
|
let lines = break_buff(buff, usize::from(cols));
|
||||||
|
|
||||||
let mut pager = Pager::new(rows as usize, lines, next_file, silent);
|
let mut pager = Pager::new(rows, lines, next_file, silent);
|
||||||
pager.draw(stdout, false);
|
pager.draw(stdout, None);
|
||||||
if pager.should_close() {
|
if pager.should_close() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let mut wrong_key = false;
|
let mut wrong_key = None;
|
||||||
if event::poll(Duration::from_millis(10)).unwrap() {
|
if event::poll(Duration::from_millis(10)).unwrap() {
|
||||||
match event::read().unwrap() {
|
match event::read().unwrap() {
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
|
@ -239,7 +239,11 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>, silent: bo
|
||||||
code: KeyCode::Char(' '),
|
code: KeyCode::Char(' '),
|
||||||
modifiers: KeyModifiers::NONE,
|
modifiers: KeyModifiers::NONE,
|
||||||
}) => {
|
}) => {
|
||||||
pager.page_down();
|
if pager.should_close() {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
pager.page_down();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::Key(KeyEvent {
|
Event::Key(KeyEvent {
|
||||||
code: KeyCode::Up,
|
code: KeyCode::Up,
|
||||||
|
@ -247,15 +251,17 @@ fn more(buff: &str, mut stdout: &mut Stdout, next_file: Option<&str>, silent: bo
|
||||||
}) => {
|
}) => {
|
||||||
pager.page_up();
|
pager.page_up();
|
||||||
}
|
}
|
||||||
_ => {
|
Event::Resize(col, row) => {
|
||||||
wrong_key = true;
|
pager.page_resize(col, row);
|
||||||
}
|
}
|
||||||
|
Event::Key(KeyEvent {
|
||||||
|
code: KeyCode::Char(k),
|
||||||
|
..
|
||||||
|
}) => wrong_key = Some(k),
|
||||||
|
_ => continue,
|
||||||
}
|
}
|
||||||
|
|
||||||
pager.draw(stdout, wrong_key);
|
pager.draw(stdout, wrong_key);
|
||||||
if pager.should_close() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,54 +270,49 @@ struct Pager<'a> {
|
||||||
// The current line at the top of the screen
|
// The current line at the top of the screen
|
||||||
upper_mark: usize,
|
upper_mark: usize,
|
||||||
// The number of rows that fit on the screen
|
// The number of rows that fit on the screen
|
||||||
content_rows: usize,
|
content_rows: u16,
|
||||||
lines: Vec<String>,
|
lines: Vec<String>,
|
||||||
next_file: Option<&'a str>,
|
next_file: Option<&'a str>,
|
||||||
line_count: usize,
|
line_count: usize,
|
||||||
close_on_down: bool,
|
|
||||||
silent: bool,
|
silent: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Pager<'a> {
|
impl<'a> Pager<'a> {
|
||||||
fn new(rows: usize, lines: Vec<String>, next_file: Option<&'a str>, silent: bool) -> Self {
|
fn new(rows: u16, lines: Vec<String>, next_file: Option<&'a str>, silent: bool) -> Self {
|
||||||
let line_count = lines.len();
|
let line_count = lines.len();
|
||||||
Self {
|
Self {
|
||||||
upper_mark: 0,
|
upper_mark: 0,
|
||||||
content_rows: rows - 1,
|
content_rows: rows.saturating_sub(1),
|
||||||
lines,
|
lines,
|
||||||
next_file,
|
next_file,
|
||||||
line_count,
|
line_count,
|
||||||
close_on_down: false,
|
|
||||||
silent,
|
silent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_close(&mut self) -> bool {
|
fn should_close(&mut self) -> bool {
|
||||||
if self.upper_mark + self.content_rows >= self.line_count {
|
self.upper_mark
|
||||||
if self.close_on_down {
|
.saturating_add(self.content_rows.into())
|
||||||
return true;
|
.ge(&self.line_count)
|
||||||
}
|
|
||||||
if self.next_file.is_none() {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
self.close_on_down = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.close_on_down = false;
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn page_down(&mut self) {
|
fn page_down(&mut self) {
|
||||||
self.upper_mark += self.content_rows;
|
self.upper_mark = self.upper_mark.saturating_add(self.content_rows.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn page_up(&mut self) {
|
fn page_up(&mut self) {
|
||||||
self.upper_mark = self.upper_mark.saturating_sub(self.content_rows);
|
self.upper_mark = self.upper_mark.saturating_sub(self.content_rows.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, stdout: &mut std::io::Stdout, wrong_key: bool) {
|
// TODO: Deal with column size changes.
|
||||||
let lower_mark = self.line_count.min(self.upper_mark + self.content_rows);
|
fn page_resize(&mut self, _: u16, row: u16) {
|
||||||
|
self.content_rows = row.saturating_sub(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&self, stdout: &mut std::io::Stdout, wrong_key: Option<char>) {
|
||||||
|
let lower_mark = self
|
||||||
|
.line_count
|
||||||
|
.min(self.upper_mark.saturating_add(self.content_rows.into()));
|
||||||
self.draw_lines(stdout);
|
self.draw_lines(stdout);
|
||||||
self.draw_prompt(stdout, lower_mark, wrong_key);
|
self.draw_prompt(stdout, lower_mark, wrong_key);
|
||||||
stdout.flush().unwrap();
|
stdout.flush().unwrap();
|
||||||
|
@ -323,7 +324,7 @@ impl<'a> Pager<'a> {
|
||||||
.lines
|
.lines
|
||||||
.iter()
|
.iter()
|
||||||
.skip(self.upper_mark)
|
.skip(self.upper_mark)
|
||||||
.take(self.content_rows);
|
.take(self.content_rows.into());
|
||||||
|
|
||||||
for line in displayed_lines {
|
for line in displayed_lines {
|
||||||
stdout
|
stdout
|
||||||
|
@ -332,7 +333,7 @@ impl<'a> Pager<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_prompt(&self, stdout: &mut Stdout, lower_mark: usize, wrong_key: bool) {
|
fn draw_prompt(&self, stdout: &mut Stdout, lower_mark: usize, wrong_key: Option<char>) {
|
||||||
let status_inner = if lower_mark == self.line_count {
|
let status_inner = if lower_mark == self.line_count {
|
||||||
format!("Next file: {}", self.next_file.unwrap_or_default())
|
format!("Next file: {}", self.next_file.unwrap_or_default())
|
||||||
} else {
|
} else {
|
||||||
|
@ -345,10 +346,15 @@ impl<'a> Pager<'a> {
|
||||||
let status = format!("--More--({})", status_inner);
|
let status = format!("--More--({})", status_inner);
|
||||||
|
|
||||||
let banner = match (self.silent, wrong_key) {
|
let banner = match (self.silent, wrong_key) {
|
||||||
(true, true) => "[Press 'h' for instructions. (unimplemented)]".to_string(),
|
(true, Some(key)) => {
|
||||||
(true, false) => format!("{}[Press space to continue, 'q' to quit.]", status),
|
format!(
|
||||||
(false, true) => format!("{}{}", status, BELL),
|
"{} [Unknown key: '{}'. Press 'h' for instructions. (unimplemented)]",
|
||||||
(false, false) => status,
|
status, key
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(true, None) => format!("{}[Press space to continue, 'q' to quit.]", status),
|
||||||
|
(false, Some(_)) => format!("{}{}", status, BELL),
|
||||||
|
(false, None) => status,
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(
|
write!(
|
||||||
|
@ -364,7 +370,7 @@ impl<'a> Pager<'a> {
|
||||||
|
|
||||||
// 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::new();
|
let mut lines = Vec::with_capacity(buff.lines().count());
|
||||||
|
|
||||||
for l in buff.lines() {
|
for l in buff.lines() {
|
||||||
lines.append(&mut break_line(l, cols));
|
lines.append(&mut break_line(l, cols));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue