Merge pull request #34 from ClementTsang/alternate_alt_macos

Colours if selected and F1-3 keys for search options
This commit is contained in:
Clement Tsang 2020-02-25 22:22:43 -05:00 committed by GitHub
commit cdf464f323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 134 additions and 70 deletions

View File

@ -29,7 +29,6 @@ script:
- cargo clippy -- -D clippy::all - cargo clippy -- -D clippy::all
- cargo build --verbose --target $TARGET - cargo build --verbose --target $TARGET
- cargo test --verbose --target $TARGET - cargo test --verbose --target $TARGET
- cargo install --target $TARGET
# Need to cache the whole `.cargo` directory to keep .crates.toml for cargo-update to work # Need to cache the whole `.cargo` directory to keep .crates.toml for cargo-update to work
cache: cache:
@ -46,6 +45,7 @@ notifications:
on_success: never on_success: never
before_deploy: before_deploy:
- cargo install --path . --target $TARGET
- | - |
if [[ $TRAVIS_OS_NAME == "windows" ]]; then if [[ $TRAVIS_OS_NAME == "windows" ]]; then
choco install zip; choco install zip;

View File

@ -184,11 +184,11 @@ Run using `btm`.
- `Left` and `Right` arrow keys to move the cursor within the search bar. - `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. Note that `q` is disabled while in the search widget.

View File

@ -106,15 +106,15 @@ impl Default for ProcessSearchState {
} }
impl 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; 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; 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; 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 &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) { pub fn update_regex(&mut self) {
if self if self
.process_search_state .process_search_state

View File

@ -97,6 +97,7 @@ pub struct Painter {
pub styled_general_help_text: Vec<Text<'static>>, pub styled_general_help_text: Vec<Text<'static>>,
pub styled_process_help_text: Vec<Text<'static>>, pub styled_process_help_text: Vec<Text<'static>>,
pub styled_search_help_text: Vec<Text<'static>>, pub styled_search_help_text: Vec<Text<'static>>,
is_mac_os: bool,
} }
impl Painter { impl Painter {
@ -106,6 +107,8 @@ impl Painter {
/// assumes that you, the programmer, are sane and do not do stupid things. /// assumes that you, the programmer, are sane and do not do stupid things.
/// RIGHT? /// RIGHT?
pub fn initialize(&mut self) { pub fn initialize(&mut self) {
self.is_mac_os = cfg!(target_os = "macos");
self.styled_general_help_text.push(Text::Styled( self.styled_general_help_text.push(Text::Styled(
GENERAL_HELP_TEXT[0].into(), GENERAL_HELP_TEXT[0].into(),
self.colours.table_header_style, self.colours.table_header_style,
@ -1222,27 +1225,60 @@ impl Painter {
option_text.push(Text::raw("\n")); option_text.push(Text::raw("\n"));
} }
let option_row = vec![ let case_style = if !app_state.process_search_state.is_ignoring_case {
Text::styled("Match Case (Alt+C)", self.colours.table_header_style), 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 { if !app_state.process_search_state.is_ignoring_case {
Text::styled("[*]", self.colours.table_header_style) "*"
} else { } 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 { if app_state.process_search_state.is_searching_whole_word {
Text::styled("[*]", self.colours.table_header_style) "*"
} else { } 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 { if app_state.process_search_state.is_searching_with_regex {
Text::styled("[*]", self.colours.table_header_style) "*"
} else { } 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); 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", "Delete Delete the character at the cursor\n",
"Left Move cursor left\n", "Left Move cursor left\n",
"Right Move cursor right\n", "Right Move cursor right\n",
"Alt-c Toggle whether to ignore case\n", "Alt-c/F1 Toggle whether to ignore case\n",
"Alt-m Toggle whether to match the whole word\n", "Alt-w/F2 Toggle whether to match the whole word\n",
"Alt-r Toggle whether to use regex\n", "Alt-r/F3 Toggle whether to use regex\n",
]; ];

View File

@ -42,7 +42,10 @@ mod canvas;
mod constants; mod constants;
mod data_conversion; mod data_conversion;
use app::data_harvester::{self, processes::ProcessSorting}; use app::{
data_harvester::{self, processes::ProcessSorting},
App,
};
use constants::*; use constants::*;
use data_conversion::*; use data_conversion::*;
use utils::error::{self, BottomError}; use utils::error::{self, BottomError};
@ -155,7 +158,7 @@ fn main() -> error::Result<()> {
let show_disabled_data = get_show_disabled_data_option(&matches, &config); 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 // 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, show_average_cpu,
temperature_type, temperature_type,
update_rate_in_milliseconds as u64, update_rate_in_milliseconds as u64,
@ -301,7 +304,7 @@ fn main() -> error::Result<()> {
Ok(()) Ok(())
} }
fn handle_mouse_event(event: MouseEvent, app: &mut app::App) { fn handle_mouse_event(event: MouseEvent, app: &mut App) {
match event { match event {
MouseEvent::ScrollUp(_x, _y, _modifiers) => app.decrement_position_count(), MouseEvent::ScrollUp(_x, _y, _modifiers) => app.decrement_position_count(),
MouseEvent::ScrollDown(_x, _y, _modifiers) => app.increment_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( 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 { ) -> bool {
if event.modifiers.is_empty() { if event.modifiers.is_empty() {
// Required catch for searching - otherwise you couldn't search with q. // 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::Tab => app.on_tab(),
KeyCode::Backspace => app.on_backspace(), KeyCode::Backspace => app.on_backspace(),
KeyCode::Delete => app.on_delete(), 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 { } else {
// Otherwise, track the modifier as well... // 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') { if event.code == KeyCode::Char('c') {
return true; return true;
} }
@ -367,31 +404,6 @@ fn handle_key_event_or_break(
KeyCode::Char(caught_char) => app.on_char_key(caught_char), 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 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") { if matches.is_present("GROUP_PROCESSES") {
app.toggle_grouping(); app.toggle_grouping();
} else if let Some(flags) = &config.flags { } 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( fn enable_app_case_sensitive(matches: &clap::ArgMatches<'static>, config: &Config, app: &mut App) {
matches: &clap::ArgMatches<'static>, config: &Config, app: &mut app::App,
) {
if matches.is_present("CASE_SENSITIVE") { 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 { } else if let Some(flags) = &config.flags {
if let Some(case_sensitive) = flags.case_sensitive { if let Some(case_sensitive) = flags.case_sensitive {
if 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( 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") { 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 { } else if let Some(flags) = &config.flags {
if let Some(whole_word) = flags.whole_word { if let Some(whole_word) = flags.whole_word {
if 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") { 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 { } else if let Some(flags) = &config.flags {
if let Some(regex) = flags.regex { if let Some(regex) = flags.regex {
if 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( fn try_drawing(
terminal: &mut tui::terminal::Terminal<tui::backend::CrosstermBackend<std::io::Stdout>>, 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<()> { ) -> error::Result<()> {
if let Err(err) = painter.draw_data(terminal, app) { if let Err(err) = painter.draw_data(terminal, app) {
cleanup_terminal(terminal)?; cleanup_terminal(terminal)?;
@ -777,7 +787,7 @@ fn panic_hook(panic_info: &PanicInfo<'_>) {
.unwrap(); .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() { let mut filtered_process_data: Vec<ConvertedProcessData> = if app.is_grouped() {
app.canvas_data app.canvas_data
.grouped_process_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; 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)); to_sort_vec.sort_by(|a, b| utils::gen_util::get_ordering(&a.name, &b.name, false));
match app.process_sorting_type { match app.process_sorting_type {