-
Notifications
You must be signed in to change notification settings - Fork 22
Keybinding
This page is deprecated, documentation moved to: https://inquirerpy.readthedocs.io/
One of the issues PyInquirer was facing is the lack of keybinding customization,
especially the highly requested vim navigation. InquirerPy offers a parameter
vi_mode which will automatically apply vim keybindings to input buffer as well
as list type prompts navigations.
InquirerPy takes the keybindings customization to another level where you can also
customize any supported keybindings with your own keys and filter.
The default keybindings is a classic emacs keybindings.
This is done because on most operating systems, also the Bash shell uses Emacs bindings by default, and that is more intuitive. If however, Vi binding are required, just pass vi_mode=True
You can use the regular emacs cursor shortcuts to move between words such as alt-b and alt-f in any input buffer
such as input, secret, filepath and fuzzy.
You can reference keybindings through emacs documentation.
The following dictionary contains the default keybindings that applies to all list type prompts. Only
down and up will be active at all time, other actions are only active when the list type prompt is
multiselect prompt or checkbox.
{
"down": [
{"key": "down"},
{"key": "c-n"}, # ctrl-n
],
"up": [
{"key": "up"},
{"key": "c-p"}, # ctrl-p
],
"toggle": [
{"key": "space"},
],
"toggle-down": [
{"key": "c-i"}, # tab
],
"toggle-up": [
{"key": "s-tab"}, # shift + tab
],
"toggle-all": [
{"key": "alt-r"},
],
"toggle-all-true": [
{"key": "alt-a"},
],
"toggle-all-false": [],
}All InquirerPy prompts accepts a boolean parameter vi_mode which will set both the keybinding of input buffer and
list navigation to vim keybindings.
from InquirerPy import prompt
from InquirerPy import inquirer
result = prompt(
questions=[
{"type": "input", "message": "Name:"},
{"type": "input", "message": "Address:"},
],
vi_mode=True,
)
result = inquirer.text(message="Name:", vi_mode=True)The input buffer will behave the same as if you enable the vi mode in readline/bash. The
navigation up and down will replace the emacs keybindings to vim.
{
"down": [
{"key": "down"},
{"key": "j"}, # ctrl-n is removed
],
"up": [
{"key": "up"},
{"key": "k"}, # ctrl-p is removed
],
# ....
}All the actions/keybinding in the Available actions and keybindings are customizable. Each InquirerPy prompt
takes an additional parameter called keybindings.
Available keys/syntax:
| Name | Possible keys |
|---|---|
| Escape | escape |
| Arrows |
left, right, up, down
|
| Navigation |
home, end, delete, pageup, pagedown, insert
|
| Control+lowercase |
c-a, c-b ... c-y, c-z
|
| Control+uppercase |
c-A, c-B ... c-Y, c-Z
|
| Control + arrow |
c-left, c-right, c-up, c-down
|
| Other control keys |
c-@, c-\, c-], c-^, c-\_, c-delete
|
| Shift + arrow | s-left, s-right, s-up, s-down |
| Other shift keys |
s-delete, s-tab
|
| F-keys |
f1, f2, .... f23, f24
|
| Alt+lowercase |
alt-a, alt-b ... alt-y, alt-z
|
| Alt+uppercase |
alt-A, alt-B ... alt-Y, alt-Z
|
Visit prompt_toolkit documentation
for more information about limitations and other advanced topics.
The provided keybindings will be merged with the default keybindings, the structure of this dictionary is exactly the same as the dictionary
in the Available actions and keybindings section.
The key can be either a list or a string. If you require multiple keys to be pressed in sequence, provide the key with a list of keys.
The following example maps the action toggle-all to press c-a and then press space.
keybindings = {
"toggle": [
{"key": "space"}
],
"toggle-all": [
{"key": ["c-a", "space"]}
]
}The following example enabled vim keybindings for input buffer, but still uses c-n and c-p for list navigations. It also enabled
the shortcut alt-x to deselect all choices/checkbox.
from InquirerPy import prompt
from InquirerPy import inquirer
keybindings = {
"down": [
{"key": "c-n"},
],
"up": [
{"key": "c-p"},
],
"toggle-all-false": [{"key": "alt-x"}],
}
result = prompt(
questions=[
{
"type": "list",
"message": "Select one:",
"choices": ["Fruit", "Meat", "Drinks", "Vegetable"],
},
],
vi_mode=True,
keybindings=keybindings,
)
result = inquirer.select(
message="Select one:",
choices=["Fruit", "Meat", "Drinks", "Vegetable"],
vi_mode=True,
keybindings=keybindings,
)Each keybinding also takes another key called filter which can be used to determine if certain keys should be enabled/disabled.
The filter key can be either a boolean or a prompt_toolkit Conditon.
special_vim = True
keybindings = {
"down": [
{"key": "c-j", "filter": special_vim},
],
"up": [
{"key": "c-k", "filter": special_vim},
],
"toggle-all-false": [{"key": "alt-x"}],
}
# ....from prompt_toolkit.filters.base import Condition
@Condition
def special_vim():
# logic ...
return True
keybindings = {
"down": [
{"key": "c-j", "filter": special_vim},
],
"up": [
{"key": "c-k", "filter": special_vim},
],
"toggle-all-false": [{"key": "alt-x"}],
}
# ....This is only available for
Alternate Syntax(i.e. usinginquirer).
You can also create your own keybindings/actions. When creating a prompt via inquirer, instead of running
the execute function immediately, you can bind keys to your custom functions before running the prompt.
register_kb is a decorator function thats available to use once the prompt is created.
The function that are being binded will be provided by a parameter event. The event can give
you access to the application (event.app). It's more of a prompt_toolkit
, if you don't plan to use it, simply provide a dummy parameter _.
The following example will print "Hello World" on top of the prompt when pressing alt-a.
from InquirerPy import inquirer
from InquirerPy.utils import patched_print as print
name_prompt = inquirer.text(message="Name:")
kb_activate = True
@name_prompt.register_kb("alt-a")
def _(_):
print("Hello World")
name = name_prompt.execute()You can bind multiple keys and also have the ability to apply filter.
from prompt_toolkit.filters.base import Condition
hello_active = Condition(lambda: True)
world_active = False
@name_prompt.register_kb("alt-j", "alt-k" filter=hello_active)
def _(_):
print("Hello")
@name_prompt.register_kb("escape", "k", "escape", "j" filter=world_active)
def _(_):
print("World")Prompts