change: add scrolling to help menu

This commit is contained in:
Clement Tsang 2020-04-24 19:17:58 -04:00 committed by GitHub
parent 99fe0a1844
commit 863e780f2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 373 additions and 172 deletions

View File

@ -27,12 +27,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `"processes"`
- `"temperature"`
- Removed an (undocumented) feature in allowing modifying total RX/TX colours. This is mainly due to the legend change.
- Updated error messages to be a bit more consistent/helpful.
- [#117](https://github.com/ClementTsang/bottom/issues/117): Update tui to 0.9:
- Removed an (undocumented) feature in allowing modifying total RX/TX colours. This is mainly due to the legend change.
- Use custom legend-hiding to stop hiding legends for memory and network widgets.
- In addition, changed to using only legends within the graph for network, as well as redesigned the legend.
@ -40,9 +38,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow for option to hide the header gap on tables via `--hide_table_gap` or `hide_table_gap = true`.
- Switch to stateful widget style for tables.
- [#126](https://github.com/ClementTsang/bottom/pull/126): Updated error messages to be a bit more consistent/helpful.
- Switch to using tui-rs' new built in linear interpolation rather than doing it manually.
- Redesigned help menu to allow for scrolling.
### Bug Fixes
@ -51,9 +49,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed bug where a single empty row as a layout would crash without a proper warning.
The behaviour now errors out with a more helpful message.
### Other
### Development changes
- Updated tests and added config testing.
- Switch to stateful widget style for tables.
- Switch to using tui-rs' new built in linear interpolation rather than doing it manually.
- Updated arg tests and added config testing.
- More refactoring.
## [0.3.0] - 2020-04-07

View File

@ -7,6 +7,8 @@
A cross-platform graphical process/system monitor with a customizable interface and a multitude of features. Supports Linux, macOS, and Windows. Inspired by both [gtop](https://github.com/aksakalli/gtop) and [gotop](https://github.com/cjbassi/gotop).
<!--TODO: Update recording for 0.4-->
![Quick demo recording showing off searching, maximizing, and process killing.](assets/summary_and_search.gif) _Theme based on [gruvbox](https://github.com/morhetz/gruvbox) (see [sample config](./sample_configs/demo_config.toml))._ Recorded on version 0.2.0.
**Note**: This documentation is relevant to version 0.4.0 and may refer to in-development features, especially if you are reading this on the master branch. Please refer to [release branch](https://github.com/ClementTsang/bottom/tree/release/README.md) or [crates.io](https://crates.io/crates/bottom) for the most up-to-date _release_ documentation.
@ -163,19 +165,19 @@ Run using `btm`.
| | |
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `q`, `Ctrl-c` | Quit bottom |
| `q`, `Ctrl-c` | Quit |
| `Esc` | Close dialog windows, search, widgets, or exit maximized mode |
| `Ctrl-r` | Reset display and any collected data |
| `f` | Freeze/unfreeze updating with new data |
| `Ctrl`-arrow key<br>`Shift`-arrow key<br>`H/J/K/L` | Move to a different widget (on macOS some keybindings may conflict) |
| `Up`,`k` | Scroll up in tables |
| `Down`, `j` | Scroll down in tables |
| `Up`,`k` | Scroll up |
| `Down`, `j` | Scroll down |
| `?` | Open help menu |
| `gg`, `Home` | Jump to the first entry of a table |
| `Shift-g`, `End` | Jump to the last entry of a table |
| `Enter` | Maximize widget |
| `+` | Zoom in on a chart |
| `-` | Zoom out on a chart |
| `gg`, `Home` | Jump to the first entry |
| `Shift-g`, `End` | Jump to the last entry |
| `Enter` | Maximize the currently selected widget |
| `+` | Zoom in on chart (decrease time range) |
| `-` | Zoom out on chart (increase time range) |
| `=` | Reset zoom |
| Mouse scroll | Table: Scrolls through the list<br>Chart: Zooms in or out by scrolling up or down respectively |
@ -207,6 +209,9 @@ Run using `btm`.
| `Esc` | Close the search widget (retains the filter) |
| `Ctrl-a` | Skip to the start of the search query |
| `Ctrl-e` | Skip to the end of the search query |
| `Ctrl-u` | Clear the current search query |
| `Backspace` | Delete the character behind the cursor |
| `Delete` | Delete the character at the cursor |
| `Alt-c`/`F1` | Toggle matching case |
| `Alt-w`/`F2` | Toggle matching the entire word |
| `Alt-r`/`F3` | Toggle using regex |

View File

@ -64,18 +64,15 @@ pub enum AppHelpCategory {
Search,
}
#[derive(Default)]
pub struct AppHelpDialogState {
pub is_showing_help: bool,
pub current_category: AppHelpCategory,
}
impl Default for AppHelpDialogState {
fn default() -> Self {
AppHelpDialogState {
is_showing_help: false,
current_category: AppHelpCategory::General,
}
}
pub scroll_state: ParagraphScrollState,
pub general_index: u16,
pub cpu_index: u16,
pub process_index: u16,
pub search_index: u16,
pub battery_index: u16,
}
/// AppConfigFields is meant to cover basic fields that would normally be set
@ -481,6 +478,12 @@ impl BatteryState {
}
}
#[derive(Default)]
pub struct ParagraphScrollState {
pub current_scroll_index: u16,
pub max_scroll_index: u16,
}
#[derive(TypedBuilder)]
pub struct App {
#[builder(default = false, setter(skip))]
@ -517,7 +520,7 @@ pub struct App {
pub is_expanded: bool,
#[builder(default = false, setter(skip))]
pub is_resized: bool,
pub is_force_redraw: bool,
pub cpu_state: CpuState,
pub mem_state: MemState,
@ -581,11 +584,11 @@ impl App {
self.reset_multi_tap_keys();
if self.is_in_dialog() {
self.help_dialog_state.is_showing_help = false;
self.help_dialog_state.current_category = AppHelpCategory::General;
self.delete_dialog_state.is_showing_dd = false;
self.delete_dialog_state.is_on_yes = false;
self.to_delete_process_list = None;
self.dd_err = None;
self.is_force_redraw = true;
} else if self.is_filtering_or_searching() {
match self.current_widget.widget_type {
BottomWidgetType::Cpu => {
@ -603,7 +606,7 @@ impl App {
cpu_widget_state.scroll_state.current_scroll_position = new_position;
cpu_widget_state.scroll_state.previous_scroll_position = 0;
}
self.is_resized = true;
self.is_force_redraw = true;
}
}
BottomWidgetType::CpuLegend => {
@ -621,7 +624,7 @@ impl App {
cpu_widget_state.scroll_state.current_scroll_position = new_position;
cpu_widget_state.scroll_state.previous_scroll_position = 0;
}
self.is_resized = true;
self.is_force_redraw = true;
}
}
BottomWidgetType::Proc => {
@ -636,7 +639,7 @@ impl App {
.search_state
.is_enabled = false;
}
self.is_resized = true;
self.is_force_redraw = true;
}
}
BottomWidgetType::ProcSearch => {
@ -652,14 +655,14 @@ impl App {
.is_enabled = false;
self.move_widget_selection_up();
}
self.is_resized = true;
self.is_force_redraw = true;
}
}
_ => {}
}
} else if self.is_expanded {
self.is_expanded = false;
self.is_resized = true;
self.is_force_redraw = true;
}
}
@ -974,7 +977,7 @@ impl App {
BottomWidgetType::ProcSearch => {}
_ => {
self.is_expanded = true;
self.is_resized = true;
self.is_force_redraw = true;
}
}
}
@ -1098,13 +1101,19 @@ impl App {
pub fn on_up_key(&mut self) {
if !self.is_in_dialog() {
self.decrement_position_count();
} else if self.help_dialog_state.is_showing_help {
self.help_scroll_up();
}
self.reset_multi_tap_keys();
}
pub fn on_down_key(&mut self) {
if !self.is_in_dialog() {
self.increment_position_count();
} else if self.help_dialog_state.is_showing_help {
self.help_scroll_down();
}
self.reset_multi_tap_keys();
}
pub fn on_left_key(&mut self) {
@ -1428,10 +1437,16 @@ impl App {
}
self.handle_char(caught_char);
} else if self.help_dialog_state.is_showing_help {
// TODO: Seems weird that we have it like this; it would be better to make this
// more obvious that we are separating dialog logic and normal logic IMO.
// This is even more so as most logic already checks for dialog state.
match caught_char {
'1' => self.help_dialog_state.current_category = AppHelpCategory::General,
'2' => self.help_dialog_state.current_category = AppHelpCategory::Process,
'3' => self.help_dialog_state.current_category = AppHelpCategory::Search,
'1' => self.help_scroll_to_or_max(self.help_dialog_state.general_index),
'2' => self.help_scroll_to_or_max(self.help_dialog_state.cpu_index),
'3' => self.help_scroll_to_or_max(self.help_dialog_state.process_index),
'4' => self.help_scroll_to_or_max(self.help_dialog_state.search_index),
'5' => self.help_scroll_to_or_max(self.help_dialog_state.battery_index),
'j' | 'k' | 'g' | 'G' => self.handle_char(caught_char),
_ => {}
}
}
@ -1478,8 +1493,8 @@ impl App {
}
}
'G' => self.skip_to_last(),
'k' => self.decrement_position_count(),
'j' => self.increment_position_count(),
'k' => self.on_up_key(),
'j' => self.on_down_key(),
'f' => {
self.is_frozen = !self.is_frozen;
if self.is_frozen {
@ -1584,6 +1599,7 @@ impl App {
}
'?' => {
self.help_dialog_state.is_showing_help = true;
self.is_force_redraw = true;
}
'H' => self.move_widget_selection_left(),
'L' => self.move_widget_selection_right(),
@ -2019,6 +2035,8 @@ impl App {
_ => {}
}
self.reset_multi_tap_keys();
} else {
self.help_dialog_state.scroll_state.current_scroll_index = 0;
}
}
@ -2093,6 +2111,12 @@ impl App {
_ => {}
}
self.reset_multi_tap_keys();
} else {
self.help_dialog_state.scroll_state.current_scroll_index = self
.help_dialog_state
.scroll_state
.max_scroll_index
.saturating_sub(1);
}
}
@ -2105,7 +2129,6 @@ impl App {
BottomWidgetType::CpuLegend => self.change_cpu_table_position(-1),
_ => {}
}
self.reset_multi_tap_keys();
}
}
@ -2118,7 +2141,6 @@ impl App {
BottomWidgetType::CpuLegend => self.change_cpu_table_position(1),
_ => {}
}
self.reset_multi_tap_keys();
}
}
@ -2228,8 +2250,33 @@ impl App {
}
}
fn help_scroll_up(&mut self) {
if self.help_dialog_state.scroll_state.current_scroll_index > 0 {
self.help_dialog_state.scroll_state.current_scroll_index -= 1;
}
}
fn help_scroll_down(&mut self) {
if self.help_dialog_state.scroll_state.current_scroll_index + 1
< self.help_dialog_state.scroll_state.max_scroll_index
{
self.help_dialog_state.scroll_state.current_scroll_index += 1;
}
}
fn help_scroll_to_or_max(&mut self, new_position: u16) {
if new_position < self.help_dialog_state.scroll_state.max_scroll_index {
self.help_dialog_state.scroll_state.current_scroll_index = new_position;
} else {
self.help_dialog_state.scroll_state.current_scroll_index =
self.help_dialog_state.scroll_state.max_scroll_index - 1;
}
}
pub fn handle_scroll_up(&mut self) {
if self.current_widget.widget_type.is_widget_graph() {
if self.help_dialog_state.is_showing_help {
self.help_scroll_up();
} else if self.current_widget.widget_type.is_widget_graph() {
self.zoom_in();
} else if self.current_widget.widget_type.is_widget_table() {
self.decrement_position_count();
@ -2237,7 +2284,9 @@ impl App {
}
pub fn handle_scroll_down(&mut self) {
if self.current_widget.widget_type.is_widget_graph() {
if self.help_dialog_state.is_showing_help {
self.help_scroll_down();
} else if self.current_widget.widget_type.is_widget_graph() {
self.zoom_out();
} else if self.current_widget.widget_type.is_widget_table() {
self.increment_position_count();

View File

@ -59,9 +59,7 @@ pub struct Painter {
pub colours: CanvasColours,
height: u16,
width: u16,
styled_general_help_text: Vec<Text<'static>>,
styled_process_help_text: Vec<Text<'static>>,
styled_search_help_text: Vec<Text<'static>>,
styled_help_text: Vec<Text<'static>>,
is_mac_os: bool,
row_constraints: Vec<Constraint>,
col_constraints: Vec<Vec<Constraint>>,
@ -145,9 +143,7 @@ impl Painter {
colours: CanvasColours::default(),
height: 0,
width: 0,
styled_general_help_text: Vec::new(),
styled_process_help_text: Vec::new(),
styled_search_help_text: Vec::new(),
styled_help_text: Vec::new(),
is_mac_os: false,
row_constraints,
col_constraints,
@ -164,44 +160,79 @@ impl Painter {
pub fn complete_painter_init(&mut self) {
self.is_mac_os = cfg!(target_os = "macos");
if GENERAL_HELP_TEXT.len() > 1 {
self.styled_general_help_text.push(Text::Styled(
GENERAL_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_general_help_text.extend(
GENERAL_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
}
// Init help text:
// ToC
self.styled_help_text.extend(
HELP_CONTENTS_TEXT
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
if PROCESS_HELP_TEXT.len() > 1 {
self.styled_process_help_text.push(Text::Styled(
PROCESS_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_process_help_text.extend(
PROCESS_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
}
// General
self.styled_help_text.push(Text::Raw("\n\n".into()));
self.styled_help_text.push(Text::Styled(
GENERAL_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_help_text.extend(
GENERAL_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
if SEARCH_HELP_TEXT.len() > 1 {
self.styled_search_help_text.push(Text::Styled(
SEARCH_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_search_help_text.extend(
SEARCH_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
}
// CPU
self.styled_help_text.push(Text::Raw("\n\n".into()));
self.styled_help_text.push(Text::Styled(
CPU_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_help_text.extend(
CPU_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
// Proc
self.styled_help_text.push(Text::Raw("\n\n".into()));
self.styled_help_text.push(Text::Styled(
PROCESS_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_help_text.extend(
PROCESS_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
// Proc Search
self.styled_help_text.push(Text::Raw("\n\n".into()));
self.styled_help_text.push(Text::Styled(
SEARCH_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_help_text.extend(
SEARCH_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
// Battery
self.styled_help_text.push(Text::Raw("\n\n".into()));
self.styled_help_text.push(Text::Styled(
BATTERY_HELP_TEXT[0].into(),
self.colours.table_header_style,
));
self.styled_help_text.extend(
BATTERY_HELP_TEXT[1..]
.iter()
.map(|&text| Text::Styled(text.into(), self.colours.text_style))
.collect::<Vec<_>>(),
);
}
// TODO: [FEATURE] Auto-resizing dialog sizes.
@ -214,11 +245,10 @@ impl Painter {
let current_height = terminal_size.height;
let current_width = terminal_size.width;
if self.height == 0 && self.width == 0 {
self.height = current_height;
self.width = current_width;
} else if self.height != current_height || self.width != current_width {
app_state.is_resized = true;
if (self.height == 0 && self.width == 0)
|| (self.height != current_height || self.width != current_width)
{
app_state.is_force_redraw = true;
self.height = current_height;
self.width = current_width;
}
@ -434,7 +464,7 @@ impl Painter {
}
} else {
// Draws using the passed in (or default) layout. NOT basic so far.
if self.derived_widget_draw_locs.is_empty() || app_state.is_resized {
if self.derived_widget_draw_locs.is_empty() || app_state.is_force_redraw {
let row_draw_locs = Layout::default()
.margin(0)
.constraints(self.row_constraints.as_ref())
@ -531,7 +561,7 @@ impl Painter {
}
})?;
app_state.is_resized = false;
app_state.is_force_redraw = false;
Ok(())
}

View File

View File

@ -1,4 +1,5 @@
use std::cmp::max;
use unicode_width::UnicodeWidthStr;
use tui::{
backend::Backend,
@ -7,12 +8,9 @@ use tui::{
widgets::{Block, Borders, Paragraph},
};
use crate::{
app::{App, AppHelpCategory},
canvas::Painter,
};
use crate::{app::App, canvas::Painter, constants};
const HELP_BASE: &str = " Help ── 1: General ─── 2: Processes ─── 3: Search ─── Esc to close ";
const HELP_BASE: &str = " Help ── Esc to close ";
pub trait HelpDialog {
fn draw_help_dialog<B: Backend>(
@ -28,31 +26,121 @@ impl HelpDialog for Painter {
0,
draw_loc.width as i32 - HELP_BASE.chars().count() as i32 - 2,
);
let help_title = format!(
" Help ─{}─ 1: General ─── 2: Processes ─── 3: Search ─── Esc to close ",
"".repeat(repeat_num as usize)
);
let help_title = format!(" Help ─{}─ Esc to close ", "".repeat(repeat_num as usize));
if app_state.is_force_redraw {
// We must also recalculate how many lines are wrapping to properly get scrolling to work on
// small terminal sizes... oh joy.
// TODO: Make this more automated and easier to add.
let mut overflow_buffer = 0;
let paragraph_width = draw_loc.width - 2;
constants::HELP_CONTENTS_TEXT.iter().for_each(|text_line| {
overflow_buffer +=
UnicodeWidthStr::width(*text_line).saturating_sub(1) as u16 / paragraph_width;
});
// General
app_state.help_dialog_state.general_index =
constants::HELP_CONTENTS_TEXT.len() as u16 + 1 + overflow_buffer;
constants::GENERAL_HELP_TEXT.iter().for_each(|text_line| {
overflow_buffer +=
UnicodeWidthStr::width(*text_line).saturating_sub(1) as u16 / paragraph_width;
});
// CPU
app_state.help_dialog_state.cpu_index =
(constants::HELP_CONTENTS_TEXT.len() + constants::GENERAL_HELP_TEXT.len()) as u16
+ 2
+ overflow_buffer;
constants::CPU_HELP_TEXT.iter().for_each(|text_line| {
overflow_buffer +=
UnicodeWidthStr::width(*text_line).saturating_sub(1) as u16 / paragraph_width;
});
// Processes
app_state.help_dialog_state.process_index = (constants::HELP_CONTENTS_TEXT.len()
+ constants::GENERAL_HELP_TEXT.len()
+ constants::CPU_HELP_TEXT.len())
as u16
+ 3
+ overflow_buffer;
constants::PROCESS_HELP_TEXT.iter().for_each(|text_line| {
overflow_buffer +=
UnicodeWidthStr::width(*text_line).saturating_sub(1) as u16 / paragraph_width;
});
// Search
app_state.help_dialog_state.search_index = (constants::HELP_CONTENTS_TEXT.len()
+ constants::GENERAL_HELP_TEXT.len()
+ constants::CPU_HELP_TEXT.len()
+ constants::PROCESS_HELP_TEXT.len())
as u16
+ 4
+ overflow_buffer;
constants::SEARCH_HELP_TEXT.iter().for_each(|text_line| {
overflow_buffer +=
UnicodeWidthStr::width(*text_line).saturating_sub(1) as u16 / paragraph_width;
});
// Battery
app_state.help_dialog_state.battery_index = (constants::HELP_CONTENTS_TEXT.len()
+ constants::GENERAL_HELP_TEXT.len()
+ constants::CPU_HELP_TEXT.len()
+ constants::PROCESS_HELP_TEXT.len()
+ constants::SEARCH_HELP_TEXT.len())
as u16
+ 5
+ overflow_buffer;
constants::BATTERY_HELP_TEXT.iter().for_each(|text_line| {
overflow_buffer +=
UnicodeWidthStr::width(*text_line).saturating_sub(1) as u16 / paragraph_width;
});
app_state.help_dialog_state.scroll_state.max_scroll_index =
(self.styled_help_text.len() as u16
+ (constants::NUM_CATEGORIES - 3)
+ overflow_buffer)
.saturating_sub(draw_loc.height);
// Fix if over-scrolled
if app_state
.help_dialog_state
.scroll_state
.current_scroll_index
>= app_state.help_dialog_state.scroll_state.max_scroll_index
{
app_state
.help_dialog_state
.scroll_state
.current_scroll_index = app_state
.help_dialog_state
.scroll_state
.max_scroll_index
.saturating_sub(1);
}
}
f.render_widget(
Paragraph::new(
match app_state.help_dialog_state.current_category {
AppHelpCategory::General => &self.styled_general_help_text,
AppHelpCategory::Process => &self.styled_process_help_text,
AppHelpCategory::Search => &self.styled_search_help_text,
}
.iter(),
)
.block(
Block::default()
.title(&help_title)
.title_style(self.colours.border_style)
.style(self.colours.border_style)
.borders(Borders::ALL)
.border_style(self.colours.border_style),
)
.style(self.colours.text_style)
.alignment(Alignment::Left)
.wrap(true),
Paragraph::new(self.styled_help_text.iter())
.block(
Block::default()
.title(&help_title)
.title_style(self.colours.border_style)
.style(self.colours.border_style)
.borders(Borders::ALL)
.border_style(self.colours.border_style),
)
.style(self.colours.text_style)
.alignment(Alignment::Left)
.wrap(true)
.scroll(
app_state
.help_dialog_state
.scroll_state
.current_scroll_index,
),
draw_loc,
);
}

View File

@ -1,6 +1,7 @@
use crate::app;
use itertools::izip;
// TODO: Reverse intrinsic?
/// A somewhat jury-rigged solution to simulate a variable intrinsic layout for
/// table widths. Note that this will do one main pass to try to properly
/// allocate widths. This will thus potentially cut off latter elements
@ -77,9 +78,9 @@ pub fn get_variable_intrinsic_widths(
pub fn get_search_start_position(
num_columns: usize, cursor_direction: &app::CursorDirection, cursor_bar: &mut usize,
current_cursor_position: usize, is_resized: bool,
current_cursor_position: usize, is_force_redraw: bool,
) -> usize {
if is_resized {
if is_force_redraw {
*cursor_bar = 0;
}
@ -117,9 +118,9 @@ pub fn get_search_start_position(
pub fn get_start_position(
num_rows: u64, scroll_direction: &app::ScrollDirection, scroll_position_bar: &mut u64,
currently_selected_position: u64, is_resized: bool,
currently_selected_position: u64, is_force_redraw: bool,
) -> u64 {
if is_resized {
if is_force_redraw {
*scroll_position_bar = 0;
}

View File

@ -224,7 +224,7 @@ impl CpuGraphWidget for Painter {
&cpu_widget_state.scroll_state.scroll_direction,
&mut cpu_widget_state.scroll_state.previous_scroll_position,
cpu_widget_state.scroll_state.current_scroll_position,
app_state.is_resized,
app_state.is_force_redraw,
);
let is_on_widget = widget_id == app_state.current_widget.widget_id;

View File

@ -45,7 +45,7 @@ impl DiskTableWidget for Painter {
&disk_widget_state.scroll_state.scroll_direction,
&mut disk_widget_state.scroll_state.previous_scroll_position,
disk_widget_state.scroll_state.current_scroll_position,
app_state.is_resized,
app_state.is_force_redraw,
);
let is_on_widget = app_state.current_widget.widget_id == widget_id;
let disk_table_state = &mut disk_widget_state.scroll_state.table_state;

View File

@ -91,7 +91,7 @@ impl ProcessTableWidget for Painter {
&proc_widget_state.scroll_state.scroll_direction,
&mut proc_widget_state.scroll_state.previous_scroll_position,
proc_widget_state.scroll_state.current_scroll_position,
app_state.is_resized,
app_state.is_force_redraw,
);
// Sanity check
@ -370,7 +370,7 @@ impl ProcessTableWidget for Painter {
.search_state
.cursor_bar,
current_cursor_position,
app_state.is_resized,
app_state.is_force_redraw,
);
let query = proc_widget_state.get_current_search_query().as_str();

View File

@ -46,7 +46,7 @@ impl TempTableWidget for Painter {
&temp_widget_state.scroll_state.scroll_direction,
&mut temp_widget_state.scroll_state.previous_scroll_position,
temp_widget_state.scroll_state.current_scroll_position,
app_state.is_resized,
app_state.is_force_redraw,
);
let is_on_widget = widget_id == app_state.current_widget.widget_id;
let temp_table_state = &mut temp_widget_state.scroll_state.table_state;

View File

@ -36,52 +36,76 @@ lazy_static! {
}
// Help text
pub const NUM_CATEGORIES: u16 = 6;
pub const HELP_CONTENTS_TEXT: [&str; 6] = [
"Press the corresponding numbers to jump to the section, or scroll:\n",
"1 - General bindings\n",
"2 - CPU bindings\n",
"3 - Process bindings\n",
"4 - Process search bindings\n",
"5 - Battery bindings",
];
pub const GENERAL_HELP_TEXT: [&str; 18] = [
"General Keybindings\n\n",
"q, Ctrl-c Quit bottom\n",
"Esc Close filters, dialog boxes, etc.\n",
"Ctrl-r Reset all data\n",
"f Freeze display\n",
"Ctrl-Arrow Change your selected widget\n",
"Shift-Arrow Change your selected widget\n",
"H/J/K/L Change your selected widget up/down/left/right\n",
"Up, k Move cursor up\n",
"Down, j Move cursor down\n",
"? Open the help screen\n",
"gg Skip to the first entry of a list\n",
"G Skip to the last entry of a list\n",
"1 - General bindings\n",
"q, Ctrl-c Quit\n",
"Esc Close dialog windows, search, widgets, or exit maximized mode\n",
"Ctrl-r Reset display and any collected data\n",
"f Freeze/unfreeze updating with new data\n",
"Ctrl-Arrow \n",
"Shift-Arrow Move to a different widget\n",
"H/J/K/L \n",
"Up, k Scroll up\n",
"Down, j Scroll down\n",
"? Open help menu\n",
"gg Jump to the first entry\n",
"G Jump to the last entry\n",
"Enter Maximize the currently selected widget\n",
"/ Filter out graph lines (only CPU at the moment)\n",
"+ Zoom in (decrease time range)\n",
"- Zoom out (increase time range)\n",
"+ Zoom in on chart (decrease time range)\n",
"- Zoom out on chart (increase time range)\n",
"= Reset zoom\n",
"Mouse scroll Scroll through the tables or zoom in/out of charts by scrolling up/down",
];
pub const CPU_HELP_TEXT: [&str; 4] = [
"2 - CPU bindings\n",
"/ Open filtering for showing certain CPU cores\n",
"Space Toggle enabled/disabled cores\n",
"Esc Exit filtering mode",
];
pub const PROCESS_HELP_TEXT: [&str; 8] = [
"Process Keybindings\n\n",
"dd, Delete Kill the highlighted process\n",
"c Sort by CPU usage\n",
"3 - Process bindings\n",
"dd Kill the selected process\n",
"c Sort by memory usage, press again to reverse sorting order\n",
"m Sort by memory usage\n",
"p Sort by PID\n",
"n Sort by process name\n",
"Tab Group together processes with the same name\n",
"Ctrl-f, / Open up the search widget\n",
"p Sort by PID name, press again to reverse sorting order\n",
"n Sort by process name, press again to reverse sorting order\n",
"Tab Group/un-group processes with the same name\n",
"Ctrl-f, / Open process search widget",
];
pub const SEARCH_HELP_TEXT: [&str; 13] = [
"Search Keybindings\n\n",
"Tab Toggle between searching for PID and name.\n",
"Esc Close search widget\n",
"Ctrl-a Skip to the start of search widget\n",
"Ctrl-e Skip to the end of search widget\n",
"4 - Process search bindings\n",
"Tab Toggle between searching for PID and name\n",
"Esc Close the search widget (retains the filter)\n",
"Ctrl-a Skip to the start of the search query\n",
"Ctrl-e Skip to the end of the search query\n",
"Ctrl-u Clear the current search query\n",
"Backspace Delete the character behind the cursor\n",
"Delete Delete the character at the cursor\n",
"Alt-c/F1 Toggle matching case\n",
"Alt-w/F2 Toggle matching the entire word\n",
"Alt-r/F3 Toggle using regex\n",
"Left Move cursor left\n",
"Right Move cursor right\n",
"Alt-c/F1 Toggle whether to ignore case\n",
"Alt-w/F2 Toggle whether to match the whole word\n",
"Alt-r/F3 Toggle whether to use regex\n",
"Right Move cursor right",
];
pub const BATTERY_HELP_TEXT: [&str; 3] = [
"5 - Battery bindings\n",
"Left Go to previous battery\n",
"Right Go to next battery",
];
// Config and flags

View File

@ -114,17 +114,6 @@ fn main() -> error::Result<()> {
painter.colours.generate_remaining_cpu_colours();
painter.complete_painter_init();
// Set up up tui and crossterm
let mut stdout_val = stdout();
execute!(stdout_val, EnterAlternateScreen, EnableMouseCapture)?;
enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout_val))?;
terminal.hide_cursor()?;
// Set panic hook
panic::set_hook(Box::new(|info| panic_hook(info)));
// Set up input handling
let (tx, rx) = mpsc::channel();
create_input_thread(tx.clone());
@ -151,6 +140,17 @@ fn main() -> error::Result<()> {
app.used_widgets.clone(),
);
// Set up up tui and crossterm
let mut stdout_val = stdout();
execute!(stdout_val, EnterAlternateScreen, EnableMouseCapture)?;
enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout_val))?;
terminal.hide_cursor()?;
// Set panic hook
panic::set_hook(Box::new(|info| panic_hook(info)));
let mut first_run = true;
loop {
if let Ok(recv) = rx.recv_timeout(Duration::from_millis(TICK_RATE_IN_MILLISECONDS)) {