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
|
use tuikit::prelude::{Event, Key, MouseButton};
use crate::event_exec::EventExec;
use crate::fm_error::FmResult;
use crate::keybindings::Bindings;
use crate::mode::{InputSimple, MarkAction, Mode, Navigate};
use crate::status::Status;
/// Struct which mutates `tabs.selected()..
/// Holds a mapping which can't be static since it's read from a config file.
/// All keys are mapped to relevent events on tabs.selected().
/// Keybindings are read from `Config`.
pub struct EventDispatcher {
binds: Bindings,
}
impl EventDispatcher {
/// Creates a map of configurable keybindings to `EventChar`
/// The `EventChar` is then associated to a `tabs.selected(). method.
pub fn new(binds: Bindings) -> Self {
Self { binds }
}
/// Reaction to received events.
/// Only non keyboard events are dealt here directly.
/// Keyboard events are configurable and are sent to specific functions
/// which needs to know those keybindings.
pub fn dispatch(&self, status: &mut Status, ev: Event) -> FmResult<()> {
match ev {
Event::Key(Key::WheelUp(_, col, _)) => {
EventExec::event_select_pane(status, col)?;
EventExec::event_move_up(status)
}
Event::Key(Key::WheelDown(_, col, _)) => {
EventExec::event_select_pane(status, col)?;
EventExec::event_move_down(status)
}
Event::Key(Key::SingleClick(MouseButton::Left, row, col)) => {
EventExec::event_select_pane(status, col)?;
EventExec::event_select_row(status, row)
}
Event::Key(Key::SingleClick(MouseButton::Right, row, col))
| Event::Key(Key::DoubleClick(MouseButton::Left, row, col)) => {
EventExec::event_select_pane(status, col)?;
EventExec::event_select_row(status, row)?;
EventExec::event_right_click(status)
}
Event::User(_) => EventExec::refresh_status(status),
Event::Resize { width, height } => EventExec::resize(status, width, height),
Event::Key(Key::Char(c)) => self.char(status, Key::Char(c)),
Event::Key(key) => self.key_matcher(status, key),
_ => Ok(()),
}
}
fn key_matcher(&self, status: &mut Status, key: Key) -> FmResult<()> {
match self.binds.get(&key) {
Some(action) => action.matcher(status),
None => Ok(()),
}
}
fn char(&self, status: &mut Status, key_char: Key) -> FmResult<()> {
match key_char {
Key::Char(c) => match status.selected_non_mut().mode {
Mode::InputSimple(InputSimple::Marks(MarkAction::Jump)) => {
EventExec::exec_marks_jump(status, c)
}
Mode::InputSimple(InputSimple::Marks(MarkAction::New)) => {
EventExec::exec_marks_new(status, c)
}
Mode::InputSimple(InputSimple::Sort) => EventExec::event_leave_sort(status, c),
Mode::InputSimple(InputSimple::RegexMatch) => {
EventExec::event_text_insertion(status.selected(), c);
status.select_from_regex()?;
Ok(())
}
Mode::InputSimple(_) => {
EventExec::event_text_insertion(status.selected(), c);
Ok(())
}
Mode::InputCompleted(_) => {
EventExec::event_text_insert_and_complete(status.selected(), c)
}
Mode::Normal | Mode::Tree => match self.binds.get(&key_char) {
Some(event_char) => event_char.matcher(status),
None => Ok(()),
},
Mode::NeedConfirmation(confirmed_action) => {
if c == 'y' {
let _ = EventExec::exec_confirmed_action(status, confirmed_action);
}
EventExec::event_leave_need_confirmation(status.selected());
Ok(())
}
Mode::Navigate(Navigate::Trash) if c == 'x' => {
EventExec::event_trash_remove_file(status)
}
Mode::Preview | Mode::Navigate(_) => {
status.selected().set_mode(Mode::Normal);
EventExec::event_normal(status.selected())
}
},
_ => Ok(()),
}
}
}
|