1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
use super::{Event, KeyCode, KeyEvent, KeyModifiers};
#[derive(Debug)]
pub struct KeyBindings {
pub(crate) abort: Vec<Event>,
pub(crate) action_break: Vec<Event>,
pub(crate) action_drop: Vec<Event>,
pub(crate) action_edit: Vec<Event>,
pub(crate) action_fixup: Vec<Event>,
pub(crate) action_pick: Vec<Event>,
pub(crate) action_reword: Vec<Event>,
pub(crate) action_squash: Vec<Event>,
pub(crate) confirm_yes: Vec<Event>,
pub(crate) edit: Vec<Event>,
pub(crate) force_abort: Vec<Event>,
pub(crate) force_rebase: Vec<Event>,
pub(crate) help: Vec<Event>,
pub(crate) insert_line: Vec<Event>,
pub(crate) move_down: Vec<Event>,
pub(crate) move_down_step: Vec<Event>,
pub(crate) move_end: Vec<Event>,
pub(crate) move_home: Vec<Event>,
pub(crate) move_left: Vec<Event>,
pub(crate) move_right: Vec<Event>,
pub(crate) move_selection_down: Vec<Event>,
pub(crate) move_selection_up: Vec<Event>,
pub(crate) move_up: Vec<Event>,
pub(crate) move_up_step: Vec<Event>,
pub(crate) open_in_external_editor: Vec<Event>,
pub(crate) rebase: Vec<Event>,
pub(crate) redo: Vec<Event>,
pub(crate) remove_line: Vec<Event>,
pub(crate) show_commit: Vec<Event>,
pub(crate) show_diff: Vec<Event>,
pub(crate) toggle_visual_mode: Vec<Event>,
pub(crate) undo: Vec<Event>,
}
fn map_keybindings(bindings: &[String]) -> Vec<Event> {
bindings
.iter()
.map(|b| {
let mut key = String::from(b);
let mut modifiers = KeyModifiers::empty();
if key.contains("Control") {
key = key.replace("Control", "");
modifiers.insert(KeyModifiers::CONTROL);
}
if key.contains("Alt") {
key = key.replace("Alt", "");
modifiers.insert(KeyModifiers::ALT);
}
if key.contains("Shift") {
key = key.replace("Shift", "");
modifiers.insert(KeyModifiers::SHIFT);
}
let code = match key.as_str() {
"Backspace" => KeyCode::Backspace,
"BackTab" => KeyCode::BackTab,
"Delete" => KeyCode::Delete,
"Down" => KeyCode::Down,
"End" => KeyCode::End,
"Enter" => KeyCode::Enter,
"Esc" => KeyCode::Esc,
"Home" => KeyCode::Home,
"Insert" => KeyCode::Insert,
"Left" => KeyCode::Left,
"PageDown" => KeyCode::PageDown,
"PageUp" => KeyCode::PageUp,
"Right" => KeyCode::Right,
"Tab" => KeyCode::Tab,
"Up" => KeyCode::Up,
// assume that this is an F key
k if k.len() > 1 => {
let key_number = k[1..].parse::<u8>().unwrap_or(1);
KeyCode::F(key_number)
},
k => {
let c = k.chars().next().unwrap();
KeyCode::Char(c)
},
};
Event::Key(KeyEvent::new(code, modifiers))
})
.collect()
}
impl KeyBindings {
pub fn new(key_bindings: &config::KeyBindings) -> Self {
Self {
abort: map_keybindings(&key_bindings.abort),
action_break: map_keybindings(&key_bindings.action_break),
action_drop: map_keybindings(&key_bindings.action_drop),
action_edit: map_keybindings(&key_bindings.action_edit),
action_fixup: map_keybindings(&key_bindings.action_fixup),
action_pick: map_keybindings(&key_bindings.action_pick),
action_reword: map_keybindings(&key_bindings.action_reword),
action_squash: map_keybindings(&key_bindings.action_squash),
edit: map_keybindings(&key_bindings.edit),
force_abort: map_keybindings(&key_bindings.force_abort),
force_rebase: map_keybindings(&key_bindings.force_rebase),
help: map_keybindings(&key_bindings.help),
insert_line: map_keybindings(&key_bindings.insert_line),
move_down: map_keybindings(&key_bindings.move_down),
move_down_step: map_keybindings(&key_bindings.move_down_step),
move_end: map_keybindings(&key_bindings.move_end),
move_home: map_keybindings(&key_bindings.move_home),
move_left: map_keybindings(&key_bindings.move_left),
move_right: map_keybindings(&key_bindings.move_right),
move_selection_down: map_keybindings(&key_bindings.move_selection_down),
move_selection_up: map_keybindings(&key_bindings.move_selection_up),
move_up: map_keybindings(&key_bindings.move_up),
move_up_step: map_keybindings(&key_bindings.move_up_step),
open_in_external_editor: map_keybindings(&key_bindings.open_in_external_editor),
rebase: map_keybindings(&key_bindings.rebase),
redo: map_keybindings(&key_bindings.redo),
remove_line: map_keybindings(&key_bindings.remove_line),
show_commit: map_keybindings(&key_bindings.show_commit),
show_diff: map_keybindings(&key_bindings.show_diff),
toggle_visual_mode: map_keybindings(&key_bindings.toggle_visual_mode),
undo: map_keybindings(&key_bindings.undo),
confirm_yes: map_keybindings(&key_bindings.confirm_yes),
}
}
}
#[cfg(test)]
mod tests {
use config::testutil::create_config;
use rstest::rstest;
use super::*;
#[test]
fn new() {
KeyBindings::new(&create_config().key_bindings);
}
#[test]
fn map_keybindings_with_modifiers() {
assert_eq!(map_keybindings(&[String::from("ControlAltShifta")]), vec![Event::Key(
KeyEvent {
code: KeyCode::Char('a'),
modifiers: KeyModifiers::all()
}
)]);
}
#[rstest(
binding,
key_code,
case::backspace("Backspace", KeyCode::Backspace),
case::back_tab("BackTab", KeyCode::BackTab),
case::delete("Delete", KeyCode::Delete),
case::down("Down", KeyCode::Down),
case::end("End", KeyCode::End),
case::enter("Enter", KeyCode::Enter),
case::esc("Esc", KeyCode::Esc),
case::home("Home", KeyCode::Home),
case::insert("Insert", KeyCode::Insert),
case::left("Left", KeyCode::Left),
case::page_down("PageDown", KeyCode::PageDown),
case::page_up("PageUp", KeyCode::PageUp),
case::right("Right", KeyCode::Right),
case::tab("Tab", KeyCode::Tab),
case::up("Up", KeyCode::Up),
case::function_in_range("F10", KeyCode::F(10)),
case::function_out_of_range("F10000", KeyCode::F(1)),
case::char("a", KeyCode::Char('a'))
)]
fn map_keybindings_key_code(binding: &str, key_code: KeyCode) {
assert_eq!(map_keybindings(&[String::from(binding)]), vec![Event::from(key_code)]);
}
}
|