summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2020-12-01 15:47:45 +0200
committerManos Pitsidianakis <el13635@mail.ntua.gr>2020-12-01 20:03:58 +0200
commitc5a5c2666bb32f2bd46a4ccfa465882638a8f068 (patch)
tree03d4b5f0cbec70fb51e3869125448a13d2fe58ad
parent7db32ff1b382bcdd562909855893dd4252d2e41e (diff)
utilities/pager: show scrolling percentage and/or search results position
-rw-r--r--src/components/utilities/pager.rs117
1 files changed, 110 insertions, 7 deletions
diff --git a/src/components/utilities/pager.rs b/src/components/utilities/pager.rs
index e80b2a58..8e1e7c0d 100644
--- a/src/components/utilities/pager.rs
+++ b/src/components/utilities/pager.rs
@@ -54,6 +54,7 @@ impl fmt::Display for Pager {
impl Pager {
pub const DESCRIPTION: &'static str = "pager";
+ const PAGES_AHEAD_TO_RENDER_NO: usize = 16;
pub fn new(context: &Context) -> Self {
let mut ret = Pager::default();
ret.minimum_width = context.settings.pager.minimum_width;
@@ -240,8 +241,18 @@ impl Pager {
.map(|offset| (y, offset)),
);
}
+ if let Some(pos) = search.positions.get(search.cursor) {
+ if self.cursor.1 > pos.0 || self.cursor.1 + height!(area) < pos.0 {
+ self.cursor.1 = pos.0.saturating_sub(3);
+ }
+ }
}
- self.draw_lines_up_to(grid, area, context, self.cursor.1 + 2 * height!(area));
+ self.draw_lines_up_to(
+ grid,
+ area,
+ context,
+ self.cursor.1 + Self::PAGES_AHEAD_TO_RENDER_NO * height!(area),
+ );
self.draw_page(grid, area, context);
self.initialised = true;
}
@@ -350,8 +361,10 @@ impl Pager {
{
let x = *x + get_x(upper_left);
let y = *y - cursor_line;
- for c in grid.row_iter(x..x + search.pattern.grapheme_len(), y + get_y(upper_left))
- {
+ for c in grid.row_iter(
+ x..x + search.pattern.grapheme_width(),
+ y + get_y(upper_left),
+ ) {
if i == search.cursor {
grid[c]
.set_fg(results_current_attr.fg)
@@ -399,7 +412,12 @@ impl Component for Pager {
} else {
self.cursor.1 = self.height.saturating_sub(1);
}
- self.draw_lines_up_to(grid, area, context, self.cursor.1 + height);
+ self.draw_lines_up_to(
+ grid,
+ area,
+ context,
+ self.cursor.1 + Self::PAGES_AHEAD_TO_RENDER_NO * height,
+ );
}
PageMovement::PageDown(multiplier) => {
if self.cursor.1 + height * multiplier + 1 < self.height {
@@ -409,7 +427,12 @@ impl Component for Pager {
} else {
self.cursor.1 = (self.height / height) * height;
}
- self.draw_lines_up_to(grid, area, context, self.cursor.1 + height);
+ self.draw_lines_up_to(
+ grid,
+ area,
+ context,
+ self.cursor.1 + Self::PAGES_AHEAD_TO_RENDER_NO * height,
+ );
}
PageMovement::Right(amount) => {
if self.cursor.0 + amount + 1 < self.width {
@@ -425,8 +448,8 @@ impl Component for Pager {
self.cursor.1 = 0;
}
PageMovement::End => {
- self.cursor.1 = self.height.saturating_sub(1);
self.draw_lines_up_to(grid, area, context, 0);
+ self.cursor.1 = self.height.saturating_sub(1);
}
}
}
@@ -462,7 +485,11 @@ impl Component for Pager {
let (width, height) = (self.line_breaker.width().unwrap_or(cols), self.height);
if self.show_scrollbar && rows < height {
cols -= 1;
+ rows -= 1;
+ } else if self.search.is_some() {
+ rows -= 1;
}
+
if self.show_scrollbar && cols < width {
rows -= 1;
}
@@ -470,7 +497,11 @@ impl Component for Pager {
std::cmp::min(width.saturating_sub(cols), self.cursor.0),
std::cmp::min(height.saturating_sub(rows), self.cursor.1),
);
- self.draw_page(grid, area, context);
+ self.draw_page(
+ grid,
+ (upper_left!(area), pos_inc(upper_left!(area), (cols, rows))),
+ context,
+ );
if self.show_scrollbar && rows < height {
ScrollBar::default().set_show_arrows(true).draw(
grid,
@@ -500,6 +531,78 @@ impl Component for Pager {
width,
);
}
+ if (rows < height) || self.search.is_some() {
+ const RESULTS_STR: &str = "Results for ";
+ let shown_percentage =
+ ((self.cursor.1 + rows) as f32 / (height as f32) * 100.0) as usize;
+ let shown_lines = self.cursor.1 + rows;
+ let total_lines = height;
+ let scrolling = if rows < height {
+ format!(
+ "{shown_percentage}% {line_desc}{shown_lines}/{total_lines}{has_more_lines}",
+ line_desc = if grid.ascii_drawing { "lines:" } else { "☰ " },
+ shown_percentage = shown_percentage,
+ shown_lines = shown_lines,
+ total_lines = total_lines,
+ has_more_lines = if self.line_breaker.is_finished() {
+ ""
+ } else {
+ "(+)"
+ }
+ )
+ } else {
+ String::new()
+ };
+ let search_results = if let Some(ref search) = self.search {
+ format!(
+ "{results_str}{search_pattern}: {current_pos}/{total_results}{has_more_lines}",
+ results_str = RESULTS_STR,
+ search_pattern = &search.pattern,
+ current_pos = if search.positions.is_empty() {
+ 0
+ } else {
+ search.cursor + 1
+ },
+ total_results = search.positions.len(),
+ has_more_lines = if self.line_breaker.is_finished() {
+ ""
+ } else {
+ "(+)"
+ }
+ )
+ } else {
+ String::new()
+ };
+ let status_message = format!(
+ "{search_results}{divider}{scrolling}",
+ search_results = search_results,
+ divider = if self.search.is_some() { " " } else { "" },
+ scrolling = scrolling,
+ );
+ let mut attribute = crate::conf::value(context, "status.bar");
+ if !context.settings.terminal.use_color() {
+ attribute.attrs |= Attr::REVERSE;
+ }
+ let (_, y) = write_string_to_grid(
+ &status_message,
+ grid,
+ attribute.fg,
+ attribute.bg,
+ attribute.attrs,
+ (
+ set_y(upper_left!(area), get_y(bottom_right!(area))),
+ bottom_right!(area),
+ ),
+ None,
+ );
+ /* set search pattern to italics */
+ if let Some(ref search) = self.search {
+ let start_x = get_x(upper_left!(area)) + RESULTS_STR.len();
+ for c in grid.row_iter(start_x..(start_x + search.pattern.grapheme_width()), y) {
+ grid[c].set_attrs(attribute.attrs | Attr::ITALICS);
+ }
+ }
+ }
context.dirty_areas.push_back(area);
}