mirror of
https://github.com/sayanarijit/xplr
synced 2024-11-10 07:10:45 +00:00
Support easier key remaps
Also, - Add key binding `~` to go to homedir. - Add customizable cursor and prompts. - Improve the help menus.
This commit is contained in:
parent
d34dc77ea5
commit
055c1083d6
17
src/app.rs
17
src/app.rs
@ -889,10 +889,12 @@ impl App {
|
|||||||
|
|
||||||
fn handle_key(mut self, key: Key) -> Result<Self> {
|
fn handle_key(mut self, key: Key) -> Result<Self> {
|
||||||
let kb = self.mode.key_bindings.clone();
|
let kb = self.mode.key_bindings.clone();
|
||||||
|
let key_str = key.to_string();
|
||||||
let default = kb.default.clone();
|
let default = kb.default.clone();
|
||||||
let msgs = kb
|
let msgs = kb
|
||||||
.on_key
|
.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()))
|
.map(|a| Some(a.messages.clone()))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
if key.is_alphabet() {
|
if key.is_alphabet() {
|
||||||
@ -1419,14 +1421,23 @@ impl App {
|
|||||||
.map(|l| match l {
|
.map(|l| match l {
|
||||||
HelpMenuLine::Paragraph(p) => format!("\t{}\n", p),
|
HelpMenuLine::Paragraph(p) => format!("\t{}\n", p),
|
||||||
HelpMenuLine::KeyMap(k, h) => {
|
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>>()
|
.collect::<Vec<String>>()
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
format!(
|
format!(
|
||||||
"### {}\n\n key | action\n --------------- | ------\n{}\n",
|
"### {}\n\n key | remaps | action\n --------------- | ------------------------- |------\n{}\n",
|
||||||
name, help
|
name, help
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -160,6 +160,14 @@ pub struct UiElement {
|
|||||||
pub style: Style,
|
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)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct TableRowConfig {
|
pub struct TableRowConfig {
|
||||||
@ -250,6 +258,12 @@ pub struct GeneralConfig {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub show_hidden: Option<bool>,
|
pub show_hidden: Option<bool>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub cursor: UiElement,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub prompt: UiElement,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub table: TableConfig,
|
pub table: TableConfig,
|
||||||
|
|
||||||
@ -266,6 +280,8 @@ pub struct GeneralConfig {
|
|||||||
impl GeneralConfig {
|
impl GeneralConfig {
|
||||||
pub fn extend(mut self, other: Self) -> Self {
|
pub fn extend(mut self, other: Self) -> Self {
|
||||||
self.show_hidden = other.show_hidden.or(self.show_hidden);
|
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.table = other.table.extend(self.table);
|
||||||
self.default_ui = other.default_ui.extend(self.default_ui);
|
self.default_ui = other.default_ui.extend(self.default_ui);
|
||||||
self.focus_ui = other.focus_ui.extend(self.focus_ui);
|
self.focus_ui = other.focus_ui.extend(self.focus_ui);
|
||||||
@ -277,6 +293,9 @@ impl GeneralConfig {
|
|||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct KeyBindings {
|
pub struct KeyBindings {
|
||||||
|
#[serde(default)]
|
||||||
|
pub remaps: BTreeMap<String, String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub on_key: BTreeMap<String, Action>,
|
pub on_key: BTreeMap<String, Action>,
|
||||||
|
|
||||||
@ -295,6 +314,8 @@ pub struct KeyBindings {
|
|||||||
|
|
||||||
impl KeyBindings {
|
impl KeyBindings {
|
||||||
pub fn extend(mut self, mut other: Self) -> Self {
|
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);
|
other.on_key.extend(self.on_key);
|
||||||
self.on_key = other.on_key;
|
self.on_key = other.on_key;
|
||||||
self.on_alphabet = other.on_alphabet.or(self.on_alphabet);
|
self.on_alphabet = other.on_alphabet.or(self.on_alphabet);
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
version: v0.4.0
|
version: v0.4.0
|
||||||
general:
|
general:
|
||||||
show_hidden: false
|
show_hidden: false
|
||||||
|
prompt:
|
||||||
|
format: "> "
|
||||||
|
cursor:
|
||||||
|
format: █
|
||||||
table:
|
table:
|
||||||
header:
|
header:
|
||||||
cols:
|
cols:
|
||||||
@ -180,6 +184,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
c:
|
c:
|
||||||
help: copy here
|
help: copy here
|
||||||
@ -226,6 +231,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
enter:
|
enter:
|
||||||
help: create file
|
help: create file
|
||||||
@ -266,6 +272,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
enter:
|
enter:
|
||||||
help: create directory
|
help: create directory
|
||||||
@ -306,6 +313,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
ctrl-c:
|
ctrl-c:
|
||||||
help: cancel & quit
|
help: cancel & quit
|
||||||
@ -337,6 +345,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
enter:
|
enter:
|
||||||
help: rename
|
help: rename
|
||||||
@ -377,6 +386,15 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps:
|
||||||
|
/: ctrl-f
|
||||||
|
h: left
|
||||||
|
j: down
|
||||||
|
k: up
|
||||||
|
l: right
|
||||||
|
v: space
|
||||||
|
q: ctrl-c
|
||||||
|
|
||||||
on_key:
|
on_key:
|
||||||
'#':
|
'#':
|
||||||
help: null
|
help: null
|
||||||
@ -390,12 +408,6 @@ modes:
|
|||||||
input: .
|
input: .
|
||||||
case_sensitive: false
|
case_sensitive: false
|
||||||
- Explore
|
- Explore
|
||||||
/:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- SwitchMode: search
|
|
||||||
- SetInputBuffer: ''
|
|
||||||
- Explore
|
|
||||||
':':
|
':':
|
||||||
help: action
|
help: action
|
||||||
messages:
|
messages:
|
||||||
@ -405,16 +417,22 @@ modes:
|
|||||||
messages:
|
messages:
|
||||||
- BashExec: |
|
- BashExec: |
|
||||||
${PAGER:-less} "${XPLR_PIPE_GLOBAL_HELP_MENU_OUT}"
|
${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:
|
G:
|
||||||
help: go to bottom
|
help: go to bottom
|
||||||
messages:
|
messages:
|
||||||
- FocusLast
|
- FocusLast
|
||||||
ctrl-c:
|
ctrl-c:
|
||||||
help: cancel & quit [q]
|
help: cancel & quit
|
||||||
messages:
|
messages:
|
||||||
- Terminate
|
- Terminate
|
||||||
ctrl-f:
|
ctrl-f:
|
||||||
help: search [/]
|
help: search
|
||||||
messages:
|
messages:
|
||||||
- SwitchMode: search
|
- SwitchMode: search
|
||||||
- SetInputBuffer: ''
|
- SetInputBuffer: ''
|
||||||
@ -424,7 +442,7 @@ modes:
|
|||||||
messages:
|
messages:
|
||||||
- SwitchMode: delete
|
- SwitchMode: delete
|
||||||
down:
|
down:
|
||||||
help: down [j]
|
help: down
|
||||||
messages:
|
messages:
|
||||||
- FocusNext
|
- FocusNext
|
||||||
enter:
|
enter:
|
||||||
@ -435,55 +453,29 @@ modes:
|
|||||||
help: go to
|
help: go to
|
||||||
messages:
|
messages:
|
||||||
- SwitchMode: go to
|
- SwitchMode: go to
|
||||||
h:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- Back
|
|
||||||
j:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- FocusNext
|
|
||||||
k:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- FocusPrevious
|
|
||||||
l:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- Enter
|
|
||||||
left:
|
left:
|
||||||
help: back [h]
|
help: back
|
||||||
messages:
|
messages:
|
||||||
- Back
|
- Back
|
||||||
q:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- Terminate
|
|
||||||
r:
|
r:
|
||||||
help: rename
|
help: rename
|
||||||
messages:
|
messages:
|
||||||
- SwitchMode: rename
|
- SwitchMode: rename
|
||||||
- BashExecSilently: |
|
- BashExecSilently: |
|
||||||
echo "SetInputBuffer: $(basename ${XPLR_FOCUS_PATH})" >> "${XPLR_PIPE_MSG_IN:?}"
|
echo "SetInputBuffer: $(basename ${XPLR_FOCUS_PATH})" >> "${XPLR_PIPE_MSG_IN:?}"
|
||||||
|
|
||||||
right:
|
right:
|
||||||
help: enter [l]
|
help: enter
|
||||||
messages:
|
messages:
|
||||||
- Enter
|
- Enter
|
||||||
space:
|
space:
|
||||||
help: toggle selection [v]
|
help: toggle selection
|
||||||
messages:
|
messages:
|
||||||
- ToggleSelection
|
- ToggleSelection
|
||||||
- FocusNext
|
- FocusNext
|
||||||
up:
|
up:
|
||||||
help: up [k]
|
help: up
|
||||||
messages:
|
messages:
|
||||||
- FocusPrevious
|
- FocusPrevious
|
||||||
v:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- ToggleSelection
|
|
||||||
- FocusNext
|
|
||||||
on_alphabet: null
|
on_alphabet: null
|
||||||
on_number:
|
on_number:
|
||||||
help: input
|
help: input
|
||||||
@ -501,6 +493,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
ctrl-c:
|
ctrl-c:
|
||||||
help: cancel & quit
|
help: cancel & quit
|
||||||
@ -532,6 +525,9 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps:
|
||||||
|
j: down
|
||||||
|
k: up
|
||||||
on_key:
|
on_key:
|
||||||
backspace:
|
backspace:
|
||||||
help: clear
|
help: clear
|
||||||
@ -542,7 +538,7 @@ modes:
|
|||||||
messages:
|
messages:
|
||||||
- Terminate
|
- Terminate
|
||||||
down:
|
down:
|
||||||
help: to down [j]
|
help: to down
|
||||||
messages:
|
messages:
|
||||||
- FocusNextByRelativeIndexFromInput
|
- FocusNextByRelativeIndexFromInput
|
||||||
- SwitchMode: default
|
- SwitchMode: default
|
||||||
@ -551,18 +547,8 @@ modes:
|
|||||||
messages:
|
messages:
|
||||||
- FocusByIndexFromInput
|
- FocusByIndexFromInput
|
||||||
- SwitchMode: default
|
- SwitchMode: default
|
||||||
j:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- FocusNextByRelativeIndexFromInput
|
|
||||||
- SwitchMode: default
|
|
||||||
k:
|
|
||||||
help: null
|
|
||||||
messages:
|
|
||||||
- FocusPreviousByRelativeIndexFromInput
|
|
||||||
- SwitchMode: default
|
|
||||||
up:
|
up:
|
||||||
help: to up [k]
|
help: to up
|
||||||
messages:
|
messages:
|
||||||
- FocusPreviousByRelativeIndexFromInput
|
- FocusPreviousByRelativeIndexFromInput
|
||||||
- SwitchMode: default
|
- SwitchMode: default
|
||||||
@ -581,6 +567,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
d:
|
d:
|
||||||
help: delete
|
help: delete
|
||||||
@ -637,6 +624,9 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps:
|
||||||
|
q: ctrl-c
|
||||||
|
|
||||||
on_number:
|
on_number:
|
||||||
help: go to index
|
help: go to index
|
||||||
messages:
|
messages:
|
||||||
@ -679,11 +669,7 @@ modes:
|
|||||||
- SwitchMode: default
|
- SwitchMode: default
|
||||||
|
|
||||||
ctrl-c:
|
ctrl-c:
|
||||||
help: cancel & quit [q]
|
help: cancel & quit
|
||||||
messages:
|
|
||||||
- Terminate
|
|
||||||
|
|
||||||
q:
|
|
||||||
messages:
|
messages:
|
||||||
- Terminate
|
- Terminate
|
||||||
|
|
||||||
@ -695,6 +681,7 @@ modes:
|
|||||||
help: null
|
help: null
|
||||||
extra_help: null
|
extra_help: null
|
||||||
key_bindings:
|
key_bindings:
|
||||||
|
remaps: {}
|
||||||
on_key:
|
on_key:
|
||||||
backspace:
|
backspace:
|
||||||
help: clear
|
help: clear
|
||||||
|
45
src/ui.rs
45
src/ui.rs
@ -9,6 +9,7 @@ use tui::backend::Backend;
|
|||||||
use tui::layout::Rect;
|
use tui::layout::Rect;
|
||||||
use tui::layout::{Constraint as TuiConstraint, Direction, Layout};
|
use tui::layout::{Constraint as TuiConstraint, Direction, Layout};
|
||||||
use tui::style::{Color, Style};
|
use tui::style::{Color, Style};
|
||||||
|
use tui::text::{Span, Spans};
|
||||||
use tui::widgets::{
|
use tui::widgets::{
|
||||||
Block, Borders, Cell, List, ListItem, ListState, Paragraph, Row, Table, TableState,
|
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()
|
.into_iter()
|
||||||
.map(|l| match l {
|
.map(|l| match l {
|
||||||
HelpMenuLine::Paragraph(p) => Row::new([Cell::from(p)].to_vec()),
|
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>>();
|
.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)
|
.borders(Borders::ALL)
|
||||||
.title(format!(" Help [{}] ", &app.mode().name)),
|
.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);
|
f.render_widget(help_menu, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_input_buffer<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &Handlebars) {
|
fn draw_input_buffer<B: Backend>(f: &mut Frame<B>, rect: Rect, app: &app::App, _: &Handlebars) {
|
||||||
let input_buf = Paragraph::new(format!(
|
let input_buf = Paragraph::new(Spans::from(vec![
|
||||||
"> {}",
|
Span::styled(
|
||||||
app.input_buffer().unwrap_or_else(|| "".into())
|
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 "));
|
.block(Block::default().borders(Borders::ALL).title(" Input "));
|
||||||
f.render_widget(input_buf, rect);
|
f.render_widget(input_buf, rect);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user