Support easier key remaps

Also,

- Add key binding `~` to go to homedir.
- Add customizable cursor and prompts.
- Improve the help menus.
pull/48/head v0.4.0
Arijit Basu 3 years ago committed by Arijit Basu
parent d34dc77ea5
commit 055c1083d6

@ -889,10 +889,12 @@ impl App {
fn handle_key(mut self, key: Key) -> Result<Self> {
let kb = self.mode.key_bindings.clone();
let key_str = key.to_string();
let default = kb.default.clone();
let msgs = kb
.on_key
.get(&key.to_string())
.get(&key_str)
.or_else(|| kb.remaps.get(&key_str).and_then(|k| kb.on_key.get(k)))
.map(|a| Some(a.messages.clone()))
.unwrap_or_else(|| {
if key.is_alphabet() {
@ -1419,14 +1421,23 @@ impl App {
.map(|l| match l {
HelpMenuLine::Paragraph(p) => format!("\t{}\n", p),
HelpMenuLine::KeyMap(k, h) => {
format!(" {:15} | {}\n", k, h)
let remaps = self
.mode()
.key_bindings
.remaps
.iter()
.filter(|(_, t)| t == &k)
.map(|(f, _)| f.clone())
.collect::<Vec<String>>()
.join(", ");
format!(" {:15} | {:25} | {}\n", k, remaps, h)
}
})
.collect::<Vec<String>>()
.join("");
format!(
"### {}\n\n key | action\n --------------- | ------\n{}\n",
"### {}\n\n key | remaps | action\n --------------- | ------------------------- |------\n{}\n",
name, help
)
})

@ -160,6 +160,14 @@ pub struct UiElement {
pub style: Style,
}
impl UiElement {
fn extend(mut self, other: Self) -> Self {
self.format = other.format.or(self.format);
self.style = other.style.extend(self.style);
self
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TableRowConfig {
@ -250,6 +258,12 @@ pub struct GeneralConfig {
#[serde(default)]
pub show_hidden: Option<bool>,
#[serde(default)]
pub cursor: UiElement,
#[serde(default)]
pub prompt: UiElement,
#[serde(default)]
pub table: TableConfig,
@ -266,6 +280,8 @@ pub struct GeneralConfig {
impl GeneralConfig {
pub fn extend(mut self, other: Self) -> Self {
self.show_hidden = other.show_hidden.or(self.show_hidden);
self.cursor = other.cursor.extend(self.cursor);
self.prompt = other.prompt.extend(self.prompt);
self.table = other.table.extend(self.table);
self.default_ui = other.default_ui.extend(self.default_ui);
self.focus_ui = other.focus_ui.extend(self.focus_ui);
@ -277,6 +293,9 @@ impl GeneralConfig {
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct KeyBindings {
#[serde(default)]
pub remaps: BTreeMap<String, String>,
#[serde(default)]
pub on_key: BTreeMap<String, Action>,
@ -295,6 +314,8 @@ pub struct KeyBindings {
impl KeyBindings {
pub fn extend(mut self, mut other: Self) -> Self {
other.remaps.extend(self.remaps);
self.remaps = other.remaps;
other.on_key.extend(self.on_key);
self.on_key = other.on_key;
self.on_alphabet = other.on_alphabet.or(self.on_alphabet);

@ -1,6 +1,10 @@
version: v0.4.0
general:
show_hidden: false
prompt:
format: "> "
cursor:
format:
table:
header:
cols:
@ -180,6 +184,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
c:
help: copy here
@ -226,6 +231,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
enter:
help: create file
@ -266,6 +272,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
enter:
help: create directory
@ -306,6 +313,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
ctrl-c:
help: cancel & quit
@ -337,6 +345,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
enter:
help: rename
@ -377,6 +386,15 @@ modes:
help: null
extra_help: null
key_bindings:
remaps:
/: ctrl-f
h: left
j: down
k: up
l: right
v: space
q: ctrl-c
on_key:
'#':
help: null
@ -390,12 +408,6 @@ modes:
input: .
case_sensitive: false
- Explore
/:
help: null
messages:
- SwitchMode: search
- SetInputBuffer: ''
- Explore
':':
help: action
messages:
@ -405,16 +417,22 @@ modes:
messages:
- BashExec: |
${PAGER:-less} "${XPLR_PIPE_GLOBAL_HELP_MENU_OUT}"
'~':
help: go home
messages:
- BashExecSilently: |
echo "ChangeDirectory: ${HOME:?}" >> "${XPLR_PIPE_MSG_IN:?}"
echo "Explore" >> "${XPLR_PIPE_MSG_IN:?}"
G:
help: go to bottom
messages:
- FocusLast
ctrl-c:
help: cancel & quit [q]
help: cancel & quit
messages:
- Terminate
ctrl-f:
help: search [/]
help: search
messages:
- SwitchMode: search
- SetInputBuffer: ''
@ -424,7 +442,7 @@ modes:
messages:
- SwitchMode: delete
down:
help: down [j]
help: down
messages:
- FocusNext
enter:
@ -435,55 +453,29 @@ modes:
help: go to
messages:
- SwitchMode: go to
h:
help: null
messages:
- Back
j:
help: null
messages:
- FocusNext
k:
help: null
messages:
- FocusPrevious
l:
help: null
messages:
- Enter
left:
help: back [h]
help: back
messages:
- Back
q:
help: null
messages:
- Terminate
r:
help: rename
messages:
- SwitchMode: rename
- BashExecSilently: |
echo "SetInputBuffer: $(basename ${XPLR_FOCUS_PATH})" >> "${XPLR_PIPE_MSG_IN:?}"
right:
help: enter [l]
help: enter
messages:
- Enter
space:
help: toggle selection [v]
help: toggle selection
messages:
- ToggleSelection
- FocusNext
up:
help: up [k]
help: up
messages:
- FocusPrevious
v:
help: null
messages:
- ToggleSelection
- FocusNext
on_alphabet: null
on_number:
help: input
@ -501,6 +493,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
ctrl-c:
help: cancel & quit
@ -532,6 +525,9 @@ modes:
help: null
extra_help: null
key_bindings:
remaps:
j: down
k: up
on_key:
backspace:
help: clear
@ -542,7 +538,7 @@ modes:
messages:
- Terminate
down:
help: to down [j]
help: to down
messages:
- FocusNextByRelativeIndexFromInput
- SwitchMode: default
@ -551,18 +547,8 @@ modes:
messages:
- FocusByIndexFromInput
- SwitchMode: default
j:
help: null
messages:
- FocusNextByRelativeIndexFromInput
- SwitchMode: default
k:
help: null
messages:
- FocusPreviousByRelativeIndexFromInput
- SwitchMode: default
up:
help: to up [k]
help: to up
messages:
- FocusPreviousByRelativeIndexFromInput
- SwitchMode: default
@ -581,6 +567,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
d:
help: delete
@ -637,6 +624,9 @@ modes:
help: null
extra_help: null
key_bindings:
remaps:
q: ctrl-c
on_number:
help: go to index
messages:
@ -679,11 +669,7 @@ modes:
- SwitchMode: default
ctrl-c:
help: cancel & quit [q]
messages:
- Terminate
q:
help: cancel & quit
messages:
- Terminate
@ -695,6 +681,7 @@ modes:
help: null
extra_help: null
key_bindings:
remaps: {}
on_key:
backspace:
help: clear

@ -9,6 +9,7 @@ use tui::backend::Backend;
use tui::layout::Rect;
use tui::layout::{Constraint as TuiConstraint, Direction, Layout};
use tui::style::{Color, Style};
use tui::text::{Span, Spans};
use tui::widgets::{
Block, Borders, Cell, List, ListItem, ListState, Paragraph, Row, Table, TableState,
};
@ -282,7 +283,18 @@ fn draw_help_menu<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &
.into_iter()
.map(|l| match l {
HelpMenuLine::Paragraph(p) => Row::new([Cell::from(p)].to_vec()),
HelpMenuLine::KeyMap(k, h) => Row::new([Cell::from(k), Cell::from(h)].to_vec()),
HelpMenuLine::KeyMap(k, h) => {
let remaps = app
.mode()
.key_bindings
.remaps
.iter()
.filter(|(_, t)| t == &&k)
.map(|(f, _)| f.clone())
.collect::<Vec<String>>()
.join("|");
Row::new([Cell::from(k), Cell::from(remaps), Cell::from(h)].to_vec())
}
})
.collect::<Vec<Row>>();
@ -292,15 +304,36 @@ fn draw_help_menu<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &
.borders(Borders::ALL)
.title(format!(" Help [{}] ", &app.mode().name)),
)
.widths(&[TuiConstraint::Percentage(30), TuiConstraint::Percentage(70)]);
.widths(&[
TuiConstraint::Percentage(20),
TuiConstraint::Percentage(20),
TuiConstraint::Percentage(60),
]);
f.render_widget(help_menu, rect);
}
fn draw_input_buffer<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &Handlebars) {
let input_buf = Paragraph::new(format!(
"> {}",
app.input_buffer().unwrap_or_else(|| "".into())
))
let input_buf = Paragraph::new(Spans::from(vec![
Span::styled(
app.config()
.general
.prompt
.format
.clone()
.unwrap_or_default(),
app.config().general.prompt.style.into(),
),
Span::raw(app.input_buffer().unwrap_or_else(|| "".into())),
Span::styled(
app.config()
.general
.cursor
.format
.clone()
.unwrap_or_default(),
app.config().general.cursor.style.into(),
),
]))
.block(Block::default().borders(Borders::ALL).title(" Input "));
f.render_widget(input_buf, rect);
}

Loading…
Cancel
Save