Skip to content

Customize key binds #234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Aug 26, 2020
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
.DS_Store
/.idea/
flamegraph.svg
KEY_CONFIG.md
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ keywords = [
[dependencies]
scopetime = { path = "./scopetime", version = "0.1" }
asyncgit = { path = "./asyncgit", version = "0.9" }
crossterm = "0.17"
crossterm = { version = "0.17", features = [ "serde" ] }
clap = { version = "2.33", default-features = false }
tui = { version = "0.9", default-features = false, features = ['crossterm'] }
bytesize = { version = "1.0.1", default-features = false}
Expand Down
15 changes: 15 additions & 0 deletions KEY_CONFIG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Key Config

Default using arrow key to navigate the gitui and Ctrl + C to quit the program

The first time Gitui will create `key_config.ron` file automatically.
You can change the every single key bindings of the program as what you like.

The config file format is [Ron format](https://github.com/ron-rs/ron).
And the path differs depending on the operating system:
* `$HOME/Library/Preferences/gitui/key_config.ron` (mac)
* `$XDG_CONFIG_HOME/gitui/key_config.ron` (linux using XDG)
* `$HOME/.config/gitui/key_config.ron` (linux)

Here is a [vim style key config](assets/vim_style_key_config.ron) with `h`, `j`, `k`, `l` to navigate and `Ctrl + C` to leave.
You can use it to replace `key_config.ron` and get a vim style setting.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,6 @@ However, you can customize everything to your liking: See [Themes](THEMES.md).
- [tig](https://github.com/jonas/tig)
- [GitUp](https://github.com/git-up/GitUp)
- It would be nice to come up with a way to have the map view available in a terminal tool

# Key Bindings
You can customize every keybing to your liking: See [Key Config](KEY_CONFIG.md).
66 changes: 66 additions & 0 deletions assets/vim_style_key_config.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// bit for modifiers
// bits: 0 None
// bits: 1 SHIFT
// bits: 2 CONTROL
(
tab_status: ( code: Char('1'), modifiers: ( bits: 0,),),
tab_log: ( code: Char('2'), modifiers: ( bits: 0,),),
tab_stashing: ( code: Char('3'), modifiers: ( bits: 0,),),
tab_stashes: ( code: Char('4'), modifiers: ( bits: 0,),),

tab_toggle: ( code: Tab, modifiers: ( bits: 0,),),
tab_toggle_reverse: ( code: BackTab, modifiers: ( bits: 0,),),
tab_toggle_reverse_windows: ( code: BackTab, modifiers: ( bits: 1,),),

focus_workdir: ( code: Char('w'), modifiers: ( bits: 0,),),
focus_stage: ( code: Char('s'), modifiers: ( bits: 0,),),
focus_right: ( code: Char('l'), modifiers: ( bits: 0,),),
focus_left: ( code: Char('h'), modifiers: ( bits: 0,),),
focus_above: ( code: Char('k'), modifiers: ( bits: 0,),),
focus_below: ( code: Char('j'), modifiers: ( bits: 0,),),

exit: ( code: Char('c'), modifiers: ( bits: 2,),),
exit_popup: ( code: Esc, modifiers: ( bits: 0,),),

close_msg: ( code: Enter, modifiers: ( bits: 0,),),
open_commit: ( code: Char('c'), modifiers: ( bits: 0,),),
open_commit_editor: ( code: Char('E'), modifiers: ( bits: 0,),),
open_help: ( code: F(1), modifiers: ( bits: 0,),),

move_left: ( code: Char('h'), modifiers: ( bits: 0,),),
move_right: ( code: Char('l'), modifiers: ( bits: 0,),),
home: ( code: Home, modifiers: ( bits: 0,),),
end: ( code: End, modifiers: ( bits: 0,),),
move_up: ( code: Char('k'), modifiers: ( bits: 0,),),
move_down: ( code: Char('j'), modifiers: ( bits: 0,),),
page_up: ( code: Char('u'), modifiers: ( bits: 2,),),
page_down: ( code: Char('d'), modifiers: ( bits: 2,),),

shift_up: ( code: Char('K'), modifiers: ( bits: 0,),),
shift_down: ( code: Char('J'), modifiers: ( bits: 0,),),

enter: ( code: Enter, modifiers: ( bits: 0,),),

edit_file: ( code: Char('I'), modifiers: ( bits: 0,),),

status_stage_file: ( code: Enter, modifiers: ( bits: 0,),),
status_stage_all: ( code: Char('a'), modifiers: ( bits: 0,),),
status_reset_file: ( code: Char('U'), modifiers: ( bits: 0,),),

diff_reset_hunk: ( code: Enter, modifiers: ( bits: 0,),),
status_ignore_file: ( code: Char('i'), modifiers: ( bits: 0,),),

stashing_save: ( code: Char('w'), modifiers: ( bits: 0,),),
stashing_toggle_untracked: ( code: Char('u'), modifiers: ( bits: 0,),),
stashing_toggle_index: ( code: Char('m'), modifiers: ( bits: 0,),),

stash_apply: ( code: Enter, modifiers: ( bits: 0,),),
stash_open: ( code: Char('l'), modifiers: ( bits: 0,),),
stash_drop: ( code: Char('D'), modifiers: ( bits: 0,),),

cmd_bar_toggle: ( code: Char('.'), modifiers: ( bits: 0,),),
log_commit_details: ( code: Enter, modifiers: ( bits: 0,),),
log_tag_commit: ( code: Char('t'), modifiers: ( bits: 0,),),
commit_amend: ( code: Char('A'), modifiers: ( bits: 0,),),
copy: ( code: Char('y'), modifiers: ( bits: 0,),),
)
129 changes: 81 additions & 48 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use crate::{
ResetComponent, StashMsgComponent, TagCommitComponent,
},
input::{Input, InputEvent, InputState},
keys,
keys::{KeyConfig, SharedKeyConfig},
queue::{Action, InternalEvent, NeedsUpdate, Queue},
strings::{self, commands, order},
strings::{self, order},
tabs::{Revlog, StashList, Stashing, Status},
ui::style::{SharedTheme, Theme},
};
Expand Down Expand Up @@ -49,6 +49,7 @@ pub struct App {
stashlist_tab: StashList,
queue: Queue,
theme: SharedTheme,
key_config: SharedKeyConfig,
input: Input,

// "Flags"
Expand All @@ -66,45 +67,77 @@ impl App {
let queue = Queue::default();

let theme = Rc::new(Theme::init());
let key_config = Rc::new(KeyConfig::init());

Self {
input,
reset: ResetComponent::new(queue.clone(), theme.clone()),
reset: ResetComponent::new(
queue.clone(),
theme.clone(),
key_config.clone(),
),
commit: CommitComponent::new(
queue.clone(),
theme.clone(),
key_config.clone(),
),
stashmsg_popup: StashMsgComponent::new(
queue.clone(),
theme.clone(),
key_config.clone(),
),
inspect_commit_popup: InspectCommitComponent::new(
&queue,
sender,
theme.clone(),
key_config.clone(),
),
external_editor_popup: ExternalEditorComponent::new(
theme.clone(),
key_config.clone(),
),
tag_commit_popup: TagCommitComponent::new(
queue.clone(),
theme.clone(),
key_config.clone(),
),
do_quit: false,
cmdbar: RefCell::new(CommandBar::new(theme.clone())),
help: HelpComponent::new(theme.clone()),
msg: MsgComponent::new(theme.clone()),
cmdbar: RefCell::new(CommandBar::new(
theme.clone(),
key_config.clone(),
)),
help: HelpComponent::new(
theme.clone(),
key_config.clone(),
),
msg: MsgComponent::new(theme.clone(), key_config.clone()),
tab: 0,
revlog: Revlog::new(&queue, sender, theme.clone()),
status_tab: Status::new(&queue, sender, theme.clone()),
revlog: Revlog::new(
&queue,
sender,
theme.clone(),
key_config.clone(),
),
status_tab: Status::new(
&queue,
sender,
theme.clone(),
key_config.clone(),
),
stashing_tab: Stashing::new(
sender,
&queue,
theme.clone(),
key_config.clone(),
),
stashlist_tab: StashList::new(
&queue,
theme.clone(),
key_config.clone(),
),
stashlist_tab: StashList::new(&queue, theme.clone()),
queue,
theme,
key_config,
requires_redraw: Cell::new(false),
file_to_open: None,
}
Expand Down Expand Up @@ -160,30 +193,26 @@ impl App {
if event_pump(ev, self.components_mut().as_mut_slice())? {
flags.insert(NeedsUpdate::COMMANDS);
} else if let Event::Key(k) = ev {
let new_flags = match k {
keys::TAB_TOGGLE => {
self.toggle_tabs(false)?;
NeedsUpdate::COMMANDS
}
keys::TAB_TOGGLE_REVERSE
| keys::TAB_TOGGLE_REVERSE_WINDOWS => {
self.toggle_tabs(true)?;
NeedsUpdate::COMMANDS
}
keys::TAB_1
| keys::TAB_2
| keys::TAB_3
| keys::TAB_4 => {
self.switch_tab(k)?;
NeedsUpdate::COMMANDS
}

keys::CMD_BAR_TOGGLE => {
self.cmdbar.borrow_mut().toggle_more();
NeedsUpdate::empty()
}

_ => NeedsUpdate::empty(),
let new_flags = if k == self.key_config.tab_toggle {
self.toggle_tabs(false)?;
NeedsUpdate::COMMANDS
} else if k == self.key_config.tab_toggle_reverse
|| k == self.key_config.tab_toggle_reverse_windows
{
self.toggle_tabs(true)?;
NeedsUpdate::COMMANDS
} else if k == self.key_config.tab_status
|| k == self.key_config.tab_log
|| k == self.key_config.tab_stashing
|| k == self.key_config.tab_stashes
{
self.switch_tab(k)?;
NeedsUpdate::COMMANDS
} else if k == self.key_config.cmd_bar_toggle {
self.cmdbar.borrow_mut().toggle_more();
NeedsUpdate::empty()
} else {
NeedsUpdate::empty()
};

flags.insert(new_flags);
Expand Down Expand Up @@ -312,7 +341,7 @@ impl App {

fn check_quit_key(&mut self, ev: Event) -> bool {
if let Event::Key(e) = ev {
if let keys::EXIT = e {
if e == self.key_config.exit {
self.do_quit = true;
return true;
}
Expand Down Expand Up @@ -341,12 +370,14 @@ impl App {
}

fn switch_tab(&mut self, k: KeyEvent) -> Result<()> {
match k {
keys::TAB_1 => self.set_tab(0)?,
keys::TAB_2 => self.set_tab(1)?,
keys::TAB_3 => self.set_tab(2)?,
keys::TAB_4 => self.set_tab(3)?,
_ => (),
if k == self.key_config.tab_status {
self.set_tab(0)?
} else if k == self.key_config.tab_log {
self.set_tab(1)?
} else if k == self.key_config.tab_stashing {
self.set_tab(2)?
} else if k == self.key_config.tab_stashes {
self.set_tab(3)?
}

Ok(())
Expand Down Expand Up @@ -458,15 +489,17 @@ impl App {

res.push(
CommandInfo::new(
commands::TOGGLE_TABS,
strings::commands::toggle_tabs(&self.key_config),
true,
!self.any_popup_visible(),
)
.order(order::NAV),
);
res.push(
CommandInfo::new(
commands::TOGGLE_TABS_DIRECT,
strings::commands::toggle_tabs_direct(
&self.key_config,
),
true,
!self.any_popup_visible(),
)
Expand All @@ -475,7 +508,7 @@ impl App {

res.push(
CommandInfo::new(
commands::QUIT,
strings::commands::quit(&self.key_config),
true,
!self.any_popup_visible(),
)
Expand Down Expand Up @@ -531,10 +564,10 @@ impl App {
});

let tabs = &[
strings::TAB_STATUS,
strings::TAB_LOG,
strings::TAB_STASHING,
strings::TAB_STASHES,
strings::tab_status(&self.key_config),
strings::tab_log(&self.key_config),
strings::tab_stashing(&self.key_config),
strings::tab_stashes(&self.key_config),
];

f.render_widget(
Expand All @@ -547,7 +580,7 @@ impl App {
.titles(tabs)
.style(self.theme.tab(false))
.highlight_style(self.theme.tab(true))
.divider(strings::TAB_DIVIDER)
.divider(&strings::tab_divider(&self.key_config))
.select(self.tab),
r,
);
Expand Down
Loading