diff --git a/Cargo.lock b/Cargo.lock index 26f00149..add57641 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -317,9 +317,9 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.23.2" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" dependencies = [ "bitflags", "crossterm_winapi", @@ -1638,9 +1638,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tui" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe69244ec2af261bced1d9046a6fee6c8c2a6b0228e59e5ba39bc8ba4ed729" +checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" dependencies = [ "bitflags", "cassowary", diff --git a/Cargo.toml b/Cargo.toml index 7a20cf12..2254e5c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ bytesize = { version = "1.1", default-features = false } chrono = { version = "0.4", default-features = false, features = [ "clock" ] } clap = { version = "3.2", features = [ "env", "cargo" ] } crossbeam-channel = "0.5" -crossterm = { version = "0.23", features = [ "serde" ] } +crossterm = { version = "0.25", features = [ "serde" ] } dirs-next = "2.0" easy-cast = "0.4" filetreelist = { path = "./filetreelist", version = "0.5" } @@ -46,7 +46,7 @@ serde = "1.0" simplelog = { version = "0.12", default-features = false } syntect = { version = "5.0", default-features = false, features = ["parsing", "default-syntaxes", "default-themes", "html", "regex-fancy"] } textwrap = "0.15" -tui = { version = "0.18", default-features = false, features = ['crossterm', 'serde'] } +tui = { version = "0.19", default-features = false, features = ['crossterm', 'serde'] } unicode-segmentation = "1.9" unicode-truncate = "0.2" unicode-width = "0.1" diff --git a/src/app.rs b/src/app.rs index 2425dd75..c00c8351 100644 --- a/src/app.rs +++ b/src/app.rs @@ -14,7 +14,7 @@ use crate::{ TagCommitComponent, TagListComponent, }, input::{Input, InputEvent, InputState}, - keys::{KeyConfig, SharedKeyConfig}, + keys::{key_match, KeyConfig, SharedKeyConfig}, popup_stack::PopupStack, queue::{ Action, InternalEvent, NeedsUpdate, Queue, StackablePopupOpen, @@ -345,38 +345,57 @@ impl App { log::trace!("event: {:?}", ev); if let InputEvent::Input(ev) = ev { - if self.check_hard_exit(ev) || self.check_quit(ev) { + if self.check_hard_exit(&ev) || self.check_quit(&ev) { return Ok(()); } let mut flags = NeedsUpdate::empty(); - if event_pump(ev, self.components_mut().as_mut_slice())? + if event_pump(&ev, self.components_mut().as_mut_slice())? .is_consumed() { flags.insert(NeedsUpdate::COMMANDS); - } else if let Event::Key(k) = ev { - let new_flags = if k - == self.key_config.keys.tab_toggle - { + } else if let Event::Key(k) = &ev { + let new_flags = if key_match( + k, + self.key_config.keys.tab_toggle, + ) { self.toggle_tabs(false)?; NeedsUpdate::COMMANDS - } else if k == self.key_config.keys.tab_toggle_reverse - { + } else if key_match( + k, + self.key_config.keys.tab_toggle_reverse, + ) { self.toggle_tabs(true)?; NeedsUpdate::COMMANDS - } else if k == self.key_config.keys.tab_status - || k == self.key_config.keys.tab_log - || k == self.key_config.keys.tab_files - || k == self.key_config.keys.tab_stashing - || k == self.key_config.keys.tab_stashes - { + } else if key_match( + k, + self.key_config.keys.tab_status, + ) || key_match( + k, + self.key_config.keys.tab_log, + ) || key_match( + k, + self.key_config.keys.tab_files, + ) || key_match( + k, + self.key_config.keys.tab_stashing, + ) || key_match( + k, + self.key_config.keys.tab_stashes, + ) { self.switch_tab(k)?; NeedsUpdate::COMMANDS - } else if k == self.key_config.keys.cmd_bar_toggle { + } else if key_match( + k, + self.key_config.keys.cmd_bar_toggle, + ) { self.cmdbar.borrow_mut().toggle_more(); NeedsUpdate::empty() - } else if k == self.key_config.keys.open_options { + } else if key_match( + k, + self.key_config.keys.open_options, + ) { self.options_popup.show()?; NeedsUpdate::ALL } else { @@ -563,12 +582,12 @@ impl App { ] ); - fn check_quit(&mut self, ev: Event) -> bool { + fn check_quit(&mut self, ev: &Event) -> bool { if self.any_popup_visible() { return false; } if let Event::Key(e) = ev { - if e == self.key_config.keys.quit { + if key_match(e, self.key_config.keys.quit) { self.do_quit = true; return true; } @@ -576,9 +595,9 @@ impl App { false } - fn check_hard_exit(&mut self, ev: Event) -> bool { + fn check_hard_exit(&mut self, ev: &Event) -> bool { if let Event::Key(e) = ev { - if e == self.key_config.keys.exit { + if key_match(e, self.key_config.keys.exit) { self.do_quit = true; return true; } @@ -607,16 +626,16 @@ impl App { self.set_tab(new_tab) } - fn switch_tab(&mut self, k: KeyEvent) -> Result<()> { - if k == self.key_config.keys.tab_status { + fn switch_tab(&mut self, k: &KeyEvent) -> Result<()> { + if key_match(k, self.key_config.keys.tab_status) { self.set_tab(0)?; - } else if k == self.key_config.keys.tab_log { + } else if key_match(k, self.key_config.keys.tab_log) { self.set_tab(1)?; - } else if k == self.key_config.keys.tab_files { + } else if key_match(k, self.key_config.keys.tab_files) { self.set_tab(2)?; - } else if k == self.key_config.keys.tab_stashing { + } else if key_match(k, self.key_config.keys.tab_stashing) { self.set_tab(3)?; - } else if k == self.key_config.keys.tab_stashes { + } else if key_match(k, self.key_config.keys.tab_stashes) { self.set_tab(4)?; } diff --git a/src/components/blame_file.rs b/src/components/blame_file.rs index 7411c297..6d7fcc74 100644 --- a/src/components/blame_file.rs +++ b/src/components/blame_file.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ components::{utils::string_width_align, ScrollType}, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, string_utils::tabs_to_spaces, strings, @@ -183,29 +183,48 @@ impl Component for BlameFileComponent { fn event( &mut self, - event: crossterm::event::Event, + event: &crossterm::event::Event, ) -> Result { if self.is_visible() { if let Event::Key(key) = event { - if key == self.key_config.keys.exit_popup { + if key_match(key, self.key_config.keys.exit_popup) { self.hide_stacked(false); - } else if key == self.key_config.keys.move_up { + } else if key_match(key, self.key_config.keys.move_up) + { self.move_selection(ScrollType::Up); - } else if key == self.key_config.keys.move_down { + } else if key_match( + key, + self.key_config.keys.move_down, + ) { self.move_selection(ScrollType::Down); - } else if key == self.key_config.keys.shift_up - || key == self.key_config.keys.home - { + } else if key_match( + key, + self.key_config.keys.shift_up, + ) || key_match( + key, + self.key_config.keys.home, + ) { self.move_selection(ScrollType::Home); - } else if key == self.key_config.keys.shift_down - || key == self.key_config.keys.end - { + } else if key_match( + key, + self.key_config.keys.shift_down, + ) || key_match( + key, + self.key_config.keys.end, + ) { self.move_selection(ScrollType::End); - } else if key == self.key_config.keys.page_down { + } else if key_match( + key, + self.key_config.keys.page_down, + ) { self.move_selection(ScrollType::PageDown); - } else if key == self.key_config.keys.page_up { + } else if key_match(key, self.key_config.keys.page_up) + { self.move_selection(ScrollType::PageUp); - } else if key == self.key_config.keys.focus_right { + } else if key_match( + key, + self.key_config.keys.focus_right, + ) { if let Some(commit_id) = self.selected_commit() { self.hide_stacked(true); self.queue.push(InternalEvent::OpenPopup( @@ -214,7 +233,10 @@ impl Component for BlameFileComponent { ), )); } - } else if key == self.key_config.keys.file_history { + } else if key_match( + key, + self.key_config.keys.file_history, + ) { if let Some(filepath) = self .params .as_ref() diff --git a/src/components/branchlist.rs b/src/components/branchlist.rs index 52b819c9..b5336ebf 100644 --- a/src/components/branchlist.rs +++ b/src/components/branchlist.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ components::ScrollType, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{ Action, InternalEvent, NeedsUpdate, Queue, StackablePopupOpen, }, @@ -212,62 +212,62 @@ impl Component for BranchListComponent { //TODO: cleanup #[allow(clippy::cognitive_complexity)] - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if !self.visible { return Ok(EventState::NotConsumed); } if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide(); - } else if e == self.key_config.keys.move_down { + } else if key_match(e, self.key_config.keys.move_down) { return self .move_selection(ScrollType::Up) .map(Into::into); - } else if e == self.key_config.keys.move_up { + } else if key_match(e, self.key_config.keys.move_up) { return self .move_selection(ScrollType::Down) .map(Into::into); - } else if e == self.key_config.keys.page_down { + } else if key_match(e, self.key_config.keys.page_down) { return self .move_selection(ScrollType::PageDown) .map(Into::into); - } else if e == self.key_config.keys.page_up { + } else if key_match(e, self.key_config.keys.page_up) { return self .move_selection(ScrollType::PageUp) .map(Into::into); - } else if e == self.key_config.keys.home { + } else if key_match(e, self.key_config.keys.home) { return self .move_selection(ScrollType::Home) .map(Into::into); - } else if e == self.key_config.keys.end { + } else if key_match(e, self.key_config.keys.end) { return self .move_selection(ScrollType::End) .map(Into::into); - } else if e == self.key_config.keys.tab_toggle { + } else if key_match(e, self.key_config.keys.tab_toggle) { self.local = !self.local; self.check_remotes(); self.update_branches()?; - } else if e == self.key_config.keys.enter { + } else if key_match(e, self.key_config.keys.enter) { try_or_popup!( self, "switch branch error:", self.switch_to_selected_branch() ); - } else if e == self.key_config.keys.create_branch + } else if key_match(e, self.key_config.keys.create_branch) && self.local { self.queue.push(InternalEvent::CreateBranch); - } else if e == self.key_config.keys.rename_branch + } else if key_match(e, self.key_config.keys.rename_branch) && self.valid_selection() { self.rename_branch(); - } else if e == self.key_config.keys.delete_branch + } else if key_match(e, self.key_config.keys.delete_branch) && !self.selection_is_cur_branch() && self.valid_selection() { self.delete_branch(); - } else if e == self.key_config.keys.merge_branch + } else if key_match(e, self.key_config.keys.merge_branch) && !self.selection_is_cur_branch() && self.valid_selection() { @@ -276,7 +276,7 @@ impl Component for BranchListComponent { "merge branch error:", self.merge_branch() ); - } else if e == self.key_config.keys.rebase_branch + } else if key_match(e, self.key_config.keys.rebase_branch) && !self.selection_is_cur_branch() && self.valid_selection() { @@ -285,12 +285,14 @@ impl Component for BranchListComponent { "rebase error:", self.rebase_branch() ); - } else if e == self.key_config.keys.move_right + } else if key_match(e, self.key_config.keys.move_right) && self.valid_selection() { self.inspect_head_of_branch(); - } else if e == self.key_config.keys.compare_commits - && self.valid_selection() + } else if key_match( + e, + self.key_config.keys.compare_commits, + ) && self.valid_selection() { self.hide(); if let Some(commit_id) = self.get_selected() { @@ -300,11 +302,14 @@ impl Component for BranchListComponent { ), )); } - } else if e == self.key_config.keys.pull + } else if key_match(e, self.key_config.keys.pull) && !self.local && self.has_remotes { self.queue.push(InternalEvent::FetchRemotes); - } else if e == self.key_config.keys.cmd_bar_toggle { + } else if key_match( + e, + self.key_config.keys.cmd_bar_toggle, + ) { //do not consume if its the more key return Ok(EventState::NotConsumed); } diff --git a/src/components/changes.rs b/src/components/changes.rs index 35996392..ca3df299 100644 --- a/src/components/changes.rs +++ b/src/components/changes.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ components::{CommandInfo, Component, EventState}, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem}, strings, try_or_popup, ui::style::SharedTheme, @@ -256,15 +256,17 @@ impl Component for ChangesComponent { CommandBlocking::PassingOn } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.files.event(ev)?.is_consumed() { return Ok(EventState::Consumed); } if self.focused() { if let Event::Key(e) = ev { - return if e == self.key_config.keys.stage_unstage_item - { + return if key_match( + e, + self.key_config.keys.stage_unstage_item, + ) { try_or_popup!( self, "staging error:", @@ -275,8 +277,10 @@ impl Component for ChangesComponent { NeedsUpdate::ALL, )); Ok(EventState::Consumed) - } else if e == self.key_config.keys.status_stage_all - && !self.is_empty() + } else if key_match( + e, + self.key_config.keys.status_stage_all, + ) && !self.is_empty() { if self.is_working_dir { try_or_popup!( @@ -290,12 +294,16 @@ impl Component for ChangesComponent { self.queue .push(InternalEvent::StatusLastFileMoved); Ok(EventState::Consumed) - } else if e == self.key_config.keys.status_reset_item - && self.is_working_dir + } else if key_match( + e, + self.key_config.keys.status_reset_item, + ) && self.is_working_dir { Ok(self.dispatch_reset_workdir().into()) - } else if e == self.key_config.keys.status_ignore_file - && self.is_working_dir + } else if key_match( + e, + self.key_config.keys.status_ignore_file, + ) && self.is_working_dir && !self.is_empty() { Ok(self.add_to_ignore().into()) diff --git a/src/components/commit.rs b/src/components/commit.rs index e783e794..5128d99c 100644 --- a/src/components/commit.rs +++ b/src/components/commit.rs @@ -4,7 +4,7 @@ use super::{ EventState, ExternalEditorComponent, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, try_or_popup, ui::style::SharedTheme, @@ -333,14 +333,14 @@ impl Component for CommitComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if self.input.event(ev)?.is_consumed() { return Ok(EventState::Consumed); } if let Event::Key(e) = ev { - if e == self.key_config.keys.enter + if key_match(e, self.key_config.keys.enter) && self.can_commit() { try_or_popup!( @@ -348,12 +348,16 @@ impl Component for CommitComponent { "commit error:", self.commit() ); - } else if e == self.key_config.keys.commit_amend - && self.can_amend() + } else if key_match( + e, + self.key_config.keys.commit_amend, + ) && self.can_amend() { self.amend()?; - } else if e == self.key_config.keys.open_commit_editor - { + } else if key_match( + e, + self.key_config.keys.open_commit_editor, + ) { self.queue.push( InternalEvent::OpenExternalEditor(None), ); diff --git a/src/components/commit_details/compare_details.rs b/src/components/commit_details/compare_details.rs index 1e045e9b..c993b8d1 100644 --- a/src/components/commit_details/compare_details.rs +++ b/src/components/commit_details/compare_details.rs @@ -161,7 +161,7 @@ impl Component for CompareDetailsComponent { CommandBlocking::PassingOn } - fn event(&mut self, _event: Event) -> Result { + fn event(&mut self, _event: &Event) -> Result { Ok(EventState::NotConsumed) } diff --git a/src/components/commit_details/details.rs b/src/components/commit_details/details.rs index 0b0e99c3..83430a28 100644 --- a/src/components/commit_details/details.rs +++ b/src/components/commit_details/details.rs @@ -6,7 +6,7 @@ use crate::{ CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, ScrollType, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, strings::{self, order}, ui::style::SharedTheme, }; @@ -357,24 +357,31 @@ impl Component for DetailsComponent { CommandBlocking::PassingOn } - fn event(&mut self, event: Event) -> Result { + fn event(&mut self, event: &Event) -> Result { if self.focused { if let Event::Key(e) = event { - return Ok(if e == self.key_config.keys.move_up { - self.move_scroll_top(ScrollType::Up).into() - } else if e == self.key_config.keys.move_down { - self.move_scroll_top(ScrollType::Down).into() - } else if e == self.key_config.keys.home - || e == self.key_config.keys.shift_up - { - self.move_scroll_top(ScrollType::Home).into() - } else if e == self.key_config.keys.end - || e == self.key_config.keys.shift_down - { - self.move_scroll_top(ScrollType::End).into() - } else { - EventState::NotConsumed - }); + return Ok( + if key_match(e, self.key_config.keys.move_up) { + self.move_scroll_top(ScrollType::Up).into() + } else if key_match( + e, + self.key_config.keys.move_down, + ) { + self.move_scroll_top(ScrollType::Down).into() + } else if key_match(e, self.key_config.keys.home) + || key_match(e, self.key_config.keys.shift_up) + { + self.move_scroll_top(ScrollType::Home).into() + } else if key_match(e, self.key_config.keys.end) + || key_match( + e, + self.key_config.keys.shift_down, + ) { + self.move_scroll_top(ScrollType::End).into() + } else { + EventState::NotConsumed + }, + ); } } diff --git a/src/components/commit_details/mod.rs b/src/components/commit_details/mod.rs index 7cf356b2..6c57bd38 100644 --- a/src/components/commit_details/mod.rs +++ b/src/components/commit_details/mod.rs @@ -7,7 +7,10 @@ use super::{ Component, DrawableComponent, EventState, StatusTreeComponent, }; use crate::{ - accessors, keys::SharedKeyConfig, queue::Queue, strings, + accessors, + keys::{key_match, SharedKeyConfig}, + queue::Queue, + strings, ui::style::SharedTheme, }; use anyhow::Result; @@ -215,7 +218,7 @@ impl Component for CommitDetailsComponent { CommandBlocking::PassingOn } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if event_pump(ev, self.components_mut().as_mut_slice())? .is_consumed() { @@ -228,14 +231,18 @@ impl Component for CommitDetailsComponent { if self.focused() { if let Event::Key(e) = ev { - return if e == self.key_config.keys.focus_below - && self.details_focused() + return if key_match( + e, + self.key_config.keys.focus_below, + ) && self.details_focused() { self.set_details_focus(false); self.file_tree.focus(true); Ok(EventState::Consumed) - } else if e == self.key_config.keys.focus_above - && self.file_tree.focused() + } else if key_match( + e, + self.key_config.keys.focus_above, + ) && self.file_tree.focused() && !self.is_compare() { self.file_tree.focus(false); diff --git a/src/components/commitlist.rs b/src/components/commitlist.rs index 7ef6cc0e..ed7a6961 100644 --- a/src/components/commitlist.rs +++ b/src/components/commitlist.rs @@ -4,7 +4,7 @@ use crate::{ utils::string_width_align, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, ScrollType, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, strings::{self, symbol}, ui::style::{SharedTheme, Theme}, ui::{calc_scroll_top, draw_scrollbar}, @@ -426,26 +426,33 @@ impl DrawableComponent for CommitList { } impl Component for CommitList { - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if let Event::Key(k) = ev { let selection_changed = - if k == self.key_config.keys.move_up { + if key_match(k, self.key_config.keys.move_up) { self.move_selection(ScrollType::Up)? - } else if k == self.key_config.keys.move_down { + } else if key_match(k, self.key_config.keys.move_down) + { self.move_selection(ScrollType::Down)? - } else if k == self.key_config.keys.shift_up - || k == self.key_config.keys.home + } else if key_match(k, self.key_config.keys.shift_up) + || key_match(k, self.key_config.keys.home) { self.move_selection(ScrollType::Home)? - } else if k == self.key_config.keys.shift_down - || k == self.key_config.keys.end + } else if key_match( + k, + self.key_config.keys.shift_down, + ) || key_match(k, self.key_config.keys.end) { self.move_selection(ScrollType::End)? - } else if k == self.key_config.keys.page_up { + } else if key_match(k, self.key_config.keys.page_up) { self.move_selection(ScrollType::PageUp)? - } else if k == self.key_config.keys.page_down { + } else if key_match(k, self.key_config.keys.page_down) + { self.move_selection(ScrollType::PageDown)? - } else if k == self.key_config.keys.log_mark_commit { + } else if key_match( + k, + self.key_config.keys.log_mark_commit, + ) { self.mark(); true } else { diff --git a/src/components/compare_commits.rs b/src/components/compare_commits.rs index 7944c4b5..97375ff4 100644 --- a/src/components/compare_commits.rs +++ b/src/components/compare_commits.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ accessors, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings, ui::style::SharedTheme, @@ -108,7 +108,7 @@ impl Component for CompareCommitsComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if event_pump(ev, self.components_mut().as_mut_slice())? .is_consumed() @@ -120,19 +120,26 @@ impl Component for CompareCommitsComponent { } if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide_stacked(false); - } else if e == self.key_config.keys.focus_right - && self.can_focus_diff() + } else if key_match( + e, + self.key_config.keys.focus_right, + ) && self.can_focus_diff() { self.details.focus(false); self.diff.focus(true); - } else if e == self.key_config.keys.focus_left - && self.diff.focused() + } else if key_match( + e, + self.key_config.keys.focus_left, + ) && self.diff.focused() { self.details.focus(true); self.diff.focus(false); - } else if e == self.key_config.keys.focus_left { + } else if key_match( + e, + self.key_config.keys.focus_left, + ) { self.hide_stacked(false); } diff --git a/src/components/create_branch.rs b/src/components/create_branch.rs index 265be31a..a5c784ff 100644 --- a/src/components/create_branch.rs +++ b/src/components/create_branch.rs @@ -4,7 +4,7 @@ use super::{ EventState, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, ui::style::SharedTheme, @@ -61,14 +61,14 @@ impl Component for CreateBranchComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if self.input.event(ev)?.is_consumed() { return Ok(EventState::Consumed); } if let Event::Key(e) = ev { - if e == self.key_config.keys.enter { + if key_match(e, self.key_config.keys.enter) { self.create_branch(); } diff --git a/src/components/cred.rs b/src/components/cred.rs index aac44eb9..2a72d4cd 100644 --- a/src/components/cred.rs +++ b/src/components/cred.rs @@ -5,6 +5,7 @@ use tui::{backend::Backend, layout::Rect, Frame}; use asyncgit::sync::cred::BasicAuthCredential; use crate::components::{EventState, InputType, TextInputComponent}; +use crate::keys::key_match; use crate::{ components::{ visibility_blocking, CommandBlocking, CommandInfo, Component, @@ -102,10 +103,10 @@ impl Component for CredComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide(); return Ok(EventState::Consumed); } @@ -113,7 +114,7 @@ impl Component for CredComponent { || self.input_password.event(ev)?.is_consumed() { return Ok(EventState::Consumed); - } else if e == self.key_config.keys.enter { + } else if key_match(e, self.key_config.keys.enter) { if self.input_username.is_visible() { self.cred = BasicAuthCredential::new( Some( diff --git a/src/components/diff.rs b/src/components/diff.rs index cf093420..7361c7b7 100644 --- a/src/components/diff.rs +++ b/src/components/diff.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ components::{CommandInfo, Component, EventState}, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem}, string_utils::tabs_to_spaces, strings, try_or_popup, @@ -723,35 +723,43 @@ impl Component for DiffComponent { } #[allow(clippy::cognitive_complexity)] - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.focused() { if let Event::Key(e) = ev { - return if e == self.key_config.keys.move_down { + return if key_match(e, self.key_config.keys.move_down) + { self.move_selection(ScrollType::Down); Ok(EventState::Consumed) - } else if e == self.key_config.keys.shift_down { + } else if key_match( + e, + self.key_config.keys.shift_down, + ) { self.modify_selection(Direction::Down); Ok(EventState::Consumed) - } else if e == self.key_config.keys.shift_up { + } else if key_match(e, self.key_config.keys.shift_up) + { self.modify_selection(Direction::Up); Ok(EventState::Consumed) - } else if e == self.key_config.keys.end { + } else if key_match(e, self.key_config.keys.end) { self.move_selection(ScrollType::End); Ok(EventState::Consumed) - } else if e == self.key_config.keys.home { + } else if key_match(e, self.key_config.keys.home) { self.move_selection(ScrollType::Home); Ok(EventState::Consumed) - } else if e == self.key_config.keys.move_up { + } else if key_match(e, self.key_config.keys.move_up) { self.move_selection(ScrollType::Up); Ok(EventState::Consumed) - } else if e == self.key_config.keys.page_up { + } else if key_match(e, self.key_config.keys.page_up) { self.move_selection(ScrollType::PageUp); Ok(EventState::Consumed) - } else if e == self.key_config.keys.page_down { + } else if key_match(e, self.key_config.keys.page_down) + { self.move_selection(ScrollType::PageDown); Ok(EventState::Consumed) - } else if e == self.key_config.keys.stage_unstage_item - && !self.is_immutable + } else if key_match( + e, + self.key_config.keys.stage_unstage_item, + ) && !self.is_immutable { try_or_popup!( self, @@ -760,8 +768,10 @@ impl Component for DiffComponent { ); Ok(EventState::Consumed) - } else if e == self.key_config.keys.status_reset_item - && !self.is_immutable + } else if key_match( + e, + self.key_config.keys.status_reset_item, + ) && !self.is_immutable && !self.is_stage() { if let Some(diff) = &self.diff { @@ -772,13 +782,17 @@ impl Component for DiffComponent { } } Ok(EventState::Consumed) - } else if e == self.key_config.keys.diff_stage_lines - && !self.is_immutable + } else if key_match( + e, + self.key_config.keys.diff_stage_lines, + ) && !self.is_immutable { self.stage_lines(); Ok(EventState::Consumed) - } else if e == self.key_config.keys.diff_reset_lines - && !self.is_immutable + } else if key_match( + e, + self.key_config.keys.diff_reset_lines, + ) && !self.is_immutable && !self.is_stage() { if let Some(diff) = &self.diff { @@ -788,7 +802,7 @@ impl Component for DiffComponent { } } Ok(EventState::Consumed) - } else if e == self.key_config.keys.copy { + } else if key_match(e, self.key_config.keys.copy) { self.copy_selection(); Ok(EventState::Consumed) } else { diff --git a/src/components/externaleditor.rs b/src/components/externaleditor.rs index eee93d15..3c9c9186 100644 --- a/src/components/externaleditor.rs +++ b/src/components/externaleditor.rs @@ -170,7 +170,7 @@ impl Component for ExternalEditorComponent { visibility_blocking(self) } - fn event(&mut self, _ev: Event) -> Result { + fn event(&mut self, _ev: &Event) -> Result { if self.visible { return Ok(EventState::Consumed); } diff --git a/src/components/fetch.rs b/src/components/fetch.rs index bedca015..17b3f829 100644 --- a/src/components/fetch.rs +++ b/src/components/fetch.rs @@ -183,7 +183,7 @@ impl Component for FetchComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(_) = ev { if self.input_cred.is_visible() { diff --git a/src/components/file_find_popup.rs b/src/components/file_find_popup.rs index 3e3cc0b2..3a459204 100644 --- a/src/components/file_find_popup.rs +++ b/src/components/file_find_popup.rs @@ -3,7 +3,7 @@ use super::{ DrawableComponent, EventState, ScrollType, TextInputComponent, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, string_utils::trim_length_left, strings, @@ -305,17 +305,23 @@ impl Component for FileFindPopup { fn event( &mut self, - event: crossterm::event::Event, + event: &crossterm::event::Event, ) -> Result { if self.is_visible() { - if let Event::Key(key) = &event { - if *key == self.key_config.keys.exit_popup - || *key == self.key_config.keys.enter + if let Event::Key(key) = event { + if key_match(key, self.key_config.keys.exit_popup) + || key_match(key, self.key_config.keys.enter) { self.hide(); - } else if *key == self.key_config.keys.popup_down { + } else if key_match( + key, + self.key_config.keys.popup_down, + ) { self.move_selection(ScrollType::Down); - } else if *key == self.key_config.keys.popup_up { + } else if key_match( + key, + self.key_config.keys.popup_up, + ) { self.move_selection(ScrollType::Up); } } diff --git a/src/components/file_revlog.rs b/src/components/file_revlog.rs index da383865..20af1096 100644 --- a/src/components/file_revlog.rs +++ b/src/components/file_revlog.rs @@ -1,5 +1,6 @@ use super::{utils::logitems::ItemBatch, SharedOptions}; use super::{visibility_blocking, BlameFileOpen, InspectCommitOpen}; +use crate::keys::key_match; use crate::queue::StackablePopupOpen; use crate::{ components::{ @@ -470,7 +471,7 @@ impl DrawableComponent for FileRevlogComponent { } impl Component for FileRevlogComponent { - fn event(&mut self, event: Event) -> Result { + fn event(&mut self, event: &Event) -> Result { if self.is_visible() { if event_pump( event, @@ -482,17 +483,22 @@ impl Component for FileRevlogComponent { } if let Event::Key(key) = event { - if key == self.key_config.keys.exit_popup { + if key_match(key, self.key_config.keys.exit_popup) { self.hide_stacked(false); - } else if key == self.key_config.keys.focus_right - && self.can_focus_diff() + } else if key_match( + key, + self.key_config.keys.focus_right, + ) && self.can_focus_diff() { self.diff.focus(true); - } else if key == self.key_config.keys.focus_left { + } else if key_match( + key, + self.key_config.keys.focus_left, + ) { if self.diff.focused() { self.diff.focus(false); } - } else if key == self.key_config.keys.enter { + } else if key_match(key, self.key_config.keys.enter) { if let Some(commit_id) = self.selected_commit() { self.hide_stacked(true); self.queue.push(InternalEvent::OpenPopup( @@ -501,7 +507,7 @@ impl Component for FileRevlogComponent { ), )); }; - } else if key == self.key_config.keys.blame { + } else if key_match(key, self.key_config.keys.blame) { if let Some(open_request) = self.open_request.clone() { @@ -516,21 +522,37 @@ impl Component for FileRevlogComponent { ), )); } - } else if key == self.key_config.keys.move_up { + } else if key_match(key, self.key_config.keys.move_up) + { self.move_selection(ScrollType::Up); - } else if key == self.key_config.keys.move_down { + } else if key_match( + key, + self.key_config.keys.move_down, + ) { self.move_selection(ScrollType::Down); - } else if key == self.key_config.keys.shift_up - || key == self.key_config.keys.home - { + } else if key_match( + key, + self.key_config.keys.shift_up, + ) || key_match( + key, + self.key_config.keys.home, + ) { self.move_selection(ScrollType::Home); - } else if key == self.key_config.keys.shift_down - || key == self.key_config.keys.end - { + } else if key_match( + key, + self.key_config.keys.shift_down, + ) || key_match( + key, + self.key_config.keys.end, + ) { self.move_selection(ScrollType::End); - } else if key == self.key_config.keys.page_up { + } else if key_match(key, self.key_config.keys.page_up) + { self.move_selection(ScrollType::PageUp); - } else if key == self.key_config.keys.page_down { + } else if key_match( + key, + self.key_config.keys.page_down, + ) { self.move_selection(ScrollType::PageDown); } } diff --git a/src/components/help.rs b/src/components/help.rs index d673c571..a965f295 100644 --- a/src/components/help.rs +++ b/src/components/help.rs @@ -2,7 +2,11 @@ use super::{ visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, }; -use crate::{keys::SharedKeyConfig, strings, ui, version::Version}; +use crate::{ + keys::{key_match, SharedKeyConfig}, + strings, ui, + version::Version, +}; use anyhow::Result; use asyncgit::hash; use crossterm::event::Event; @@ -121,14 +125,15 @@ impl Component for HelpComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide(); - } else if e == self.key_config.keys.move_down { + } else if key_match(e, self.key_config.keys.move_down) + { self.move_selection(true); - } else if e == self.key_config.keys.move_up { + } else if key_match(e, self.key_config.keys.move_up) { self.move_selection(false); } else { } @@ -136,7 +141,7 @@ impl Component for HelpComponent { Ok(EventState::Consumed) } else if let Event::Key(k) = ev { - if k == self.key_config.keys.open_help { + if key_match(k, self.key_config.keys.open_help) { self.show()?; Ok(EventState::Consumed) } else { diff --git a/src/components/inspect_commit.rs b/src/components/inspect_commit.rs index b8286209..c3b1779f 100644 --- a/src/components/inspect_commit.rs +++ b/src/components/inspect_commit.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ accessors, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings, ui::style::SharedTheme, @@ -143,7 +143,7 @@ impl Component for InspectCommitComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if event_pump(ev, self.components_mut().as_mut_slice())? .is_consumed() @@ -156,19 +156,26 @@ impl Component for InspectCommitComponent { } if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide_stacked(false); - } else if e == self.key_config.keys.focus_right - && self.can_focus_diff() + } else if key_match( + e, + self.key_config.keys.focus_right, + ) && self.can_focus_diff() { self.details.focus(false); self.diff.focus(true); - } else if e == self.key_config.keys.focus_left - && self.diff.focused() + } else if key_match( + e, + self.key_config.keys.focus_left, + ) && self.diff.focused() { self.details.focus(true); self.diff.focus(false); - } else if e == self.key_config.keys.open_file_tree { + } else if key_match( + e, + self.key_config.keys.open_file_tree, + ) { if let Some(commit) = self .open_request .as_ref() @@ -181,7 +188,10 @@ impl Component for InspectCommitComponent { ), )); } - } else if e == self.key_config.keys.focus_left { + } else if key_match( + e, + self.key_config.keys.focus_left, + ) { self.hide_stacked(false); } diff --git a/src/components/mod.rs b/src/components/mod.rs index a67c4a6c..ea7d8f28 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -146,7 +146,7 @@ macro_rules! setup_popups { /// returns `true` if event was consumed pub fn event_pump( - ev: Event, + ev: &Event, components: &mut [&mut dyn Component], ) -> Result { for c in components { @@ -255,7 +255,7 @@ pub trait Component { ) -> CommandBlocking; /// - fn event(&mut self, ev: Event) -> Result; + fn event(&mut self, ev: &Event) -> Result; /// fn focused(&self) -> bool { diff --git a/src/components/msg.rs b/src/components/msg.rs index 15806bd6..29a3ece7 100644 --- a/src/components/msg.rs +++ b/src/components/msg.rs @@ -2,7 +2,10 @@ use super::{ visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, }; -use crate::{keys::SharedKeyConfig, strings, ui}; +use crate::{ + keys::{key_match, SharedKeyConfig}, + strings, ui, +}; use crossterm::event::Event; use std::convert::TryFrom; use tui::{ @@ -89,10 +92,10 @@ impl Component for MsgComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { - if e == self.key_config.keys.enter { + if key_match(e, self.key_config.keys.enter) { self.hide(); } } diff --git a/src/components/options_popup.rs b/src/components/options_popup.rs index 66a95090..707c9928 100644 --- a/src/components/options_popup.rs +++ b/src/components/options_popup.rs @@ -6,7 +6,7 @@ use super::{ }; use crate::{ components::utils::string_width_align, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, strings::{self}, ui::{self, style::SharedTheme}, @@ -340,19 +340,29 @@ impl Component for OptionsPopupComponent { fn event( &mut self, - event: crossterm::event::Event, + event: &crossterm::event::Event, ) -> Result { if self.is_visible() { if let Event::Key(key) = &event { - if *key == self.key_config.keys.exit_popup { + if key_match(key, self.key_config.keys.exit_popup) { self.hide(); - } else if *key == self.key_config.keys.move_up { + } else if key_match(key, self.key_config.keys.move_up) + { self.move_selection(true); - } else if *key == self.key_config.keys.move_down { + } else if key_match( + key, + self.key_config.keys.move_down, + ) { self.move_selection(false); - } else if *key == self.key_config.keys.move_right { + } else if key_match( + key, + self.key_config.keys.move_right, + ) { self.switch_option(true); - } else if *key == self.key_config.keys.move_left { + } else if key_match( + key, + self.key_config.keys.move_left, + ) { self.switch_option(false); } } diff --git a/src/components/pull.rs b/src/components/pull.rs index 38ab5543..cfc1d7eb 100644 --- a/src/components/pull.rs +++ b/src/components/pull.rs @@ -263,7 +263,7 @@ impl Component for PullComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(_) = ev { if self.input_cred.is_visible() { diff --git a/src/components/push.rs b/src/components/push.rs index 528f44da..9ed2a137 100644 --- a/src/components/push.rs +++ b/src/components/push.rs @@ -3,7 +3,7 @@ use crate::{ cred::CredComponent, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, strings, ui::{self, style::SharedTheme}, @@ -297,7 +297,7 @@ impl Component for PushComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { if self.input_cred.is_visible() { @@ -312,8 +312,10 @@ impl Component for PushComponent { )?; self.input_cred.hide(); } - } else if e == self.key_config.keys.exit_popup - && !self.pending + } else if key_match( + e, + self.key_config.keys.exit_popup, + ) && !self.pending { self.hide(); } diff --git a/src/components/push_tags.rs b/src/components/push_tags.rs index 7735d70f..9ab9c78e 100644 --- a/src/components/push_tags.rs +++ b/src/components/push_tags.rs @@ -3,7 +3,7 @@ use crate::{ cred::CredComponent, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, strings::{self}, ui::{self, style::SharedTheme}, @@ -227,7 +227,7 @@ impl Component for PushTagsComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { if self.input_cred.is_visible() { @@ -241,8 +241,10 @@ impl Component for PushTagsComponent { ))?; self.input_cred.hide(); } - } else if e == self.key_config.keys.exit_popup - && !self.pending + } else if key_match( + e, + self.key_config.keys.exit_popup, + ) && !self.pending { self.hide(); } diff --git a/src/components/rename_branch.rs b/src/components/rename_branch.rs index 757f86bb..a519bf4d 100644 --- a/src/components/rename_branch.rs +++ b/src/components/rename_branch.rs @@ -4,7 +4,7 @@ use super::{ EventState, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, ui::style::SharedTheme, @@ -55,14 +55,14 @@ impl Component for RenameBranchComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if self.input.event(ev)?.is_consumed() { return Ok(EventState::Consumed); } if let Event::Key(e) = ev { - if e == self.key_config.keys.enter { + if key_match(e, self.key_config.keys.enter) { self.rename_branch(); } diff --git a/src/components/reset.rs b/src/components/reset.rs index dd48a442..c5e9f0cd 100644 --- a/src/components/reset.rs +++ b/src/components/reset.rs @@ -3,7 +3,7 @@ use crate::{ popup_paragraph, visibility_blocking, CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, Queue}, strings, ui, }; @@ -70,12 +70,12 @@ impl Component for ConfirmComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide(); - } else if e == self.key_config.keys.enter { + } else if key_match(e, self.key_config.keys.enter) { self.confirm(); } diff --git a/src/components/revision_files.rs b/src/components/revision_files.rs index 16c74d46..be1466c3 100644 --- a/src/components/revision_files.rs +++ b/src/components/revision_files.rs @@ -4,7 +4,7 @@ use super::{ EventState, FileRevOpen, SyntaxTextComponent, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings::{self, order, symbol}, ui::{self, common_nav, style::SharedTheme}, @@ -341,7 +341,7 @@ impl Component for RevisionFilesComponent { fn event( &mut self, - event: crossterm::event::Event, + event: &crossterm::event::Event, ) -> Result { if !self.is_visible() { return Ok(EventState::NotConsumed); @@ -354,36 +354,40 @@ impl Component for RevisionFilesComponent { { self.selection_changed(); return Ok(EventState::Consumed); - } else if key == self.key_config.keys.blame { + } else if key_match(key, self.key_config.keys.blame) { if self.blame() { self.hide(); return Ok(EventState::Consumed); } - } else if key == self.key_config.keys.file_history { + } else if key_match( + key, + self.key_config.keys.file_history, + ) { if self.file_history() { self.hide(); return Ok(EventState::Consumed); } - } else if key == self.key_config.keys.move_right { + } else if key_match(key, self.key_config.keys.move_right) + { if is_tree_focused { self.focus = Focus::File; self.current_file.focus(true); self.focus(true); return Ok(EventState::Consumed); } - } else if key == self.key_config.keys.move_left { + } else if key_match(key, self.key_config.keys.move_left) { if !is_tree_focused { self.focus = Focus::Tree; self.current_file.focus(false); self.focus(false); return Ok(EventState::Consumed); } - } else if key == self.key_config.keys.file_find { + } else if key_match(key, self.key_config.keys.file_find) { if is_tree_focused { self.open_finder(); return Ok(EventState::Consumed); } - } else if key == self.key_config.keys.edit_file { + } else if key_match(key, self.key_config.keys.edit_file) { if let Some(file) = self.selected_file_path_with_prefix() { @@ -437,14 +441,15 @@ fn tree_nav_cmds( fn tree_nav( tree: &mut FileTree, key_config: &SharedKeyConfig, - key: crossterm::event::KeyEvent, + key: &crossterm::event::KeyEvent, ) -> bool { if let Some(common_nav) = common_nav(key, key_config) { tree.move_selection(common_nav) - } else if key == key_config.keys.tree_collapse_recursive { + } else if key_match(key, key_config.keys.tree_collapse_recursive) + { tree.collapse_recursive(); true - } else if key == key_config.keys.tree_expand_recursive { + } else if key_match(key, key_config.keys.tree_expand_recursive) { tree.expand_recursive(); true } else { diff --git a/src/components/revision_files_popup.rs b/src/components/revision_files_popup.rs index 84cc3648..18a3ec4f 100644 --- a/src/components/revision_files_popup.rs +++ b/src/components/revision_files_popup.rs @@ -6,7 +6,7 @@ use super::{ EventState, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings::{self}, ui::style::SharedTheme, @@ -146,11 +146,11 @@ impl Component for RevisionFilesPopup { fn event( &mut self, - event: crossterm::event::Event, + event: &crossterm::event::Event, ) -> Result { if self.is_visible() { - if let Event::Key(key) = &event { - if *key == self.key_config.keys.exit_popup { + if let Event::Key(key) = event { + if key_match(key, self.key_config.keys.exit_popup) { self.hide_stacked(false); } } diff --git a/src/components/stashmsg.rs b/src/components/stashmsg.rs index 5ebeac6b..7ea0dca5 100644 --- a/src/components/stashmsg.rs +++ b/src/components/stashmsg.rs @@ -4,7 +4,7 @@ use super::{ EventState, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, tabs::StashingOptions, @@ -56,14 +56,14 @@ impl Component for StashMsgComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if self.input.event(ev)?.is_consumed() { return Ok(EventState::Consumed); } if let Event::Key(e) = ev { - if e == self.key_config.keys.enter { + if key_match(e, self.key_config.keys.enter) { let result = sync::stash_save( &self.repo.borrow(), if self.input.get_text().is_empty() { diff --git a/src/components/status_tree.rs b/src/components/status_tree.rs index 41bb8f25..f96e3fdc 100644 --- a/src/components/status_tree.rs +++ b/src/components/status_tree.rs @@ -7,7 +7,7 @@ use super::{ }; use crate::{ components::{CommandInfo, Component, EventState}, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue, StackablePopupOpen}, strings::{self, order}, ui, @@ -419,10 +419,10 @@ impl Component for StatusTreeComponent { CommandBlocking::PassingOn } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.focused { if let Event::Key(e) = ev { - return if e == self.key_config.keys.blame { + return if key_match(e, self.key_config.keys.blame) { if let Some(status_item) = self.selection_file() { self.hide(); if let Some(queue) = &self.queue { @@ -438,7 +438,10 @@ impl Component for StatusTreeComponent { } } Ok(EventState::Consumed) - } else if e == self.key_config.keys.file_history { + } else if key_match( + e, + self.key_config.keys.file_history, + ) { if let Some(status_item) = self.selection_file() { self.hide(); if let Some(queue) = &self.queue { @@ -452,27 +455,32 @@ impl Component for StatusTreeComponent { } } Ok(EventState::Consumed) - } else if e == self.key_config.keys.move_down { + } else if key_match(e, self.key_config.keys.move_down) + { Ok(self .move_selection(MoveSelection::Down) .into()) - } else if e == self.key_config.keys.move_up { + } else if key_match(e, self.key_config.keys.move_up) { Ok(self.move_selection(MoveSelection::Up).into()) - } else if e == self.key_config.keys.home - || e == self.key_config.keys.shift_up + } else if key_match(e, self.key_config.keys.home) + || key_match(e, self.key_config.keys.shift_up) { Ok(self .move_selection(MoveSelection::Home) .into()) - } else if e == self.key_config.keys.end - || e == self.key_config.keys.shift_down + } else if key_match(e, self.key_config.keys.end) + || key_match(e, self.key_config.keys.shift_down) { Ok(self.move_selection(MoveSelection::End).into()) - } else if e == self.key_config.keys.move_left { + } else if key_match(e, self.key_config.keys.move_left) + { Ok(self .move_selection(MoveSelection::Left) .into()) - } else if e == self.key_config.keys.move_right { + } else if key_match( + e, + self.key_config.keys.move_right, + ) { Ok(self .move_selection(MoveSelection::Right) .into()) diff --git a/src/components/syntax_text.rs b/src/components/syntax_text.rs index f1f4a24b..8bfc48a9 100644 --- a/src/components/syntax_text.rs +++ b/src/components/syntax_text.rs @@ -267,7 +267,7 @@ impl Component for SyntaxTextComponent { fn event( &mut self, - event: crossterm::event::Event, + event: &crossterm::event::Event, ) -> Result { if let Event::Key(key) = event { if let Some(nav) = common_nav(key, &self.key_config) { diff --git a/src/components/tag_commit.rs b/src/components/tag_commit.rs index 0af1daee..464fab6d 100644 --- a/src/components/tag_commit.rs +++ b/src/components/tag_commit.rs @@ -4,7 +4,7 @@ use super::{ EventState, }; use crate::{ - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, NeedsUpdate, Queue}, strings, ui::style::SharedTheme, @@ -67,19 +67,21 @@ impl Component for TagCommitComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.is_visible() { if self.input.event(ev)?.is_consumed() { return Ok(EventState::Consumed); } if let Event::Key(e) = ev { - if e == self.key_config.keys.enter + if key_match(e, self.key_config.keys.enter) && self.is_valid_tag() { self.tag(); - } else if e == self.key_config.keys.tag_annotate - && self.is_valid_tag() + } else if key_match( + e, + self.key_config.keys.tag_annotate, + ) && self.is_valid_tag() { let tag_name: String = self.input.get_text().into(); diff --git a/src/components/taglist.rs b/src/components/taglist.rs index e908c1be..f2c0dfb3 100644 --- a/src/components/taglist.rs +++ b/src/components/taglist.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{ components::ScrollType, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, Queue}, strings, ui::{self, Size}, @@ -187,32 +187,53 @@ impl Component for TagListComponent { visibility_blocking(self) } - fn event(&mut self, event: Event) -> Result { + fn event(&mut self, event: &Event) -> Result { if self.visible { if let Event::Key(key) = event { - if key == self.key_config.keys.exit_popup { + if key_match(key, self.key_config.keys.exit_popup) { self.hide(); - } else if key == self.key_config.keys.move_up { + } else if key_match(key, self.key_config.keys.move_up) + { self.move_selection(ScrollType::Up); - } else if key == self.key_config.keys.move_down { + } else if key_match( + key, + self.key_config.keys.move_down, + ) { self.move_selection(ScrollType::Down); - } else if key == self.key_config.keys.shift_up - || key == self.key_config.keys.home - { + } else if key_match( + key, + self.key_config.keys.shift_up, + ) || key_match( + key, + self.key_config.keys.home, + ) { self.move_selection(ScrollType::Home); - } else if key == self.key_config.keys.shift_down - || key == self.key_config.keys.end - { + } else if key_match( + key, + self.key_config.keys.shift_down, + ) || key_match( + key, + self.key_config.keys.end, + ) { self.move_selection(ScrollType::End); - } else if key == self.key_config.keys.page_down { + } else if key_match( + key, + self.key_config.keys.page_down, + ) { self.move_selection(ScrollType::PageDown); - } else if key == self.key_config.keys.page_up { + } else if key_match(key, self.key_config.keys.page_up) + { self.move_selection(ScrollType::PageUp); - } else if key == self.key_config.keys.move_right - && self.can_show_annotation() + } else if key_match( + key, + self.key_config.keys.move_right, + ) && self.can_show_annotation() { self.show_annotation(); - } else if key == self.key_config.keys.delete_tag { + } else if key_match( + key, + self.key_config.keys.delete_tag, + ) { return self.selected_tag().map_or( Ok(EventState::NotConsumed), |tag| { @@ -226,7 +247,10 @@ impl Component for TagListComponent { Ok(EventState::Consumed) }, ); - } else if key == self.key_config.keys.select_tag { + } else if key_match( + key, + self.key_config.keys.select_tag, + ) { return self.selected_tag().map_or( Ok(EventState::NotConsumed), |tag| { @@ -238,7 +262,7 @@ impl Component for TagListComponent { Ok(EventState::Consumed) }, ); - } else if key == self.key_config.keys.push + } else if key_match(key, self.key_config.keys.push) && self.has_remotes { self.queue.push(InternalEvent::PushTags); diff --git a/src/components/textinput.rs b/src/components/textinput.rs index 829901b4..a387106a 100644 --- a/src/components/textinput.rs +++ b/src/components/textinput.rs @@ -1,3 +1,4 @@ +use crate::keys::key_match; use crate::strings::symbol; use crate::ui::Size; use crate::{ @@ -348,10 +349,10 @@ impl Component for TextInputComponent { visibility_blocking(self) } - fn event(&mut self, ev: Event) -> Result { + fn event(&mut self, ev: &Event) -> Result { if self.visible { if let Event::Key(e) = ev { - if e == self.key_config.keys.exit_popup { + if key_match(e, self.key_config.keys.exit_popup) { self.hide(); return Ok(EventState::Consumed); } diff --git a/src/input.rs b/src/input.rs index 3802e61c..a3bd169c 100644 --- a/src/input.rs +++ b/src/input.rs @@ -21,7 +21,7 @@ pub enum InputState { } /// -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub enum InputEvent { Input(Event), State(InputState), diff --git a/src/keys/key_config.rs b/src/keys/key_config.rs index 0033cc2c..71d3e03b 100644 --- a/src/keys/key_config.rs +++ b/src/keys/key_config.rs @@ -1,10 +1,13 @@ use anyhow::Result; -use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use crossterm::event::{KeyCode, KeyModifiers}; use std::{path::PathBuf, rc::Rc}; use crate::{args::get_app_config_path, strings::symbol}; -use super::{key_list::KeysList, symbols::KeySymbols}; +use super::{ + key_list::{GituiKeyEvent, KeysList}, + symbols::KeySymbols, +}; pub type SharedKeyConfig = Rc; @@ -52,7 +55,7 @@ impl KeyConfig { } } - pub fn get_hint(&self, ev: KeyEvent) -> String { + pub fn get_hint(&self, ev: GituiKeyEvent) -> String { match ev.code { KeyCode::Down | KeyCode::Up @@ -93,6 +96,7 @@ impl KeyConfig { KeyCode::Null => { self.get_modifier_hint(ev.modifiers).into() } + _ => "".into(), } } @@ -109,15 +113,15 @@ impl KeyConfig { #[cfg(test)] mod tests { use super::*; - use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; + use crossterm::event::{KeyCode, KeyModifiers}; #[test] fn test_get_hint() { let config = KeyConfig::default(); - let h = config.get_hint(KeyEvent { - code: KeyCode::Char('c'), - modifiers: KeyModifiers::CONTROL, - }); + let h = config.get_hint(GituiKeyEvent::new( + KeyCode::Char('c'), + KeyModifiers::CONTROL, + )); assert_eq!(h, "^c"); } } diff --git a/src/keys/key_list.rs b/src/keys/key_list.rs index f261919a..0af9cf7c 100644 --- a/src/keys/key_list.rs +++ b/src/keys/key_list.rs @@ -1,159 +1,190 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; +use serde::{Deserialize, Serialize}; use std::path::PathBuf; use super::key_list_file::KeysListFile; +#[derive(Debug, PartialOrd, Clone, Copy, Serialize, Deserialize)] +pub struct GituiKeyEvent { + pub code: KeyCode, + pub modifiers: KeyModifiers, +} + +impl GituiKeyEvent { + pub const fn new(code: KeyCode, modifiers: KeyModifiers) -> Self { + Self { code, modifiers } + } +} + +pub fn key_match(ev: &KeyEvent, binding: GituiKeyEvent) -> bool { + ev.code == binding.code && ev.modifiers == binding.modifiers +} + +impl PartialEq for GituiKeyEvent { + fn eq(&self, other: &Self) -> bool { + let ev: KeyEvent = self.into(); + let other: KeyEvent = other.into(); + ev == other + } +} + +impl From<&GituiKeyEvent> for KeyEvent { + fn from(other: &GituiKeyEvent) -> Self { + Self::new(other.code, other.modifiers) + } +} + pub struct KeysList { - pub tab_status: KeyEvent, - pub tab_log: KeyEvent, - pub tab_files: KeyEvent, - pub tab_stashing: KeyEvent, - pub tab_stashes: KeyEvent, - pub tab_toggle: KeyEvent, - pub tab_toggle_reverse: KeyEvent, - pub toggle_workarea: KeyEvent, - pub focus_right: KeyEvent, - pub focus_left: KeyEvent, - pub focus_above: KeyEvent, - pub focus_below: KeyEvent, - pub exit: KeyEvent, - pub quit: KeyEvent, - pub exit_popup: KeyEvent, - pub open_commit: KeyEvent, - pub open_commit_editor: KeyEvent, - pub open_help: KeyEvent, - pub open_options: KeyEvent, - pub move_left: KeyEvent, - pub move_right: KeyEvent, - pub tree_collapse_recursive: KeyEvent, - pub tree_expand_recursive: KeyEvent, - pub home: KeyEvent, - pub end: KeyEvent, - pub move_up: KeyEvent, - pub move_down: KeyEvent, - pub popup_up: KeyEvent, - pub popup_down: KeyEvent, - pub page_down: KeyEvent, - pub page_up: KeyEvent, - pub shift_up: KeyEvent, - pub shift_down: KeyEvent, - pub enter: KeyEvent, - pub blame: KeyEvent, - pub file_history: KeyEvent, - pub edit_file: KeyEvent, - pub status_stage_all: KeyEvent, - pub status_reset_item: KeyEvent, - pub status_ignore_file: KeyEvent, - pub diff_stage_lines: KeyEvent, - pub diff_reset_lines: KeyEvent, - pub stashing_save: KeyEvent, - pub stashing_toggle_untracked: KeyEvent, - pub stashing_toggle_index: KeyEvent, - pub stash_apply: KeyEvent, - pub stash_open: KeyEvent, - pub stash_drop: KeyEvent, - pub cmd_bar_toggle: KeyEvent, - pub log_tag_commit: KeyEvent, - pub log_mark_commit: KeyEvent, - pub commit_amend: KeyEvent, - pub copy: KeyEvent, - pub create_branch: KeyEvent, - pub rename_branch: KeyEvent, - pub select_branch: KeyEvent, - pub delete_branch: KeyEvent, - pub merge_branch: KeyEvent, - pub rebase_branch: KeyEvent, - pub compare_commits: KeyEvent, - pub tags: KeyEvent, - pub delete_tag: KeyEvent, - pub select_tag: KeyEvent, - pub push: KeyEvent, - pub open_file_tree: KeyEvent, - pub file_find: KeyEvent, - pub force_push: KeyEvent, - pub pull: KeyEvent, - pub abort_merge: KeyEvent, - pub undo_commit: KeyEvent, - pub stage_unstage_item: KeyEvent, - pub tag_annotate: KeyEvent, + pub tab_status: GituiKeyEvent, + pub tab_log: GituiKeyEvent, + pub tab_files: GituiKeyEvent, + pub tab_stashing: GituiKeyEvent, + pub tab_stashes: GituiKeyEvent, + pub tab_toggle: GituiKeyEvent, + pub tab_toggle_reverse: GituiKeyEvent, + pub toggle_workarea: GituiKeyEvent, + pub focus_right: GituiKeyEvent, + pub focus_left: GituiKeyEvent, + pub focus_above: GituiKeyEvent, + pub focus_below: GituiKeyEvent, + pub exit: GituiKeyEvent, + pub quit: GituiKeyEvent, + pub exit_popup: GituiKeyEvent, + pub open_commit: GituiKeyEvent, + pub open_commit_editor: GituiKeyEvent, + pub open_help: GituiKeyEvent, + pub open_options: GituiKeyEvent, + pub move_left: GituiKeyEvent, + pub move_right: GituiKeyEvent, + pub tree_collapse_recursive: GituiKeyEvent, + pub tree_expand_recursive: GituiKeyEvent, + pub home: GituiKeyEvent, + pub end: GituiKeyEvent, + pub move_up: GituiKeyEvent, + pub move_down: GituiKeyEvent, + pub popup_up: GituiKeyEvent, + pub popup_down: GituiKeyEvent, + pub page_down: GituiKeyEvent, + pub page_up: GituiKeyEvent, + pub shift_up: GituiKeyEvent, + pub shift_down: GituiKeyEvent, + pub enter: GituiKeyEvent, + pub blame: GituiKeyEvent, + pub file_history: GituiKeyEvent, + pub edit_file: GituiKeyEvent, + pub status_stage_all: GituiKeyEvent, + pub status_reset_item: GituiKeyEvent, + pub status_ignore_file: GituiKeyEvent, + pub diff_stage_lines: GituiKeyEvent, + pub diff_reset_lines: GituiKeyEvent, + pub stashing_save: GituiKeyEvent, + pub stashing_toggle_untracked: GituiKeyEvent, + pub stashing_toggle_index: GituiKeyEvent, + pub stash_apply: GituiKeyEvent, + pub stash_open: GituiKeyEvent, + pub stash_drop: GituiKeyEvent, + pub cmd_bar_toggle: GituiKeyEvent, + pub log_tag_commit: GituiKeyEvent, + pub log_mark_commit: GituiKeyEvent, + pub commit_amend: GituiKeyEvent, + pub copy: GituiKeyEvent, + pub create_branch: GituiKeyEvent, + pub rename_branch: GituiKeyEvent, + pub select_branch: GituiKeyEvent, + pub delete_branch: GituiKeyEvent, + pub merge_branch: GituiKeyEvent, + pub rebase_branch: GituiKeyEvent, + pub compare_commits: GituiKeyEvent, + pub tags: GituiKeyEvent, + pub delete_tag: GituiKeyEvent, + pub select_tag: GituiKeyEvent, + pub push: GituiKeyEvent, + pub open_file_tree: GituiKeyEvent, + pub file_find: GituiKeyEvent, + pub force_push: GituiKeyEvent, + pub pull: GituiKeyEvent, + pub abort_merge: GituiKeyEvent, + pub undo_commit: GituiKeyEvent, + pub stage_unstage_item: GituiKeyEvent, + pub tag_annotate: GituiKeyEvent, } #[rustfmt::skip] impl Default for KeysList { fn default() -> Self { Self { - tab_status: KeyEvent { code: KeyCode::Char('1'), modifiers: KeyModifiers::empty()}, - tab_log: KeyEvent { code: KeyCode::Char('2'), modifiers: KeyModifiers::empty()}, - tab_files: KeyEvent { code: KeyCode::Char('3'), modifiers: KeyModifiers::empty()}, - tab_stashing: KeyEvent { code: KeyCode::Char('4'), modifiers: KeyModifiers::empty()}, - tab_stashes: KeyEvent { code: KeyCode::Char('5'), modifiers: KeyModifiers::empty()}, - tab_toggle: KeyEvent { code: KeyCode::Tab, modifiers: KeyModifiers::empty()}, - tab_toggle_reverse: KeyEvent { code: KeyCode::BackTab, modifiers: KeyModifiers::SHIFT}, - toggle_workarea: KeyEvent { code: KeyCode::Char('w'), modifiers: KeyModifiers::empty()}, - focus_right: KeyEvent { code: KeyCode::Right, modifiers: KeyModifiers::empty()}, - focus_left: KeyEvent { code: KeyCode::Left, modifiers: KeyModifiers::empty()}, - focus_above: KeyEvent { code: KeyCode::Up, modifiers: KeyModifiers::empty()}, - focus_below: KeyEvent { code: KeyCode::Down, modifiers: KeyModifiers::empty()}, - exit: KeyEvent { code: KeyCode::Char('c'), modifiers: KeyModifiers::CONTROL}, - quit: KeyEvent { code: KeyCode::Char('q'), modifiers: KeyModifiers::empty()}, - exit_popup: KeyEvent { code: KeyCode::Esc, modifiers: KeyModifiers::empty()}, - open_commit: KeyEvent { code: KeyCode::Char('c'), modifiers: KeyModifiers::empty()}, - open_commit_editor: KeyEvent { code: KeyCode::Char('e'), modifiers:KeyModifiers::CONTROL}, - open_help: KeyEvent { code: KeyCode::Char('h'), modifiers: KeyModifiers::empty()}, - open_options: KeyEvent { code: KeyCode::Char('o'), modifiers: KeyModifiers::empty()}, - move_left: KeyEvent { code: KeyCode::Left, modifiers: KeyModifiers::empty()}, - move_right: KeyEvent { code: KeyCode::Right, modifiers: KeyModifiers::empty()}, - tree_collapse_recursive: KeyEvent { code: KeyCode::Left, modifiers: KeyModifiers::SHIFT}, - tree_expand_recursive: KeyEvent { code: KeyCode::Right, modifiers: KeyModifiers::SHIFT}, - home: KeyEvent { code: KeyCode::Home, modifiers: KeyModifiers::empty()}, - end: KeyEvent { code: KeyCode::End, modifiers: KeyModifiers::empty()}, - move_up: KeyEvent { code: KeyCode::Up, modifiers: KeyModifiers::empty()}, - move_down: KeyEvent { code: KeyCode::Down, modifiers: KeyModifiers::empty()}, - popup_up: KeyEvent { code: KeyCode::Up, modifiers: KeyModifiers::empty()}, - popup_down: KeyEvent { code: KeyCode::Down, modifiers: KeyModifiers::empty()}, - page_down: KeyEvent { code: KeyCode::PageDown, modifiers: KeyModifiers::empty()}, - page_up: KeyEvent { code: KeyCode::PageUp, modifiers: KeyModifiers::empty()}, - shift_up: KeyEvent { code: KeyCode::Up, modifiers: KeyModifiers::SHIFT}, - shift_down: KeyEvent { code: KeyCode::Down, modifiers: KeyModifiers::SHIFT}, - enter: KeyEvent { code: KeyCode::Enter, modifiers: KeyModifiers::empty()}, - blame: KeyEvent { code: KeyCode::Char('B'), modifiers: KeyModifiers::SHIFT}, - file_history: KeyEvent { code: KeyCode::Char('H'), modifiers: KeyModifiers::SHIFT}, - edit_file: KeyEvent { code: KeyCode::Char('e'), modifiers: KeyModifiers::empty()}, - status_stage_all: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::empty()}, - status_reset_item: KeyEvent { code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT}, - diff_reset_lines: KeyEvent { code: KeyCode::Char('d'), modifiers: KeyModifiers::empty()}, - status_ignore_file: KeyEvent { code: KeyCode::Char('i'), modifiers: KeyModifiers::empty()}, - diff_stage_lines: KeyEvent { code: KeyCode::Char('s'), modifiers: KeyModifiers::empty()}, - stashing_save: KeyEvent { code: KeyCode::Char('s'), modifiers: KeyModifiers::empty()}, - stashing_toggle_untracked: KeyEvent { code: KeyCode::Char('u'), modifiers: KeyModifiers::empty()}, - stashing_toggle_index: KeyEvent { code: KeyCode::Char('i'), modifiers: KeyModifiers::empty()}, - stash_apply: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::empty()}, - stash_open: KeyEvent { code: KeyCode::Right, modifiers: KeyModifiers::empty()}, - stash_drop: KeyEvent { code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT}, - cmd_bar_toggle: KeyEvent { code: KeyCode::Char('.'), modifiers: KeyModifiers::empty()}, - log_tag_commit: KeyEvent { code: KeyCode::Char('t'), modifiers: KeyModifiers::empty()}, - log_mark_commit: KeyEvent { code: KeyCode::Char(' '), modifiers: KeyModifiers::empty()}, - commit_amend: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::CONTROL}, - copy: KeyEvent { code: KeyCode::Char('y'), modifiers: KeyModifiers::empty()}, - create_branch: KeyEvent { code: KeyCode::Char('c'), modifiers: KeyModifiers::empty()}, - rename_branch: KeyEvent { code: KeyCode::Char('r'), modifiers: KeyModifiers::empty()}, - select_branch: KeyEvent { code: KeyCode::Char('b'), modifiers: KeyModifiers::empty()}, - delete_branch: KeyEvent { code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT}, - merge_branch: KeyEvent { code: KeyCode::Char('m'), modifiers: KeyModifiers::empty()}, - rebase_branch: KeyEvent { code: KeyCode::Char('R'), modifiers: KeyModifiers::SHIFT}, - compare_commits: KeyEvent { code: KeyCode::Char('C'), modifiers: KeyModifiers::SHIFT}, - tags: KeyEvent { code: KeyCode::Char('T'), modifiers: KeyModifiers::SHIFT}, - delete_tag: KeyEvent { code: KeyCode::Char('D'), modifiers: KeyModifiers::SHIFT}, - select_tag: KeyEvent { code: KeyCode::Enter, modifiers: KeyModifiers::empty()}, - push: KeyEvent { code: KeyCode::Char('p'), modifiers: KeyModifiers::empty()}, - force_push: KeyEvent { code: KeyCode::Char('P'), modifiers: KeyModifiers::SHIFT}, - undo_commit: KeyEvent { code: KeyCode::Char('U'), modifiers: KeyModifiers::SHIFT}, - pull: KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty()}, - abort_merge: KeyEvent { code: KeyCode::Char('A'), modifiers: KeyModifiers::SHIFT}, - open_file_tree: KeyEvent { code: KeyCode::Char('F'), modifiers: KeyModifiers::SHIFT}, - file_find: KeyEvent { code: KeyCode::Char('f'), modifiers: KeyModifiers::empty()}, - stage_unstage_item: KeyEvent { code: KeyCode::Enter, modifiers: KeyModifiers::empty()}, - tag_annotate: KeyEvent { code: KeyCode::Char('a'), modifiers: KeyModifiers::CONTROL}, + tab_status: GituiKeyEvent::new(KeyCode::Char('1'), KeyModifiers::empty()), + tab_log: GituiKeyEvent::new(KeyCode::Char('2'), KeyModifiers::empty()), + tab_files: GituiKeyEvent::new(KeyCode::Char('3'), KeyModifiers::empty()), + tab_stashing: GituiKeyEvent::new(KeyCode::Char('4'), KeyModifiers::empty()), + tab_stashes: GituiKeyEvent::new(KeyCode::Char('5'), KeyModifiers::empty()), + tab_toggle: GituiKeyEvent::new(KeyCode::Tab, KeyModifiers::empty()), + tab_toggle_reverse: GituiKeyEvent::new(KeyCode::BackTab, KeyModifiers::SHIFT), + toggle_workarea: GituiKeyEvent::new(KeyCode::Char('w'), KeyModifiers::empty()), + focus_right: GituiKeyEvent::new(KeyCode::Right, KeyModifiers::empty()), + focus_left: GituiKeyEvent::new(KeyCode::Left, KeyModifiers::empty()), + focus_above: GituiKeyEvent::new(KeyCode::Up, KeyModifiers::empty()), + focus_below: GituiKeyEvent::new(KeyCode::Down, KeyModifiers::empty()), + exit: GituiKeyEvent::new(KeyCode::Char('c'), KeyModifiers::CONTROL), + quit: GituiKeyEvent::new(KeyCode::Char('q'), KeyModifiers::empty()), + exit_popup: GituiKeyEvent::new(KeyCode::Esc, KeyModifiers::empty()), + open_commit: GituiKeyEvent::new(KeyCode::Char('c'), KeyModifiers::empty()), + open_commit_editor: GituiKeyEvent::new(KeyCode::Char('e'), KeyModifiers::CONTROL), + open_help: GituiKeyEvent::new(KeyCode::Char('h'), KeyModifiers::empty()), + open_options: GituiKeyEvent::new(KeyCode::Char('o'), KeyModifiers::empty()), + move_left: GituiKeyEvent::new(KeyCode::Left, KeyModifiers::empty()), + move_right: GituiKeyEvent::new(KeyCode::Right, KeyModifiers::empty()), + tree_collapse_recursive: GituiKeyEvent::new(KeyCode::Left, KeyModifiers::SHIFT), + tree_expand_recursive: GituiKeyEvent::new(KeyCode::Right, KeyModifiers::SHIFT), + home: GituiKeyEvent::new(KeyCode::Home, KeyModifiers::empty()), + end: GituiKeyEvent::new(KeyCode::End, KeyModifiers::empty()), + move_up: GituiKeyEvent::new(KeyCode::Up, KeyModifiers::empty()), + move_down: GituiKeyEvent::new(KeyCode::Down, KeyModifiers::empty()), + popup_up: GituiKeyEvent::new(KeyCode::Up, KeyModifiers::empty()), + popup_down: GituiKeyEvent::new(KeyCode::Down, KeyModifiers::empty()), + page_down: GituiKeyEvent::new(KeyCode::PageDown, KeyModifiers::empty()), + page_up: GituiKeyEvent::new(KeyCode::PageUp, KeyModifiers::empty()), + shift_up: GituiKeyEvent::new(KeyCode::Up, KeyModifiers::SHIFT), + shift_down: GituiKeyEvent::new(KeyCode::Down, KeyModifiers::SHIFT), + enter: GituiKeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + blame: GituiKeyEvent::new(KeyCode::Char('B'), KeyModifiers::SHIFT), + file_history: GituiKeyEvent::new(KeyCode::Char('H'), KeyModifiers::SHIFT), + edit_file: GituiKeyEvent::new(KeyCode::Char('e'), KeyModifiers::empty()), + status_stage_all: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::empty()), + status_reset_item: GituiKeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT), + diff_reset_lines: GituiKeyEvent::new(KeyCode::Char('d'), KeyModifiers::empty()), + status_ignore_file: GituiKeyEvent::new(KeyCode::Char('i'), KeyModifiers::empty()), + diff_stage_lines: GituiKeyEvent::new(KeyCode::Char('s'), KeyModifiers::empty()), + stashing_save: GituiKeyEvent::new(KeyCode::Char('s'), KeyModifiers::empty()), + stashing_toggle_untracked: GituiKeyEvent::new(KeyCode::Char('u'), KeyModifiers::empty()), + stashing_toggle_index: GituiKeyEvent::new(KeyCode::Char('i'), KeyModifiers::empty()), + stash_apply: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::empty()), + stash_open: GituiKeyEvent::new(KeyCode::Right, KeyModifiers::empty()), + stash_drop: GituiKeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT), + cmd_bar_toggle: GituiKeyEvent::new(KeyCode::Char('.'), KeyModifiers::empty()), + log_tag_commit: GituiKeyEvent::new(KeyCode::Char('t'), KeyModifiers::empty()), + log_mark_commit: GituiKeyEvent::new(KeyCode::Char(' '), KeyModifiers::empty()), + commit_amend: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL), + copy: GituiKeyEvent::new(KeyCode::Char('y'), KeyModifiers::empty()), + create_branch: GituiKeyEvent::new(KeyCode::Char('c'), KeyModifiers::empty()), + rename_branch: GituiKeyEvent::new(KeyCode::Char('r'), KeyModifiers::empty()), + select_branch: GituiKeyEvent::new(KeyCode::Char('b'), KeyModifiers::empty()), + delete_branch: GituiKeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT), + merge_branch: GituiKeyEvent::new(KeyCode::Char('m'), KeyModifiers::empty()), + rebase_branch: GituiKeyEvent::new(KeyCode::Char('R'), KeyModifiers::SHIFT), + compare_commits: GituiKeyEvent::new(KeyCode::Char('C'), KeyModifiers::SHIFT), + tags: GituiKeyEvent::new(KeyCode::Char('T'), KeyModifiers::SHIFT), + delete_tag: GituiKeyEvent::new(KeyCode::Char('D'), KeyModifiers::SHIFT), + select_tag: GituiKeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + push: GituiKeyEvent::new(KeyCode::Char('p'), KeyModifiers::empty()), + force_push: GituiKeyEvent::new(KeyCode::Char('P'), KeyModifiers::SHIFT), + undo_commit: GituiKeyEvent::new(KeyCode::Char('U'), KeyModifiers::SHIFT), + pull: GituiKeyEvent::new(KeyCode::Char('f'), KeyModifiers::empty()), + abort_merge: GituiKeyEvent::new(KeyCode::Char('A'), KeyModifiers::SHIFT), + open_file_tree: GituiKeyEvent::new(KeyCode::Char('F'), KeyModifiers::SHIFT), + file_find: GituiKeyEvent::new(KeyCode::Char('f'), KeyModifiers::empty()), + stage_unstage_item: GituiKeyEvent::new(KeyCode::Enter, KeyModifiers::empty()), + tag_annotate: GituiKeyEvent::new(KeyCode::Char('a'), KeyModifiers::CONTROL), } } } diff --git a/src/keys/key_list_file.rs b/src/keys/key_list_file.rs index c31c4453..7b2a3bbb 100644 --- a/src/keys/key_list_file.rs +++ b/src/keys/key_list_file.rs @@ -1,85 +1,84 @@ use anyhow::Result; -use crossterm::event::KeyEvent; use ron::{self}; use serde::{Deserialize, Serialize}; use std::{fs::File, io::Read, path::PathBuf}; -use super::key_list::KeysList; +use super::key_list::{GituiKeyEvent, KeysList}; #[derive(Serialize, Deserialize, Default)] pub struct KeysListFile { - pub tab_status: Option, - pub tab_log: Option, - pub tab_files: Option, - pub tab_stashing: Option, - pub tab_stashes: Option, - pub tab_toggle: Option, - pub tab_toggle_reverse: Option, - pub toggle_workarea: Option, - pub focus_right: Option, - pub focus_left: Option, - pub focus_above: Option, - pub focus_below: Option, - pub exit: Option, - pub quit: Option, - pub exit_popup: Option, - pub open_commit: Option, - pub open_commit_editor: Option, - pub open_help: Option, - pub open_options: Option, - pub move_left: Option, - pub move_right: Option, - pub tree_collapse_recursive: Option, - pub tree_expand_recursive: Option, - pub home: Option, - pub end: Option, - pub move_up: Option, - pub move_down: Option, - pub popup_up: Option, - pub popup_down: Option, - pub page_down: Option, - pub page_up: Option, - pub shift_up: Option, - pub shift_down: Option, - pub enter: Option, - pub blame: Option, - pub edit_file: Option, - pub file_history: Option, - pub status_stage_all: Option, - pub status_reset_item: Option, - pub status_ignore_file: Option, - pub diff_stage_lines: Option, - pub diff_reset_lines: Option, - pub stashing_save: Option, - pub stashing_toggle_untracked: Option, - pub stashing_toggle_index: Option, - pub stash_apply: Option, - pub stash_open: Option, - pub stash_drop: Option, - pub cmd_bar_toggle: Option, - pub log_tag_commit: Option, - pub log_mark_commit: Option, - pub commit_amend: Option, - pub copy: Option, - pub create_branch: Option, - pub rename_branch: Option, - pub select_branch: Option, - pub delete_branch: Option, - pub merge_branch: Option, - pub rebase_branch: Option, - pub compare_commits: Option, - pub tags: Option, - pub delete_tag: Option, - pub select_tag: Option, - pub push: Option, - pub open_file_tree: Option, - pub file_find: Option, - pub force_push: Option, - pub pull: Option, - pub abort_merge: Option, - pub undo_commit: Option, - pub stage_unstage_item: Option, - pub tag_annotate: Option, + pub tab_status: Option, + pub tab_log: Option, + pub tab_files: Option, + pub tab_stashing: Option, + pub tab_stashes: Option, + pub tab_toggle: Option, + pub tab_toggle_reverse: Option, + pub toggle_workarea: Option, + pub focus_right: Option, + pub focus_left: Option, + pub focus_above: Option, + pub focus_below: Option, + pub exit: Option, + pub quit: Option, + pub exit_popup: Option, + pub open_commit: Option, + pub open_commit_editor: Option, + pub open_help: Option, + pub open_options: Option, + pub move_left: Option, + pub move_right: Option, + pub tree_collapse_recursive: Option, + pub tree_expand_recursive: Option, + pub home: Option, + pub end: Option, + pub move_up: Option, + pub move_down: Option, + pub popup_up: Option, + pub popup_down: Option, + pub page_down: Option, + pub page_up: Option, + pub shift_up: Option, + pub shift_down: Option, + pub enter: Option, + pub blame: Option, + pub edit_file: Option, + pub file_history: Option, + pub status_stage_all: Option, + pub status_reset_item: Option, + pub status_ignore_file: Option, + pub diff_stage_lines: Option, + pub diff_reset_lines: Option, + pub stashing_save: Option, + pub stashing_toggle_untracked: Option, + pub stashing_toggle_index: Option, + pub stash_apply: Option, + pub stash_open: Option, + pub stash_drop: Option, + pub cmd_bar_toggle: Option, + pub log_tag_commit: Option, + pub log_mark_commit: Option, + pub commit_amend: Option, + pub copy: Option, + pub create_branch: Option, + pub rename_branch: Option, + pub select_branch: Option, + pub delete_branch: Option, + pub merge_branch: Option, + pub rebase_branch: Option, + pub compare_commits: Option, + pub tags: Option, + pub delete_tag: Option, + pub select_tag: Option, + pub push: Option, + pub open_file_tree: Option, + pub file_find: Option, + pub force_push: Option, + pub pull: Option, + pub abort_merge: Option, + pub undo_commit: Option, + pub stage_unstage_item: Option, + pub tag_annotate: Option, } impl KeysListFile { diff --git a/src/keys/mod.rs b/src/keys/mod.rs index e572572e..657c980e 100644 --- a/src/keys/mod.rs +++ b/src/keys/mod.rs @@ -4,3 +4,4 @@ mod key_list_file; mod symbols; pub use key_config::{KeyConfig, SharedKeyConfig}; +pub use key_list::key_match; diff --git a/src/main.rs b/src/main.rs index fe11eb28..50e66801 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,7 +71,7 @@ static TICK_INTERVAL: Duration = Duration::from_secs(5); static SPINNER_INTERVAL: Duration = Duration::from_millis(80); /// -#[derive(Clone, Copy)] +#[derive(Clone)] pub enum QueueEvent { Tick, SpinnerUpdate, diff --git a/src/tabs/files.rs b/src/tabs/files.rs index 812f4b8e..c994b213 100644 --- a/src/tabs/files.rs +++ b/src/tabs/files.rs @@ -98,7 +98,7 @@ impl Component for FilesTab { fn event( &mut self, - ev: crossterm::event::Event, + ev: &crossterm::event::Event, ) -> Result { if self.visible { return self.files.event(ev); diff --git a/src/tabs/revlog.rs b/src/tabs/revlog.rs index 41fc7f8b..47baeff2 100644 --- a/src/tabs/revlog.rs +++ b/src/tabs/revlog.rs @@ -5,7 +5,7 @@ use crate::{ DrawableComponent, EventState, FileTreeOpen, InspectCommitOpen, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue, StackablePopupOpen}, strings, try_or_popup, ui::style::SharedTheme, @@ -242,7 +242,9 @@ impl DrawableComponent for Revlog { } impl Component for Revlog { - fn event(&mut self, ev: Event) -> Result { + //TODO: cleanup + #[allow(clippy::too_many_lines)] + fn event(&mut self, ev: &Event) -> Result { if self.visible { let event_used = self.list.event(ev)?; @@ -250,17 +252,20 @@ impl Component for Revlog { self.update()?; return Ok(EventState::Consumed); } else if let Event::Key(k) = ev { - if k == self.key_config.keys.enter { + if key_match(k, self.key_config.keys.enter) { self.commit_details.toggle_visible()?; self.update()?; return Ok(EventState::Consumed); - } else if k == self.key_config.keys.copy { + } else if key_match(k, self.key_config.keys.copy) { self.copy_commit_hash()?; return Ok(EventState::Consumed); - } else if k == self.key_config.keys.push { + } else if key_match(k, self.key_config.keys.push) { self.queue.push(InternalEvent::PushTags); return Ok(EventState::Consumed); - } else if k == self.key_config.keys.log_tag_commit { + } else if key_match( + k, + self.key_config.keys.log_tag_commit, + ) { return self.selected_commit().map_or( Ok(EventState::NotConsumed), |id| { @@ -269,16 +274,23 @@ impl Component for Revlog { Ok(EventState::Consumed) }, ); - } else if k == self.key_config.keys.focus_right - && self.commit_details.is_visible() + } else if key_match( + k, + self.key_config.keys.focus_right, + ) && self.commit_details.is_visible() { self.inspect_commit(); return Ok(EventState::Consumed); - } else if k == self.key_config.keys.select_branch { + } else if key_match( + k, + self.key_config.keys.select_branch, + ) { self.queue.push(InternalEvent::SelectBranch); return Ok(EventState::Consumed); - } else if k == self.key_config.keys.status_reset_item - { + } else if key_match( + k, + self.key_config.keys.status_reset_item, + ) { try_or_popup!( self, "revert error:", @@ -286,7 +298,10 @@ impl Component for Revlog { ); return Ok(EventState::Consumed); - } else if k == self.key_config.keys.open_file_tree { + } else if key_match( + k, + self.key_config.keys.open_file_tree, + ) { return self.selected_commit().map_or( Ok(EventState::NotConsumed), |id| { @@ -300,11 +315,13 @@ impl Component for Revlog { Ok(EventState::Consumed) }, ); - } else if k == self.key_config.keys.tags { + } else if key_match(k, self.key_config.keys.tags) { self.queue.push(InternalEvent::Tags); return Ok(EventState::Consumed); - } else if k == self.key_config.keys.compare_commits - && self.list.marked_count() > 0 + } else if key_match( + k, + self.key_config.keys.compare_commits, + ) && self.list.marked_count() > 0 { if self.list.marked_count() == 1 { // compare against head diff --git a/src/tabs/stashing.rs b/src/tabs/stashing.rs index 63750d52..de8f52a9 100644 --- a/src/tabs/stashing.rs +++ b/src/tabs/stashing.rs @@ -5,7 +5,7 @@ use crate::{ CommandBlocking, CommandInfo, Component, DrawableComponent, EventState, StatusTreeComponent, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{InternalEvent, Queue}, strings, ui::style::SharedTheme, @@ -213,7 +213,7 @@ impl Component for Stashing { fn event( &mut self, - ev: crossterm::event::Event, + ev: &crossterm::event::Event, ) -> Result { if self.visible { if event_pump(ev, self.components_mut().as_mut_slice())? @@ -223,24 +223,28 @@ impl Component for Stashing { } if let Event::Key(k) = ev { - return if k == self.key_config.keys.stashing_save - && !self.index.is_empty() + return if key_match( + k, + self.key_config.keys.stashing_save, + ) && !self.index.is_empty() { self.queue.push(InternalEvent::PopupStashing( self.options, )); Ok(EventState::Consumed) - } else if k - == self.key_config.keys.stashing_toggle_index - { + } else if key_match( + k, + self.key_config.keys.stashing_toggle_index, + ) { self.options.keep_index = !self.options.keep_index; self.update()?; Ok(EventState::Consumed) - } else if k - == self.key_config.keys.stashing_toggle_untracked - { + } else if key_match( + k, + self.key_config.keys.stashing_toggle_untracked, + ) { self.options.stash_untracked = !self.options.stash_untracked; self.update()?; diff --git a/src/tabs/stashlist.rs b/src/tabs/stashlist.rs index e4e5efae..dc3bc981 100644 --- a/src/tabs/stashlist.rs +++ b/src/tabs/stashlist.rs @@ -4,7 +4,7 @@ use crate::{ CommitList, Component, DrawableComponent, EventState, InspectCommitOpen, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, Queue, StackablePopupOpen}, strings, ui::style::SharedTheme, @@ -200,7 +200,7 @@ impl Component for StashList { fn event( &mut self, - ev: crossterm::event::Event, + ev: &crossterm::event::Event, ) -> Result { if self.is_visible() { if self.list.event(ev)?.is_consumed() { @@ -208,13 +208,22 @@ impl Component for StashList { } if let Event::Key(k) = ev { - if k == self.key_config.keys.enter { + if key_match(k, self.key_config.keys.enter) { self.pop_stash(); - } else if k == self.key_config.keys.stash_apply { + } else if key_match( + k, + self.key_config.keys.stash_apply, + ) { self.apply_stash(); - } else if k == self.key_config.keys.stash_drop { + } else if key_match( + k, + self.key_config.keys.stash_drop, + ) { self.drop_stash(); - } else if k == self.key_config.keys.stash_open { + } else if key_match( + k, + self.key_config.keys.stash_open, + ) { self.inspect(); } } diff --git a/src/tabs/status.rs b/src/tabs/status.rs index 65497f12..00cea28d 100644 --- a/src/tabs/status.rs +++ b/src/tabs/status.rs @@ -6,7 +6,7 @@ use crate::{ DiffComponent, DrawableComponent, EventState, FileTreeItemKind, SharedOptions, }, - keys::SharedKeyConfig, + keys::{key_match, SharedKeyConfig}, queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem}, strings, try_or_popup, ui::style::SharedTheme, @@ -803,7 +803,7 @@ impl Component for Status { #[allow(clippy::too_many_lines, clippy::cognitive_complexity)] fn event( &mut self, - ev: crossterm::event::Event, + ev: &crossterm::event::Event, ) -> Result { if self.visible { if event_pump(ev, self.components_mut().as_mut_slice())? @@ -814,7 +814,7 @@ impl Component for Status { } if let Event::Key(k) = ev { - return if k == self.key_config.keys.edit_file + return if key_match(k, self.key_config.keys.edit_file) && (self.can_focus_diff() || self.is_focus_on_diff()) { @@ -826,67 +826,85 @@ impl Component for Status { ); } Ok(EventState::Consumed) - } else if k == self.key_config.keys.open_commit - && self.can_commit() + } else if key_match( + k, + self.key_config.keys.open_commit, + ) && self.can_commit() { self.queue.push(InternalEvent::OpenCommit); Ok(EventState::Consumed) - } else if k == self.key_config.keys.toggle_workarea - && !self.is_focus_on_diff() + } else if key_match( + k, + self.key_config.keys.toggle_workarea, + ) && !self.is_focus_on_diff() { self.switch_focus(self.focus.toggled_focus()) .map(Into::into) - } else if k == self.key_config.keys.focus_right - && self.can_focus_diff() + } else if key_match( + k, + self.key_config.keys.focus_right, + ) && self.can_focus_diff() { self.switch_focus(Focus::Diff).map(Into::into) - } else if k == self.key_config.keys.focus_left { + } else if key_match( + k, + self.key_config.keys.focus_left, + ) { self.switch_focus(match self.diff_target { DiffTarget::Stage => Focus::Stage, DiffTarget::WorkingDir => Focus::WorkDir, }) .map(Into::into) - } else if k == self.key_config.keys.move_down + } else if key_match(k, self.key_config.keys.move_down) && self.focus == Focus::WorkDir && !self.index.is_empty() { self.switch_focus(Focus::Stage).map(Into::into) - } else if k == self.key_config.keys.move_up + } else if key_match(k, self.key_config.keys.move_up) && self.focus == Focus::Stage && !self.index_wd.is_empty() { self.switch_focus(Focus::WorkDir).map(Into::into) - } else if k == self.key_config.keys.select_branch - && !self.is_focus_on_diff() + } else if key_match( + k, + self.key_config.keys.select_branch, + ) && !self.is_focus_on_diff() { self.queue.push(InternalEvent::SelectBranch); Ok(EventState::Consumed) - } else if k == self.key_config.keys.force_push - && !self.is_focus_on_diff() + } else if key_match( + k, + self.key_config.keys.force_push, + ) && !self.is_focus_on_diff() && self.can_push() { self.push(true); Ok(EventState::Consumed) - } else if k == self.key_config.keys.push + } else if key_match(k, self.key_config.keys.push) && !self.is_focus_on_diff() { self.push(false); Ok(EventState::Consumed) - } else if k == self.key_config.keys.pull + } else if key_match(k, self.key_config.keys.pull) && !self.is_focus_on_diff() && self.can_pull() { self.pull(); Ok(EventState::Consumed) - } else if k == self.key_config.keys.undo_commit - && !self.is_focus_on_diff() + } else if key_match( + k, + self.key_config.keys.undo_commit, + ) && !self.is_focus_on_diff() { self.undo_last_commit(); self.queue.push(InternalEvent::Update( NeedsUpdate::ALL, )); Ok(EventState::Consumed) - } else if k == self.key_config.keys.abort_merge { + } else if key_match( + k, + self.key_config.keys.abort_merge, + ) { if self.can_abort_merge() { self.queue.push( InternalEvent::ConfirmAction( @@ -908,8 +926,10 @@ impl Component for Status { } Ok(EventState::Consumed) - } else if k == self.key_config.keys.rebase_branch - && self.pending_rebase() + } else if key_match( + k, + self.key_config.keys.rebase_branch, + ) && self.pending_rebase() { self.continue_rebase(); self.queue.push(InternalEvent::Update( diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 1e8d3c47..cee73105 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -14,7 +14,7 @@ pub use stateful_paragraph::{ pub use syntax_text::{AsyncSyntaxJob, SyntaxText}; use tui::layout::{Constraint, Direction, Layout, Rect}; -use crate::keys::SharedKeyConfig; +use crate::keys::{key_match, SharedKeyConfig}; /// return the scroll position (line) necessary to have the `selection` in view if it is not already pub const fn calc_scroll_top( @@ -115,27 +115,27 @@ pub fn centered_rect_absolute( /// pub fn common_nav( - key: crossterm::event::KeyEvent, + key: &crossterm::event::KeyEvent, key_config: &SharedKeyConfig, ) -> Option { - if key == key_config.keys.move_down { + if key_match(key, key_config.keys.move_down) { Some(MoveSelection::Down) - } else if key == key_config.keys.move_up { + } else if key_match(key, key_config.keys.move_up) { Some(MoveSelection::Up) - } else if key == key_config.keys.page_up { + } else if key_match(key, key_config.keys.page_up) { Some(MoveSelection::PageUp) - } else if key == key_config.keys.page_down { + } else if key_match(key, key_config.keys.page_down) { Some(MoveSelection::PageDown) - } else if key == key_config.keys.move_right { + } else if key_match(key, key_config.keys.move_right) { Some(MoveSelection::Right) - } else if key == key_config.keys.move_left { + } else if key_match(key, key_config.keys.move_left) { Some(MoveSelection::Left) - } else if key == key_config.keys.home - || key == key_config.keys.shift_up + } else if key_match(key, key_config.keys.home) + || key_match(key, key_config.keys.shift_up) { Some(MoveSelection::Top) - } else if key == key_config.keys.end - || key == key_config.keys.shift_down + } else if key_match(key, key_config.keys.end) + || key_match(key, key_config.keys.shift_down) { Some(MoveSelection::End) } else {