upgrade crossterm/tui

This commit is contained in:
extrawurst 2022-08-17 21:46:55 +02:00 committed by extrawurst
parent 2eee7e9b0e
commit 8e54bfd364
49 changed files with 860 additions and 574 deletions

8
Cargo.lock generated
View File

@ -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",

View File

@ -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"

View File

@ -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)?;
}

View File

@ -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<EventState> {
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()

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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);
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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())

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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),
);

View File

@ -161,7 +161,7 @@ impl Component for CompareDetailsComponent {
CommandBlocking::PassingOn
}
fn event(&mut self, _event: Event) -> Result<EventState> {
fn event(&mut self, _event: &Event) -> Result<EventState> {
Ok(EventState::NotConsumed)
}

View File

@ -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<EventState> {
fn event(&mut self, event: &Event) -> Result<EventState> {
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
},
);
}
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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);

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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 {

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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);
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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(

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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 {

View File

@ -170,7 +170,7 @@ impl Component for ExternalEditorComponent {
visibility_blocking(self)
}
fn event(&mut self, _ev: Event) -> Result<EventState> {
fn event(&mut self, _ev: &Event) -> Result<EventState> {
if self.visible {
return Ok(EventState::Consumed);
}

View File

@ -183,7 +183,7 @@ impl Component for FetchComponent {
visibility_blocking(self)
}
fn event(&mut self, ev: Event) -> Result<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
if self.visible {
if let Event::Key(_) = ev {
if self.input_cred.is_visible() {

View File

@ -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<EventState> {
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);
}
}

View File

@ -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<EventState> {
fn event(&mut self, event: &Event) -> Result<EventState> {
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);
}
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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 {

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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);
}

View File

@ -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<EventState> {
for c in components {
@ -255,7 +255,7 @@ pub trait Component {
) -> CommandBlocking;
///
fn event(&mut self, ev: Event) -> Result<EventState>;
fn event(&mut self, ev: &Event) -> Result<EventState>;
///
fn focused(&self) -> bool {

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();
}
}

View File

@ -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<EventState> {
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);
}
}

View File

@ -263,7 +263,7 @@ impl Component for PullComponent {
visibility_blocking(self)
}
fn event(&mut self, ev: Event) -> Result<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
if self.visible {
if let Event::Key(_) = ev {
if self.input_cred.is_visible() {

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();
}

View File

@ -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<EventState> {
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 {

View File

@ -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<EventState> {
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);
}
}

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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() {

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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())

View File

@ -267,7 +267,7 @@ impl Component for SyntaxTextComponent {
fn event(
&mut self,
event: crossterm::event::Event,
event: &crossterm::event::Event,
) -> Result<EventState> {
if let Event::Key(key) = event {
if let Some(nav) = common_nav(key, &self.key_config) {

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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();

View File

@ -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<EventState> {
fn event(&mut self, event: &Event) -> Result<EventState> {
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);

View File

@ -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<EventState> {
fn event(&mut self, ev: &Event) -> Result<EventState> {
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);
}

View File

@ -21,7 +21,7 @@ pub enum InputState {
}
///
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Debug)]
pub enum InputEvent {
Input(Event),
State(InputState),

View File

@ -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<KeyConfig>;
@ -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");
}
}

View File

@ -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),
}
}
}

View File

@ -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<KeyEvent>,
pub tab_log: Option<KeyEvent>,
pub tab_files: Option<KeyEvent>,
pub tab_stashing: Option<KeyEvent>,
pub tab_stashes: Option<KeyEvent>,
pub tab_toggle: Option<KeyEvent>,
pub tab_toggle_reverse: Option<KeyEvent>,
pub toggle_workarea: Option<KeyEvent>,
pub focus_right: Option<KeyEvent>,
pub focus_left: Option<KeyEvent>,
pub focus_above: Option<KeyEvent>,
pub focus_below: Option<KeyEvent>,
pub exit: Option<KeyEvent>,
pub quit: Option<KeyEvent>,
pub exit_popup: Option<KeyEvent>,
pub open_commit: Option<KeyEvent>,
pub open_commit_editor: Option<KeyEvent>,
pub open_help: Option<KeyEvent>,
pub open_options: Option<KeyEvent>,
pub move_left: Option<KeyEvent>,
pub move_right: Option<KeyEvent>,
pub tree_collapse_recursive: Option<KeyEvent>,
pub tree_expand_recursive: Option<KeyEvent>,
pub home: Option<KeyEvent>,
pub end: Option<KeyEvent>,
pub move_up: Option<KeyEvent>,
pub move_down: Option<KeyEvent>,
pub popup_up: Option<KeyEvent>,
pub popup_down: Option<KeyEvent>,
pub page_down: Option<KeyEvent>,
pub page_up: Option<KeyEvent>,
pub shift_up: Option<KeyEvent>,
pub shift_down: Option<KeyEvent>,
pub enter: Option<KeyEvent>,
pub blame: Option<KeyEvent>,
pub edit_file: Option<KeyEvent>,
pub file_history: Option<KeyEvent>,
pub status_stage_all: Option<KeyEvent>,
pub status_reset_item: Option<KeyEvent>,
pub status_ignore_file: Option<KeyEvent>,
pub diff_stage_lines: Option<KeyEvent>,
pub diff_reset_lines: Option<KeyEvent>,
pub stashing_save: Option<KeyEvent>,
pub stashing_toggle_untracked: Option<KeyEvent>,
pub stashing_toggle_index: Option<KeyEvent>,
pub stash_apply: Option<KeyEvent>,
pub stash_open: Option<KeyEvent>,
pub stash_drop: Option<KeyEvent>,
pub cmd_bar_toggle: Option<KeyEvent>,
pub log_tag_commit: Option<KeyEvent>,
pub log_mark_commit: Option<KeyEvent>,
pub commit_amend: Option<KeyEvent>,
pub copy: Option<KeyEvent>,
pub create_branch: Option<KeyEvent>,
pub rename_branch: Option<KeyEvent>,
pub select_branch: Option<KeyEvent>,
pub delete_branch: Option<KeyEvent>,
pub merge_branch: Option<KeyEvent>,
pub rebase_branch: Option<KeyEvent>,
pub compare_commits: Option<KeyEvent>,
pub tags: Option<KeyEvent>,
pub delete_tag: Option<KeyEvent>,
pub select_tag: Option<KeyEvent>,
pub push: Option<KeyEvent>,
pub open_file_tree: Option<KeyEvent>,
pub file_find: Option<KeyEvent>,
pub force_push: Option<KeyEvent>,
pub pull: Option<KeyEvent>,
pub abort_merge: Option<KeyEvent>,
pub undo_commit: Option<KeyEvent>,
pub stage_unstage_item: Option<KeyEvent>,
pub tag_annotate: Option<KeyEvent>,
pub tab_status: Option<GituiKeyEvent>,
pub tab_log: Option<GituiKeyEvent>,
pub tab_files: Option<GituiKeyEvent>,
pub tab_stashing: Option<GituiKeyEvent>,
pub tab_stashes: Option<GituiKeyEvent>,
pub tab_toggle: Option<GituiKeyEvent>,
pub tab_toggle_reverse: Option<GituiKeyEvent>,
pub toggle_workarea: Option<GituiKeyEvent>,
pub focus_right: Option<GituiKeyEvent>,
pub focus_left: Option<GituiKeyEvent>,
pub focus_above: Option<GituiKeyEvent>,
pub focus_below: Option<GituiKeyEvent>,
pub exit: Option<GituiKeyEvent>,
pub quit: Option<GituiKeyEvent>,
pub exit_popup: Option<GituiKeyEvent>,
pub open_commit: Option<GituiKeyEvent>,
pub open_commit_editor: Option<GituiKeyEvent>,
pub open_help: Option<GituiKeyEvent>,
pub open_options: Option<GituiKeyEvent>,
pub move_left: Option<GituiKeyEvent>,
pub move_right: Option<GituiKeyEvent>,
pub tree_collapse_recursive: Option<GituiKeyEvent>,
pub tree_expand_recursive: Option<GituiKeyEvent>,
pub home: Option<GituiKeyEvent>,
pub end: Option<GituiKeyEvent>,
pub move_up: Option<GituiKeyEvent>,
pub move_down: Option<GituiKeyEvent>,
pub popup_up: Option<GituiKeyEvent>,
pub popup_down: Option<GituiKeyEvent>,
pub page_down: Option<GituiKeyEvent>,
pub page_up: Option<GituiKeyEvent>,
pub shift_up: Option<GituiKeyEvent>,
pub shift_down: Option<GituiKeyEvent>,
pub enter: Option<GituiKeyEvent>,
pub blame: Option<GituiKeyEvent>,
pub edit_file: Option<GituiKeyEvent>,
pub file_history: Option<GituiKeyEvent>,
pub status_stage_all: Option<GituiKeyEvent>,
pub status_reset_item: Option<GituiKeyEvent>,
pub status_ignore_file: Option<GituiKeyEvent>,
pub diff_stage_lines: Option<GituiKeyEvent>,
pub diff_reset_lines: Option<GituiKeyEvent>,
pub stashing_save: Option<GituiKeyEvent>,
pub stashing_toggle_untracked: Option<GituiKeyEvent>,
pub stashing_toggle_index: Option<GituiKeyEvent>,
pub stash_apply: Option<GituiKeyEvent>,
pub stash_open: Option<GituiKeyEvent>,
pub stash_drop: Option<GituiKeyEvent>,
pub cmd_bar_toggle: Option<GituiKeyEvent>,
pub log_tag_commit: Option<GituiKeyEvent>,
pub log_mark_commit: Option<GituiKeyEvent>,
pub commit_amend: Option<GituiKeyEvent>,
pub copy: Option<GituiKeyEvent>,
pub create_branch: Option<GituiKeyEvent>,
pub rename_branch: Option<GituiKeyEvent>,
pub select_branch: Option<GituiKeyEvent>,
pub delete_branch: Option<GituiKeyEvent>,
pub merge_branch: Option<GituiKeyEvent>,
pub rebase_branch: Option<GituiKeyEvent>,
pub compare_commits: Option<GituiKeyEvent>,
pub tags: Option<GituiKeyEvent>,
pub delete_tag: Option<GituiKeyEvent>,
pub select_tag: Option<GituiKeyEvent>,
pub push: Option<GituiKeyEvent>,
pub open_file_tree: Option<GituiKeyEvent>,
pub file_find: Option<GituiKeyEvent>,
pub force_push: Option<GituiKeyEvent>,
pub pull: Option<GituiKeyEvent>,
pub abort_merge: Option<GituiKeyEvent>,
pub undo_commit: Option<GituiKeyEvent>,
pub stage_unstage_item: Option<GituiKeyEvent>,
pub tag_annotate: Option<GituiKeyEvent>,
}
impl KeysListFile {

View File

@ -4,3 +4,4 @@ mod key_list_file;
mod symbols;
pub use key_config::{KeyConfig, SharedKeyConfig};
pub use key_list::key_match;

View File

@ -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,

View File

@ -98,7 +98,7 @@ impl Component for FilesTab {
fn event(
&mut self,
ev: crossterm::event::Event,
ev: &crossterm::event::Event,
) -> Result<EventState> {
if self.visible {
return self.files.event(ev);

View File

@ -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<EventState> {
//TODO: cleanup
#[allow(clippy::too_many_lines)]
fn event(&mut self, ev: &Event) -> Result<EventState> {
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

View File

@ -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<EventState> {
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()?;

View File

@ -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<EventState> {
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();
}
}

View File

@ -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<EventState> {
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(

View File

@ -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<MoveSelection> {
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 {