Colours if selected and F1-3 keys for search options

Added different colours to search options if selected; added F1-3 keys as an alternative for searching.  Both are available, but on macOS F1-3 will be suggested instead.
This commit is contained in:
ClementTsang 2020-02-25 21:24:26 -05:00
parent 46b695d575
commit 0660184099
5 changed files with 133 additions and 69 deletions

View file

@ -184,11 +184,11 @@ Run using `btm`.
- `Left` and `Right` arrow keys to move the cursor within the search bar.
- `Alt-c` to toggle ignoring case.
- `Alt-c/F1` to toggle ignoring case.
- `Alt-m` to toggle matching the entire word.
- `Alt-w/F2` to toggle matching the entire word.
- `Alt-r` to toggle using regex.
- `Alt-r/F3` to toggle using regex.
Note that `q` is disabled while in the search widget.

View file

@ -106,15 +106,15 @@ impl Default for ProcessSearchState {
}
impl ProcessSearchState {
pub fn toggle_ignore_case(&mut self) {
pub fn search_toggle_ignore_case(&mut self) {
self.is_ignoring_case = !self.is_ignoring_case;
}
pub fn toggle_search_whole_word(&mut self) {
pub fn search_toggle_whole_word(&mut self) {
self.is_searching_whole_word = !self.is_searching_whole_word;
}
pub fn toggle_search_regex(&mut self) {
pub fn search_toggle_regex(&mut self) {
self.is_searching_with_regex = !self.is_searching_with_regex;
}
}
@ -463,6 +463,24 @@ impl App {
&self.process_search_state.search_state.current_search_query
}
pub fn toggle_ignore_case(&mut self) {
self.process_search_state.search_toggle_ignore_case();
self.update_regex();
self.update_process_gui = true;
}
pub fn toggle_search_whole_word(&mut self) {
self.process_search_state.search_toggle_whole_word();
self.update_regex();
self.update_process_gui = true;
}
pub fn toggle_search_regex(&mut self) {
self.process_search_state.search_toggle_regex();
self.update_regex();
self.update_process_gui = true;
}
pub fn update_regex(&mut self) {
if self
.process_search_state

View file

@ -97,6 +97,7 @@ pub struct Painter {
pub styled_general_help_text: Vec<Text<'static>>,
pub styled_process_help_text: Vec<Text<'static>>,
pub styled_search_help_text: Vec<Text<'static>>,
is_mac_os: bool,
}
impl Painter {
@ -106,6 +107,8 @@ impl Painter {
/// assumes that you, the programmer, are sane and do not do stupid things.
/// RIGHT?
pub fn initialize(&mut self) {
self.is_mac_os = cfg!(target_os = "macos");
self.styled_general_help_text.push(Text::Styled(
GENERAL_HELP_TEXT[0].into(),
self.colours.table_header_style,
@ -1222,27 +1225,60 @@ impl Painter {
option_text.push(Text::raw("\n"));
}
let option_row = vec![
Text::styled("Match Case (Alt+C)", self.colours.table_header_style),
let case_style = if !app_state.process_search_state.is_ignoring_case {
self.colours.currently_selected_text_style
} else {
self.colours.text_style
};
let whole_word_style = if app_state.process_search_state.is_searching_whole_word {
self.colours.currently_selected_text_style
} else {
self.colours.text_style
};
let regex_style = if app_state.process_search_state.is_searching_with_regex {
self.colours.currently_selected_text_style
} else {
self.colours.text_style
};
let case_text = format!(
"Match Case ({})[{}]",
if self.is_mac_os { "F1" } else { "Alt+C" },
if !app_state.process_search_state.is_ignoring_case {
Text::styled("[*]", self.colours.table_header_style)
"*"
} else {
Text::styled("[ ]", self.colours.table_header_style)
},
Text::styled(" ", self.colours.table_header_style),
Text::styled("Match Whole Word (Alt+W)", self.colours.table_header_style),
" "
}
);
let whole_text = format!(
"Match Whole Word ({})[{}]",
if self.is_mac_os { "F2" } else { "Alt+W" },
if app_state.process_search_state.is_searching_whole_word {
Text::styled("[*]", self.colours.table_header_style)
"*"
} else {
Text::styled("[ ]", self.colours.table_header_style)
},
Text::styled(" ", self.colours.table_header_style),
Text::styled("Use Regex (Alt+R)", self.colours.table_header_style),
" "
}
);
let regex_text = format!(
"Use Regex ({})[{}]",
if self.is_mac_os { "F3" } else { "Alt+R" },
if app_state.process_search_state.is_searching_with_regex {
Text::styled("[*]", self.colours.table_header_style)
"*"
} else {
Text::styled("[ ]", self.colours.table_header_style)
},
" "
}
);
let option_row = vec![
Text::styled(&case_text, case_style),
Text::raw(" "),
Text::styled(&whole_text, whole_word_style),
Text::raw(" "),
Text::styled(&regex_text, regex_style),
];
option_text.extend(option_row);

View file

@ -50,7 +50,7 @@ pub const SEARCH_HELP_TEXT: [&str; 13] = [
"Delete Delete the character at the cursor\n",
"Left Move cursor left\n",
"Right Move cursor right\n",
"Alt-c Toggle whether to ignore case\n",
"Alt-m Toggle whether to match the whole word\n",
"Alt-r Toggle whether to use regex\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",
];

View file

@ -42,7 +42,10 @@ mod canvas;
mod constants;
mod data_conversion;
use app::data_harvester::{self, processes::ProcessSorting};
use app::{
data_harvester::{self, processes::ProcessSorting},
App,
};
use constants::*;
use data_conversion::*;
use utils::error::{self, BottomError};
@ -155,7 +158,7 @@ fn main() -> error::Result<()> {
let show_disabled_data = get_show_disabled_data_option(&matches, &config);
// Create "app" struct, which will control most of the program and store settings/state
let mut app = app::App::new(
let mut app = App::new(
show_average_cpu,
temperature_type,
update_rate_in_milliseconds as u64,
@ -301,7 +304,7 @@ fn main() -> error::Result<()> {
Ok(())
}
fn handle_mouse_event(event: MouseEvent, app: &mut app::App) {
fn handle_mouse_event(event: MouseEvent, app: &mut App) {
match event {
MouseEvent::ScrollUp(_x, _y, _modifiers) => app.decrement_position_count(),
MouseEvent::ScrollDown(_x, _y, _modifiers) => app.increment_position_count(),
@ -310,7 +313,7 @@ fn handle_mouse_event(event: MouseEvent, app: &mut app::App) {
}
fn handle_key_event_or_break(
event: KeyEvent, app: &mut app::App, rtx: &std::sync::mpsc::Sender<ResetEvent>,
event: KeyEvent, app: &mut App, rtx: &std::sync::mpsc::Sender<ResetEvent>,
) -> bool {
if event.modifiers.is_empty() {
// Required catch for searching - otherwise you couldn't search with q.
@ -331,11 +334,45 @@ fn handle_key_event_or_break(
KeyCode::Tab => app.on_tab(),
KeyCode::Backspace => app.on_backspace(),
KeyCode::Delete => app.on_delete(),
KeyCode::F(1) => {
if app.is_in_search_widget() {
app.toggle_ignore_case();
}
}
KeyCode::F(2) => {
if app.is_in_search_widget() {
app.toggle_search_whole_word();
}
}
KeyCode::F(3) => {
if app.is_in_search_widget() {
app.toggle_search_regex();
}
}
_ => {}
}
} else {
// Otherwise, track the modifier as well...
if let KeyModifiers::CONTROL = event.modifiers {
if let KeyModifiers::ALT = event.modifiers {
match event.code {
KeyCode::Char('c') | KeyCode::Char('C') => {
if app.is_in_search_widget() {
app.toggle_ignore_case();
}
}
KeyCode::Char('w') | KeyCode::Char('W') => {
if app.is_in_search_widget() {
app.toggle_search_whole_word();
}
}
KeyCode::Char('r') | KeyCode::Char('R') => {
if app.is_in_search_widget() {
app.toggle_search_regex();
}
}
_ => {}
}
} else if let KeyModifiers::CONTROL = event.modifiers {
if event.code == KeyCode::Char('c') {
return true;
}
@ -367,31 +404,6 @@ fn handle_key_event_or_break(
KeyCode::Char(caught_char) => app.on_char_key(caught_char),
_ => {}
}
} else if let KeyModifiers::ALT = event.modifiers {
match event.code {
KeyCode::Char('c') | KeyCode::Char('C') => {
if app.is_in_search_widget() {
app.process_search_state.toggle_ignore_case();
app.update_regex();
app.update_process_gui = true;
}
}
KeyCode::Char('w') | KeyCode::Char('W') => {
if app.is_in_search_widget() {
app.process_search_state.toggle_search_whole_word();
app.update_regex();
app.update_process_gui = true;
}
}
KeyCode::Char('r') | KeyCode::Char('R') => {
if app.is_in_search_widget() {
app.process_search_state.toggle_search_regex();
app.update_regex();
app.update_process_gui = true;
}
}
_ => {}
}
}
}
@ -554,7 +566,7 @@ fn get_show_disabled_data_option(matches: &clap::ArgMatches<'static>, config: &C
false
}
fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App) {
fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("GROUP_PROCESSES") {
app.toggle_grouping();
} else if let Some(flags) = &config.flags {
@ -566,41 +578,39 @@ fn enable_app_grouping(matches: &clap::ArgMatches<'static>, config: &Config, app
}
}
fn enable_app_case_sensitive(
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App,
) {
fn enable_app_case_sensitive(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("CASE_SENSITIVE") {
app.process_search_state.toggle_ignore_case();
app.process_search_state.search_toggle_ignore_case();
} else if let Some(flags) = &config.flags {
if let Some(case_sensitive) = flags.case_sensitive {
if case_sensitive {
app.process_search_state.toggle_ignore_case();
app.process_search_state.search_toggle_ignore_case();
}
}
}
}
fn enable_app_match_whole_word(
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App,
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App,
) {
if matches.is_present("WHOLE_WORD") {
app.process_search_state.toggle_search_whole_word();
app.process_search_state.search_toggle_whole_word();
} else if let Some(flags) = &config.flags {
if let Some(whole_word) = flags.whole_word {
if whole_word {
app.process_search_state.toggle_search_whole_word();
app.process_search_state.search_toggle_whole_word();
}
}
}
}
fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App) {
fn enable_app_use_regex(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
if matches.is_present("REGEX_DEFAULT") {
app.process_search_state.toggle_search_regex();
app.process_search_state.search_toggle_regex();
} else if let Some(flags) = &config.flags {
if let Some(regex) = flags.regex {
if regex {
app.process_search_state.toggle_search_regex();
app.process_search_state.search_toggle_regex();
}
}
}
@ -650,7 +660,7 @@ fn get_default_widget(matches: &clap::ArgMatches<'static>, config: &Config) -> a
fn try_drawing(
terminal: &mut tui::terminal::Terminal<tui::backend::CrosstermBackend<std::io::Stdout>>,
app: &mut app::App, painter: &mut canvas::Painter,
app: &mut App, painter: &mut canvas::Painter,
) -> error::Result<()> {
if let Err(err) = painter.draw_data(terminal, app) {
cleanup_terminal(terminal)?;
@ -777,7 +787,7 @@ fn panic_hook(panic_info: &PanicInfo<'_>) {
.unwrap();
}
fn update_final_process_list(app: &mut app::App) {
fn update_final_process_list(app: &mut App) {
let mut filtered_process_data: Vec<ConvertedProcessData> = if app.is_grouped() {
app.canvas_data
.grouped_process_data
@ -841,7 +851,7 @@ fn update_final_process_list(app: &mut app::App) {
app.canvas_data.finalized_process_data = filtered_process_data;
}
fn sort_process_data(to_sort_vec: &mut Vec<ConvertedProcessData>, app: &app::App) {
fn sort_process_data(to_sort_vec: &mut Vec<ConvertedProcessData>, app: &App) {
to_sort_vec.sort_by(|a, b| utils::gen_util::get_ordering(&a.name, &b.name, false));
match app.process_sorting_type {