Implement the password-store tree sidebar
This commit is contained in:
@@ -11,6 +11,19 @@ pub enum Action {
|
||||
Command,
|
||||
Cancel,
|
||||
Lock,
|
||||
Refresh,
|
||||
Next,
|
||||
Previous,
|
||||
PageDown,
|
||||
PageUp,
|
||||
First,
|
||||
Last,
|
||||
Parent,
|
||||
Child,
|
||||
Activate,
|
||||
Filter,
|
||||
NextMatch,
|
||||
PreviousMatch,
|
||||
FocusNext,
|
||||
FocusPrevious,
|
||||
}
|
||||
@@ -27,7 +40,7 @@ pub struct ActionSpec {
|
||||
pub action: Action,
|
||||
pub label: &'static str,
|
||||
pub command: &'static str,
|
||||
pub binding: KeyBinding,
|
||||
pub bindings: &'static [KeyBinding],
|
||||
modes: &'static [Mode],
|
||||
}
|
||||
|
||||
@@ -51,82 +64,163 @@ const ALL: &[Mode] = &[
|
||||
Mode::Locked,
|
||||
];
|
||||
|
||||
macro_rules! keys {
|
||||
($(($code:expr, $modifiers:expr, $display:expr)),+ $(,)?) => {
|
||||
&[$(KeyBinding { code: $code, modifiers: $modifiers, display: $display }),+]
|
||||
};
|
||||
}
|
||||
|
||||
pub static ACTIONS: &[ActionSpec] = &[
|
||||
ActionSpec {
|
||||
action: Action::Quit,
|
||||
label: "quit",
|
||||
command: "quit",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::Char('q'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
display: "q",
|
||||
},
|
||||
bindings: keys!((KeyCode::Char('q'), KeyModifiers::NONE, "q")),
|
||||
modes: BROWSER_LIKE,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Help,
|
||||
label: "help",
|
||||
command: "help",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::Char('?'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
display: "?",
|
||||
},
|
||||
bindings: keys!((KeyCode::Char('?'), KeyModifiers::NONE, "?")),
|
||||
modes: UNLOCKED,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Command,
|
||||
label: "command",
|
||||
command: "command",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::Char(':'),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
display: ":",
|
||||
},
|
||||
bindings: keys!((KeyCode::Char(':'), KeyModifiers::NONE, ":")),
|
||||
modes: UNLOCKED,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Cancel,
|
||||
label: "back",
|
||||
command: "cancel",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::Esc,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
display: "Esc",
|
||||
},
|
||||
bindings: keys!((KeyCode::Esc, KeyModifiers::NONE, "Esc")),
|
||||
modes: OVERLAYS,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Lock,
|
||||
label: "lock",
|
||||
command: "lock",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::Char('l'),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
display: "C-l",
|
||||
},
|
||||
bindings: keys!((KeyCode::Char('l'), KeyModifiers::CONTROL, "C-l")),
|
||||
modes: UNLOCKED,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Refresh,
|
||||
label: "refresh",
|
||||
command: "refresh",
|
||||
bindings: keys!((KeyCode::Char('r'), KeyModifiers::NONE, "r")),
|
||||
modes: BROWSER_LIKE,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Next,
|
||||
label: "next",
|
||||
command: "next",
|
||||
bindings: keys!(
|
||||
(KeyCode::Char('j'), KeyModifiers::NONE, "j"),
|
||||
(KeyCode::Down, KeyModifiers::NONE, "↓"),
|
||||
),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Previous,
|
||||
label: "previous",
|
||||
command: "previous",
|
||||
bindings: keys!(
|
||||
(KeyCode::Char('k'), KeyModifiers::NONE, "k"),
|
||||
(KeyCode::Up, KeyModifiers::NONE, "↑"),
|
||||
),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::PageDown,
|
||||
label: "page down",
|
||||
command: "page-down",
|
||||
bindings: keys!((KeyCode::PageDown, KeyModifiers::NONE, "PgDn")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::PageUp,
|
||||
label: "page up",
|
||||
command: "page-up",
|
||||
bindings: keys!((KeyCode::PageUp, KeyModifiers::NONE, "PgUp")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::First,
|
||||
label: "first",
|
||||
command: "first",
|
||||
bindings: keys!((KeyCode::Home, KeyModifiers::NONE, "Home")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Last,
|
||||
label: "last",
|
||||
command: "last",
|
||||
bindings: keys!((KeyCode::End, KeyModifiers::NONE, "End")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Parent,
|
||||
label: "parent",
|
||||
command: "parent",
|
||||
bindings: keys!(
|
||||
(KeyCode::Char('h'), KeyModifiers::NONE, "h"),
|
||||
(KeyCode::Left, KeyModifiers::NONE, "←"),
|
||||
),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Child,
|
||||
label: "child",
|
||||
command: "child",
|
||||
bindings: keys!(
|
||||
(KeyCode::Char('l'), KeyModifiers::NONE, "l"),
|
||||
(KeyCode::Right, KeyModifiers::NONE, "→"),
|
||||
),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Activate,
|
||||
label: "open/toggle",
|
||||
command: "open",
|
||||
bindings: keys!((KeyCode::Enter, KeyModifiers::NONE, "Enter")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::Filter,
|
||||
label: "filter",
|
||||
command: "filter",
|
||||
bindings: keys!((KeyCode::Char('/'), KeyModifiers::NONE, "/")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::NextMatch,
|
||||
label: "next match",
|
||||
command: "next-match",
|
||||
bindings: keys!((KeyCode::Char('n'), KeyModifiers::NONE, "n")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::PreviousMatch,
|
||||
label: "previous match",
|
||||
command: "previous-match",
|
||||
bindings: keys!((KeyCode::Char('N'), KeyModifiers::SHIFT, "N")),
|
||||
modes: &[Mode::Browser],
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::FocusNext,
|
||||
label: "next pane",
|
||||
command: "focus-next",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::Tab,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
display: "Tab",
|
||||
},
|
||||
bindings: keys!((KeyCode::Tab, KeyModifiers::NONE, "Tab")),
|
||||
modes: UNLOCKED,
|
||||
},
|
||||
ActionSpec {
|
||||
action: Action::FocusPrevious,
|
||||
label: "previous pane",
|
||||
command: "focus-previous",
|
||||
binding: KeyBinding {
|
||||
code: KeyCode::BackTab,
|
||||
modifiers: KeyModifiers::SHIFT,
|
||||
display: "S-Tab",
|
||||
},
|
||||
bindings: keys!((KeyCode::BackTab, KeyModifiers::SHIFT, "S-Tab")),
|
||||
modes: UNLOCKED,
|
||||
},
|
||||
];
|
||||
@@ -136,8 +230,10 @@ pub fn resolve_key(mode: Mode, code: KeyCode, modifiers: KeyModifiers) -> Option
|
||||
.iter()
|
||||
.find(|spec| {
|
||||
spec.is_available(mode)
|
||||
&& spec.binding.code == code
|
||||
&& spec.binding.modifiers == modifiers
|
||||
&& spec
|
||||
.bindings
|
||||
.iter()
|
||||
.any(|binding| binding.code == code && binding.modifiers == modifiers)
|
||||
})
|
||||
.map(|spec| spec.action)
|
||||
}
|
||||
@@ -160,7 +256,11 @@ mod tests {
|
||||
assert_ne!(action.command, other.command);
|
||||
for mode in ALL {
|
||||
if action.is_available(*mode) && other.is_available(*mode) {
|
||||
assert_ne!(action.binding, other.binding);
|
||||
for binding in action.bindings {
|
||||
for other_binding in other.bindings {
|
||||
assert_ne!(binding, other_binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,10 +271,12 @@ mod tests {
|
||||
fn resolution_and_help_consume_the_same_registry() {
|
||||
for mode in ALL {
|
||||
for spec in available_actions(*mode) {
|
||||
assert_eq!(
|
||||
resolve_key(*mode, spec.binding.code, spec.binding.modifiers),
|
||||
Some(spec.action)
|
||||
);
|
||||
for binding in spec.bindings {
|
||||
assert_eq!(
|
||||
resolve_key(*mode, binding.code, binding.modifiers),
|
||||
Some(spec.action)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user