Add more keyboard input handlers

This PR adds 3 more keyboard input handlers:

- on_alphanumeric
- on_character
- on_navigation

Also updates documentation.
pull/399/head
Arijit Basu 3 years ago committed by Arijit Basu
parent ca6cefb1c1
commit b45a553a0c

@ -1,5 +1,5 @@
<h1 align="center">
▸[<a href="https://github.com/sayanarijit/xplr/blob/main/assets/icon/xplr.svg" target="_blank"><img src="https://s3.gifyu.com/images/xplr32.png" alt="▓▓" height="20" width="20" /></a> xplr]
▸[<a href="https://github.com/sayanarijit/xplr/blob/main/assets/icon/xplr.svg"><img src="https://s3.gifyu.com/images/xplr32.png" alt="▓▓" height="20" width="20" /></a> xplr]
</h1>
<p align="center">
@ -8,19 +8,19 @@ A hackable, minimal, fast TUI file explorer
<p align="center">
<a href="https://crates.io/crates/xplr" target="_blank">
<a href="https://crates.io/crates/xplr">
<img src="https://img.shields.io/crates/v/xplr.svg" />
</a>
<a href="https://github.com/sayanarijit/xplr/commits" target="_blank">
<a href="https://github.com/sayanarijit/xplr/commits">
<img src="https://img.shields.io/github/commit-activity/m/sayanarijit/xplr" />
</a>
<a href="https://matrix.to/#/#xplr-pub:matrix.org" target="_blank">
<a href="https://matrix.to/#/#xplr-pub:matrix.org">
<img alt="Matrix" src="https://img.shields.io/matrix/xplr-pub:matrix.org?color=0DB787&label=matrix&logo=Matrix">
</a>
<a href="https://discord.gg/JmasSPCcz3" target="_blank">
<a href="https://discord.gg/JmasSPCcz3">
<img src="https://img.shields.io/discord/834369918312382485?color=5865F2&label=discord&logo=Discord" />
</a>
@ -30,6 +30,13 @@ A hackable, minimal, fast TUI file explorer
<img src="https://s3.gifyu.com/images/xplr-0.5.0.gif" />
</p>
<h3 align="center">
[<a href="https://xplr.dev/en/install">Install</a>]
[<a href="https://xplr.dev/en">Documentation</a>]
[<a href="https://xplr.dev/en/awesome-plugins">Plugins</a>]
[<a href="https://xplr.dev/en/community">Community</a>]
</h3>
`xplr` is a terminal UI based file explorer that aims to increase our terminal
productivity by being a flexible, interactive orchestrator for the ever growing
awesome command-line utilities that work with the file-system.
@ -43,50 +50,14 @@ intuitive, scriptable, keyboard controlled, real-time visual interface, also
being an ideal candidate for further integration, enabling the users to achieve
insane terminal productivity.
Table of content
----------------
- [Introduction](https://xplr.dev/en/introduction.html)
- [Quickstart](https://xplr.dev/en/quickstart.html)
- [Install](https://xplr.dev/en/install.html)
- [Post Install](https://xplr.dev/en/post-install.html)
- [Configuration](https://xplr.dev/en/configuration.html)
- [General Config](https://xplr.dev/en/general-config.html)
- [Modes](https://xplr.dev/en/modes.html)
- [Message](https://xplr.dev/en/message.html)
- [Layouts](https://xplr.dev/en/layouts.html)
- [Node Types](https://xplr.dev/en/node_types.html)
- [Style](https://xplr.dev/en/style.html)
- [Sorting](https://xplr.dev/en/sorting.html)
- [Filtering](https://xplr.dev/en/filtering.html)
- [Column Renderer](https://xplr.dev/en/column-renderer.html)
- [Default Key Bindings](https://xplr.dev/en/default-key-bindings.html)
- [Plugin](https://xplr.dev/en/plugin.html)
- [Installing Plugins](https://xplr.dev/en/installing-plugins.html)
- [Writing Plugins](https://xplr.dev/en/writing-plugins.html)
- [Awesome Plugins](https://xplr.dev/en/awesome-plugins.html)
- [Integration](https://xplr.dev/en/integration.html)
- [Awesome Integrations](https://xplr.dev/en/awesome-integrations.html)
- [TODO](https://xplr.dev/en/todo.html)
- [Alternatives](https://xplr.dev/en/alternatives.html)
- [Upgrade Guide](https://xplr.dev/en/upgrade-guide.html)
- [Community](https://xplr.dev/en/community.html)
- [Contribute](https://xplr.dev/en/contribute.html)
Introductions & Reviews
-----------------------
## Introductions & Reviews
- [[VIDEO] XPLR: Insanely Hackable Lua File Manager ~ Brodie Robertson](https://youtu.be/MaVRtYh1IRU)
## Packaging
Packaging
---------
<a href="https://repology.org/project/xplr/versions" target="_blank"><img src="https://repology.org/badge/vertical-allrepos/xplr.svg" /></a>
<a href="https://repology.org/project/xplr/versions"><img src="https://repology.org/badge/vertical-allrepos/xplr.svg" /></a>
Backers
-------
## Backers
<a href="https://opencollective.com/xplr#backer" target="_blank"><img src="https://opencollective.com/xplr/tiers/backer.svg?width=890" /></a>
<a href="https://opencollective.com/xplr#backer"><img src="https://opencollective.com/xplr/tiers/backer.svg?width=890" /></a>

@ -5,6 +5,10 @@
- [Install][3]
- [Post Install][4]
- [Configuration][5]
- [Key Bindings][27]
- [Configure Key Bindings][28]
- [Default Key Bindings][14]
- [Debug Key Bindings][29]
- [General Config][6]
- [Modes][7]
- [Message][8]
@ -14,7 +18,6 @@
- [Sorting][12]
- [Filtering][13]
- [Column Renderer][26]
- [Default Key Bindings][14]
- [Plugin][15]
- [Installing Plugins][16]
- [Writing Plugins][17]
@ -53,3 +56,6 @@
[24]: community.md
[25]: contribute.md
[26]: column-renderer.md
[27]: key-bindings.md
[28]: configure-key-bindings.md
[29]: debug-key-bindings.md

@ -0,0 +1,223 @@
# Configure Key Bindings
In xplr, each keyboard input passes through a bunch of handlers (e.g. `on_key`,
`on_number`, `default` etc.) in a given order. If any of the handlers is
configured to with an [action][16], it will intercept the key and produce
[messages][18] for xplr to handle.
## Key Bindings
Key bindings contains the following information:
- [on_key][10]
- [on_alphabet][11]
- [on_number][12]
- [on_alphanumeric][32]
- [on_special_character][13]
- [on_character][33]
- [on_navigation][34]
- [default][14]
### on_key
Type: mapping of [Key][15] to nullable [Action][16]
Defines what to do when an exact key is pressed.
### on_alphabet
Type: nullable [Action][16]
An action to perform if the keyboard input is an alphabet and is not mapped via
the [on_key][10] field.
### on_number
Type: nullable [Action][16]
An action to perform if the keyboard input is a number and is not mapped via
the [on_key][10] field.
### on_alphanumeric
Type: nullable [Action][16]
An action to perform if the keyboard input is alphanumeric and is not mapped
via the [on_key][10], [on_alphabet][11] or [on_number][12] field.
### on_special_character
Type: nullable [Action][16]
An action to perform if the keyboard input is a special character and is not
mapped via the [on_key][10] field.
### on_character
Type: nullable [Action][16]
An action to perform if the keyboard input is a character and is not mapped
via the [on_key][10], [on_alphabet][11], [on_number][12], [on_alphanumeric][32]
or [on_special_character][13] field.
### on_navigation
Type: nullable [Action][16]
An action to perform if the keyboard input is a navigation key and is not
mapped via the [on_key][10] field.
### default
Type: nullable [Action][16]
Default action to perform in case if a keyboard input not mapped via any of the
`on_*` fields mentioned above.
## Key
A key can be one of the following:
- 0, 1, ... 9
- a, b, ... z
- A, B, ... Z
- f1, f2, ... f12
- backspace
- left
- right
- up
- down
- home
- end
- page-up
- page-down
- back-tab
- delete
- insert
- enter
- tab
- esc
- ctrl-a, ctrl-b, ... ctrl-z
- ctrl-backspace, ctrl-left, ... ctrl-esc
- alt-a, alt-b, ... alt-z
And finally, the special characters - including space (`" "`) with their `ctrl`
bindings.
## Action
An action contains the following information:
- [help][1]
- [messages][17]
### help
Type: nullable string
Description of what it does. If unspecified, it will be excluded from the help
menu.
### messages
Type: A list of [Message][18] to send.
The list of messages to send when a key is pressed.
## Tutorial: Adding a New Mode
Assuming xplr is [installed][19] and [setup][20], let's
add our own mode to integrate xplr with [fzf][21].
We'll call it `fzxplr` mode.
First, let's add a custom mode called `fzxplr`, and map the key `F` to an
action that will call `fzf` to search and focus on a file or enter into a
directory.
```lua
xplr.config.modes.custom.fzxplr = {
name = "fzxplr",
key_bindings = {
on_key = {
F = {
help = "search",
messages = {
{
BashExec = [===[
PTH=$(cat "${XPLR_PIPE_DIRECTORY_NODES_OUT:?}" | awk -F/ '{print $NF}' | fzf)
if [ -d "$PTH" ]; then
echo ChangeDirectory: "'"${PWD:?}/${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
else
echo FocusPath: "'"${PWD:?}/${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
fi
]===]
},
"PopMode",
},
},
},
default = {
messages = {
"PopMode",
},
},
},
}
```
As you can see, the key `F` in mode `fzxplr` (the name can be anything)
executes a script in `bash`.
`BashExec`, `PopMode`, `SwitchModeBuiltin`, `ChangeDirectory` and `FocusPath`
are [messages][18], `$XPLR_PIPE_MSG_IN`,
`$XPLR_PIPE_DIRECTORY_NODES_OUT` are
[environment variables][22] exported by `xplr`
before executing the command. They contain the path to the
[input][23] and [output][24] pipes that
allows external tools to interact with `xplr`.
Now that we have our new mode ready, let's add an entry point to this mode via
the `default` mode.
```lua
xplr.config.modes.builtin.default.key_bindings.on_key["F"] = {
help = "fzf mode",
messages = {
{ SwitchModeCustom = "fzxplr" },
},
}
```
Now let's try out the new `xplr`-`fzf` integration.
[![xplr-fzf.gif][25]][26]
---
Visit [Awesome Plugins][27] for more [integration][28] options.
[1]: #help
[10]: #on_key
[11]: #on_alphabet
[12]: #on_number
[13]: #on_special_character
[14]: #default
[15]: #key
[16]: #action
[17]: #messages
[18]: message.md#message
[19]: install.md
[20]: post-install.md
[21]: https://github.com/junegunn/fzf
[22]: message.md#environment-variables
[23]: message.md#input-pipe
[24]: message.md#output-pipes
[25]: https://s3.gifyu.com/images/xplr-fzf.gif
[26]: https://gifyu.com/image/tW86
[27]: awesome-plugins.md
[28]: awesome-plugins.md#integration
[31]: debug-key-bindings.md
[32]: #on_alphanumeric
[33]: #on_character
[34]: #on_navigation

@ -0,0 +1,93 @@
# Debug Key Bindings
If you need help debugging or understanding key bindings DYI way, you can
create a `test.lua` file with the following script, launch xplr with
`xplr --extra-config text.lua`, press `#` and play around.
```lua
xplr.config.modes.builtin.default.key_bindings.on_key["#"] = {
help = "test",
messages = {
"PopMode",
{ SwitchModeCustom = "test" },
},
}
xplr.config.modes.custom.test = {
name = "test",
key_bindings = {
on_key = {
["1"] = {
messages = {
{ LogInfo = "on_key called" },
},
},
a = {
messages = {
{ LogInfo = "on_key called" },
},
},
["`"] = {
messages = {
{ LogInfo = "on_key called" },
},
},
f1 = {
messages = {
{ LogInfo = "on_key called" },
},
},
tab = {
messages = {
{ LogInfo = "on_key called" },
},
},
esc = {
messages = {
"PopMode",
},
},
["ctrl-c"] = {
messages = {
"Terminate",
},
},
},
on_alphabet = {
messages = {
{ LogInfo = "on_alphabet called" },
},
},
on_number = {
messages = {
{ LogInfo = "on_number called" },
},
},
-- on_alphanumeric = {
-- messages = {
-- { LogInfo = "on_alphanumeric called" },
-- },
-- },
on_special_character = {
messages = {
{ LogInfo = "on_special_character called" },
},
},
-- on_character = {
-- messages = {
-- { LogInfo = "on_character called" },
-- },
-- },
on_navigation = {
messages = {
{ LogInfo = "on_navigation called" },
},
},
default = {
messages = {
{ LogInfo = "default called" },
},
},
},
}
```

@ -1,8 +1,8 @@
# Default Key Bindings
The default key binding is inspired by [vim][1] and slightly
overlaps with [nnn][2], but it's supposed to be
customized as per user requirements.
overlaps with [nnn][2], but it's supposed to be customized as per user
requirements.
When you press `?` in [default mode][3], you can see the complete list
of [modes][4] and the key mappings for each mode.
@ -47,29 +47,25 @@ of [modes][4] and the key mappings for each mode.
### filter
| key | remaps | action |
| --------- | ------ | ------------------------- |
| R | | relative does not contain |
| backspace | | remove last filter |
| ctrl-c | | terminate |
| ctrl-r | | reset filters |
| ctrl-u | | clear filters |
| enter | esc | done |
| r | | relative does contain |
| key | remaps | action |
| ------ | ------ | ------------------------- |
| R | | relative does not contain |
| ctrl-c | | terminate |
| ctrl-r | | reset filters |
| ctrl-u | | clear filters |
| enter | esc | done |
| r | | relative does contain |
### number
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| down | j | to down |
| enter | | to index |
| esc | | cancel |
| k | up | to up |
| [0-9] | | input |
| key | remaps | action |
| ------ | ------ | --------- |
| ctrl-c | | terminate |
| down | j | to down |
| enter | | to index |
| esc | | cancel |
| k | up | to up |
| [0-9] | | input |
### go to
@ -83,18 +79,15 @@ of [modes][4] and the key mappings for each mode.
### search
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-n | down | down |
| ctrl-p | up | up |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| enter | esc | focus |
| left | | back |
| right | | enter |
| tab | | toggle selection |
| key | remaps | action |
| ------ | ------ | ---------------- |
| ctrl-c | | terminate |
| ctrl-n | down | down |
| ctrl-p | up | up |
| enter | esc | focus |
| left | | back |
| right | | enter |
| tab | | toggle selection |
### selection ops
@ -132,36 +125,27 @@ of [modes][4] and the key mappings for each mode.
### create file
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| enter | | create file |
| esc | | cancel |
| key | remaps | action |
| ------ | ------ | ----------- |
| ctrl-c | | terminate |
| enter | | create file |
| esc | | cancel |
### create directory
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| enter | | create directory |
| esc | | cancel |
| key | remaps | action |
| ------ | ------ | ---------------- |
| ctrl-c | | terminate |
| enter | | create directory |
| esc | | cancel |
### rename
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| enter | | rename |
| esc | | cancel |
| key | remaps | action |
| ------ | ------ | --------- |
| ctrl-c | | terminate |
| enter | | rename |
| esc | | cancel |
### delete
@ -195,37 +179,30 @@ of [modes][4] and the key mappings for each mode.
### filter
| key | remaps | action |
| --------- | ------ | ------------------------- |
| R | | relative does not contain |
| backspace | | remove last filter |
| ctrl-c | | terminate |
| ctrl-r | | reset filters |
| ctrl-u | | clear filters |
| enter | esc | done |
| r | | relative does contain |
| key | remaps | action |
| ------ | ------ | ------------------------- |
| R | | relative does not contain |
| ctrl-c | | terminate |
| ctrl-r | | reset filters |
| ctrl-u | | clear filters |
| enter | esc | done |
| r | | relative does contain |
### relative path does contain
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| enter | | apply filter |
| esc | | cancel |
| key | remaps | action |
| ------ | ------ | ------------ |
| ctrl-c | | terminate |
| enter | | apply filter |
| esc | | cancel |
### relative path does not contain
| key | remaps | action |
| --------- | ------ | --------------------- |
| backspace | | remove last character |
| ctrl-c | | terminate |
| ctrl-u | | remove line |
| ctrl-w | | remove last word |
| enter | | apply filter |
| esc | | cancel |
| key | remaps | action |
| ------ | ------ | ------------ |
| ctrl-c | | terminate |
| enter | | apply filter |
| esc | | cancel |
### switch layout

@ -1 +1,16 @@
# Key Bindings
Key bindings define how each keyboard input will be handled while in a specific
[mode][4].
See the [Default key bindings][1] for example.
To configure or work with key bindings, visit [Configure Key Bindings][2].
In case you need help debugging key bindings or to understand the system DYI
way, refer to the [Debug Key Bindings][3] guide.
[1]: default-key-bindings.md
[2]: configure-key-bindings.md
[3]: debug-key-bindings.md
[4]: modes.md#mode

@ -1217,7 +1217,7 @@ xplr.config.modes.builtin.default.key_bindings.on_key.space = {
```
[1]: #full-list-of-messages
[2]: modes.md#key-bindings
[2]: key-bindings.md
[3]: #lua-function-calls
[4]: #input-pipe
[5]: https://www.lua.org/
@ -1234,7 +1234,7 @@ xplr.config.modes.builtin.default.key_bindings.on_key.space = {
[16]: filtering.md
[17]: sorting.md#sorter
[18]: https://docs.rs/xplr/latest/xplr/app/struct.CallLuaArg.html#fields
[19]: modes.md#tutorial-adding-a-new-mode
[19]: configure-key-bindings.md#tutorial-adding-a-new-mode
[20]: #xplr_pipe_msg_in
[21]: #xplr_pipe_selection_out
[22]: #xplr_pipe_global_help_menu_out

@ -81,7 +81,7 @@ A mode contains the following information:
- [help][6]
- [extra_help][7]
- [key_bindings][8]
- [layout][29]
- [layout][10]
### name
@ -111,180 +111,10 @@ The key bindings available in that mode.
### layout
Type: nullable [Layout][30]
Type: nullable [Layout][11]
If specified, this layout will be used to render the UI.
## Key Bindings
Key bindings define how each keyboard input will be handled in a specific mode.
See the [default key bindings][4] for example.
Key bindings contains the following information:
- [on_key][10]
- [on_alphabet][11]
- [on_number][12]
- [on_special_character][13]
- [default][14]
### on_key
Type: mapping of [Key][15] to nullable [Action][16]
Defines what to do when a specific key is pressed.
### on_alphabet
Type: nullable [Action][16]
An action to perform if the keyboard input is an alphabet and is not mapped via
the [on_key][10] field.
### on_number
Type: nullable [Action][16]
An action to perform if the keyboard input is a number and is not mapped via
the [on_key][10] field.
### on_special_character
Type: nullable [Action][16]
An action to perform if the keyboard input is a special character and is not
mapped via the [on_key][10] field.
### default
Type: nullable [Action][16]
Default action to perform in case of a keyboard input not mapped via any of the
[on_key][10], [on_alphabet][11], [on_number][12] or
[on_special_character][13] field.
## Key
A key can be one of the following:
- 0, 1, ... 9
- a, b, ... z
- A, B, ... Z
- f1, f2, ... f12
- ctrl-a, ctrl-b, ... ctrl-z
- alt-a, alt-b, ... alt-z
- backspace
- left
- right
- up
- down
- home
- end
- page-up
- page-down
- back-tab
- delete
- insert
- enter
- tab
- esc
And finally, the special characters - including space (`" "`).
## Action
An action contains the following information:
- help
- [messages][17]
### help
Type: nullable string
Description of what it does. If unspecified, it will be excluded from the help
menu.
### messages
Type: A list of [Message][18] to send.
The list of messages to send when a key is pressed.
## Tutorial: Adding a New Mode
Assuming xplr is [installed][19] and [setup][20], let's
add our own mode to integrate xplr with [fzf][21].
We'll call it `fzxplr` mode.
First, let's add a custom mode called `fzxplr`, and map the key `F` to an
action that will call `fzf` to search and focus on a file or enter into a
directory.
```lua
xplr.config.modes.custom.fzxplr = {
name = "fzxplr",
key_bindings = {
on_key = {
F = {
help = "search",
messages = {
{
BashExec = [===[
PTH=$(cat "${XPLR_PIPE_DIRECTORY_NODES_OUT:?}" | awk -F/ '{print $NF}' | fzf)
if [ -d "$PTH" ]; then
echo ChangeDirectory: "'"${PWD:?}/${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
else
echo FocusPath: "'"${PWD:?}/${PTH:?}"'" >> "${XPLR_PIPE_MSG_IN:?}"
fi
]===]
},
"PopMode",
},
},
},
default = {
messages = {
"PopMode",
},
},
},
}
```
As you can see, the key `F` in mode `fzxplr` (the name can be anything)
executes a script in `bash`.
`BashExec`, `PopMode`, `SwitchModeBuiltin`, `ChangeDirectory` and `FocusPath`
are [messages][18], `$XPLR_PIPE_MSG_IN`,
`$XPLR_PIPE_DIRECTORY_NODES_OUT` are
[environment variables][22] exported by `xplr`
before executing the command. They contain the path to the
[input][23] and [output][24] pipes that
allows external tools to interact with `xplr`.
Now that we have our new mode ready, let's add an entry point to this mode via
the `default` mode.
```lua
xplr.config.modes.builtin.default.key_bindings.on_key["F"] = {
help = "fzf mode",
messages = {
{ SwitchModeCustom = "fzxplr" },
},
}
```
Now let's try out the new `xplr`-`fzf` integration.
[![xplr-fzf.gif][25]][26]
---
Visit [Awesome Plugins][27] for more [integration][28] options.
[1]: #builtin
[2]: #custom
[3]: #mode
@ -292,26 +122,7 @@ Visit [Awesome Plugins][27] for more [integration][28] options.
[5]: #name
[6]: #help
[7]: #extra_help
[8]: #key_bindings
[8]: configure-key-bindings.md#key-bindings
[9]: #key-bindings
[10]: #on_key
[11]: #on_alphabet
[12]: #on_number
[13]: #on_special_character
[14]: #default
[15]: #key
[16]: #action
[17]: #messages
[18]: message.md
[19]: install.md
[20]: post-install.md
[21]: https://github.com/junegunn/fzf
[22]: message.md#environment-variables
[23]: message.md#input-pipe
[24]: message.md#output-pipes
[25]: https://s3.gifyu.com/images/xplr-fzf.gif
[26]: https://gifyu.com/image/tW86
[27]: awesome-plugins.md
[28]: awesome-plugins.md#integration
[29]: #layout
[30]: layouts.md#Layout
[10]: #layout
[11]: layouts.md#Layout

@ -74,7 +74,7 @@ Visit [Awesome Plugins][5] for xplr plugin examples.
[3]: https://neovim.io
[4]: https://github.com/sayanarijit/xplr/discussions/categories/show-and-tell
[5]: awesome-plugins.md
[6]: modes.md#tutorial-adding-a-new-mode
[6]: configure-key-bindings.md#tutorial-adding-a-new-mode
[7]: message.md#example-using-environment-variables-and-pipes
[8]: message.md#example-using-lua-function-calls
[9]: layouts.md#example-defining-custom-layout

@ -66,6 +66,7 @@
file explorer
</p>
<br />
<p><a href="/en/install.html">Try or Install</a></p>
</div>
<div class="main-video">
<img

@ -1605,24 +1605,38 @@ 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_str)
.to_owned()
.map(|a| Some(a.messages.clone()))
.unwrap_or_else(|| {
.map(|a| a.messages.clone())
.or_else(|| {
if key.is_alphabet() {
kb.on_alphabet.clone().map(|a| a.messages)
kb.on_alphabet.as_ref().map(|a| a.messages.clone())
} else if key.is_number() {
kb.on_number.clone().map(|a| a.messages)
kb.on_number.as_ref().map(|a| a.messages.clone())
} else {
None
}
})
.or_else(|| {
if key.is_alphanumeric() {
kb.on_alphanumeric.as_ref().map(|a| a.messages.clone())
} else if key.is_special_character() {
kb.on_special_character.clone().map(|a| a.messages)
kb.on_special_character.as_ref().map(|a| a.messages.clone())
} else {
None
}
})
.or_else(|| {
if key.is_character() {
kb.on_character.as_ref().map(|a| a.messages.clone())
} else if key.is_navigation() {
kb.on_navigation.as_ref().map(|a| a.messages.clone())
} else {
None
}
})
.or_else(|| default.map(|a| a.messages))
.or_else(|| kb.default.as_ref().map(|a| a.messages.clone()))
.unwrap_or_else(|| {
if self.config.general.enable_recover_mode {
vec![ExternalMsg::SwitchModeBuiltin("recover".into())]

@ -279,9 +279,18 @@ pub struct KeyBindings {
#[serde(default)]
pub on_number: Option<Action>,
#[serde(default)]
pub on_alphanumeric: Option<Action>,
#[serde(default)]
pub on_special_character: Option<Action>,
#[serde(default)]
pub on_character: Option<Action>,
#[serde(default)]
pub on_navigation: Option<Action>,
#[serde(default)]
pub default: Option<Action>,
}

@ -949,7 +949,6 @@ xplr.config.modes.builtin.default = {
},
},
},
on_alphabet = nil,
on_number = {
help = "input",
messages = {
@ -958,8 +957,6 @@ xplr.config.modes.builtin.default = {
"BufferInputFromKey",
},
},
on_special_character = nil,
default = nil,
},
}
@ -1102,10 +1099,6 @@ xplr.config.modes.builtin.selection_ops = {
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}
@ -1149,10 +1142,6 @@ xplr.config.modes.builtin.create = {
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}
@ -1191,11 +1180,7 @@ xplr.config.modes.builtin.create_directory = {
messages = { "PopMode" },
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = {
help = nil,
messages = { "UpdateInputBufferFromKey" },
},
},
@ -1236,11 +1221,8 @@ xplr.config.modes.builtin.create_file = {
messages = { "PopMode" },
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = {
help = nil,
messages = { "UpdateInputBufferFromKey" },
},
},
@ -1274,13 +1256,13 @@ xplr.config.modes.builtin.number = {
messages = { "FocusPreviousByRelativeIndexFromInput", "PopMode" },
},
},
on_alphabet = nil,
on_navigation = {
messages = { "UpdateInputBufferFromKey" },
},
on_number = {
help = "input",
messages = { "UpdateInputBufferFromKey" },
},
on_special_character = nil,
default = nil,
},
}
@ -1335,10 +1317,6 @@ xplr.config.modes.builtin.go_to = {
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}
@ -1374,9 +1352,6 @@ xplr.config.modes.builtin.rename = {
messages = { "PopMode" },
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = {
help = nil,
messages = { "UpdateInputBufferFromKey" },
@ -1446,10 +1421,6 @@ xplr.config.modes.builtin.delete = {
messages = { "PopMode" },
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}
@ -1537,7 +1508,6 @@ xplr.config.modes.builtin.action = {
},
},
},
on_alphabet = nil,
on_number = {
help = "go to index",
messages = {
@ -1548,8 +1518,6 @@ xplr.config.modes.builtin.action = {
"BufferInputFromKey",
},
},
on_special_character = nil,
default = nil,
},
}
@ -1666,11 +1634,7 @@ xplr.config.modes.builtin.search = {
messages = { "FocusPrevious" },
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = {
help = nil,
messages = {
{
RemoveNodeFilterFromInput = "IRelativePathDoesContain",
@ -1746,10 +1710,6 @@ xplr.config.modes.builtin.filter = {
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}
@ -1782,9 +1742,6 @@ xplr.config.modes.builtin.relative_path_does_contain = {
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = {
help = nil,
messages = {
@ -1827,9 +1784,6 @@ xplr.config.modes.builtin.relative_path_does_not_contain = {
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = {
help = nil,
messages = {
@ -2000,32 +1954,18 @@ xplr.config.modes.builtin.sort = {
["r"] = {
help = "by relative path",
messages = {
{
AddNodeSorter = {
sorter = "ByIRelativePath",
reverse = false,
},
},
{ AddNodeSorter = { sorter = "ByIRelativePath", reverse = false } },
"ExplorePwdAsync",
},
},
["s"] = {
help = "by size",
messages = {
{
AddNodeSorter = {
sorter = "BySize",
reverse = false,
},
},
{ AddNodeSorter = { sorter = "BySize", reverse = false } },
"ExplorePwdAsync",
},
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}
@ -2084,10 +2024,6 @@ xplr.config.modes.builtin.switch_layout = {
messages = { "PopMode" },
},
},
on_alphabet = nil,
on_number = nil,
on_special_character = nil,
default = nil,
},
}

@ -197,7 +197,7 @@ impl std::fmt::Display for Key {
_ => c.to_string(),
})
.unwrap_or_else(|| {
serde_yaml::to_value(self)
serde_yaml::to_value(&self)
.ok()
.and_then(|v| v.as_str().map(|v| v.to_string()))
.unwrap_or_default()
@ -208,32 +208,27 @@ impl std::fmt::Display for Key {
}
impl Key {
pub fn to_input_request(self) -> Option<InputRequest> {
pub fn to_input_request(&self) -> Option<InputRequest> {
use InputRequest::*;
use Key::*;
if self.is_alphabet() || self.is_number() || self.is_special_character()
{
self.to_char().map(InsertChar)
} else {
match self {
Backspace => Some(DeletePrevChar),
Delete => Some(DeleteNextChar),
Tab => Some(InsertChar('\t')),
Space => Some(InsertChar(' ')),
Left => Some(GoToPrevChar),
CtrlLeft => Some(GoToPrevWord),
Right => Some(GoToNextChar),
CtrlRight => Some(GoToNextWord),
CtrlU => Some(DeleteLine),
CtrlW => Some(DeletePrevWord),
CtrlDelete => Some(DeleteNextWord),
CtrlA => Some(GoToStart),
CtrlE => Some(GoToEnd),
Enter => Some(Submit),
Esc => Some(Escape),
_ => None,
}
match self {
Backspace => Some(DeletePrevChar),
Delete => Some(DeleteNextChar),
Tab => Some(InsertChar('\t')),
Space => Some(InsertChar(' ')),
Left => Some(GoToPrevChar),
CtrlLeft => Some(GoToPrevWord),
Right => Some(GoToNextChar),
CtrlRight => Some(GoToNextWord),
CtrlU => Some(DeleteLine),
CtrlW => Some(DeletePrevWord),
CtrlDelete => Some(DeleteNextWord),
CtrlA => Some(GoToStart),
CtrlE => Some(GoToEnd),
Enter => Some(Submit),
Esc => Some(Escape),
key => key.to_char().map(InsertChar),
}
}
@ -444,11 +439,109 @@ impl Key {
)
}
pub fn is_alphanumeric(&self) -> bool {
self.is_alphabet() || self.is_number()
}
pub fn is_special_character(&self) -> bool {
matches!(self, Self::Special(_))
matches!(&self, Self::Special(_))
}
pub fn is_character(&self) -> bool {
self.is_alphanumeric() || self.is_special_character()
}
pub fn is_navigation(&self) -> bool {
matches!(
&self,
Self::Backspace
| Self::Left
| Self::Right
| Self::Up
| Self::Down
| Self::Home
| Self::End
| Self::PageUp
| Self::PageDown
| Self::BackTab
| Self::Delete
| Self::Insert
| Self::Enter
| Self::Space
| Self::Tab
| Self::Esc
| Self::CtrlA
| Self::CtrlB
| Self::CtrlC
| Self::CtrlD
| Self::CtrlE
| Self::CtrlF
| Self::CtrlG
| Self::CtrlH
| Self::CtrlI
| Self::CtrlJ
| Self::CtrlK
| Self::CtrlL
| Self::CtrlM
| Self::CtrlN
| Self::CtrlO
| Self::CtrlP
| Self::CtrlQ
| Self::CtrlR
| Self::CtrlS
| Self::CtrlT
| Self::CtrlU
| Self::CtrlV
| Self::CtrlW
| Self::CtrlX
| Self::CtrlY
| Self::CtrlZ
| Self::CtrlBackspace
| Self::CtrlLeft
| Self::CtrlRight
| Self::CtrlUp
| Self::CtrlDown
| Self::CtrlHome
| Self::CtrlEnd
| Self::CtrlPageUp
| Self::CtrlPageDown
| Self::CtrlBackTab
| Self::CtrlDelete
| Self::CtrlInsert
| Self::CtrlEnter
| Self::CtrlSpace
| Self::CtrlTab
| Self::CtrlEsc
| Self::AltA
| Self::AltB
| Self::AltC
| Self::AltD
| Self::AltE
| Self::AltF
| Self::AltG
| Self::AltH
| Self::AltI
| Self::AltJ
| Self::AltK
| Self::AltL
| Self::AltM
| Self::AltN
| Self::AltO
| Self::AltP
| Self::AltQ
| Self::AltR
| Self::AltS
| Self::AltT
| Self::AltU
| Self::AltV
| Self::AltW
| Self::AltX
| Self::AltY
| Self::AltZ
)
}
pub fn to_char(self) -> Option<char> {
pub fn to_char(&self) -> Option<char> {
match self {
Self::Num0 => Some('0'),
Self::Num1 => Some('1'),

Loading…
Cancel
Save