litecli icon indicating copy to clipboard operation
litecli copied to clipboard

Feature Request: Customize vi mode keybinds.

Open aljustiet opened this issue 5 months ago • 1 comments

I use alternative keyboard layout with haei instead of hjkl. That's why, I would like to be able to customize these bindings.

aljustiet avatar Aug 10 '25 15:08 aljustiet

There is no option to customise keybinds in the configuration file, but you can work around this by monkey patching the litecli.key_bindings.cli_bindings() function:

    # This binding will be enabled for all modes except Insert.
    @kb.add("h", filter=~vi_insert_mode)
    def _(event):
        event.app.current_buffer.cursor_left(count=event.arg)

    @kb.add("a", filter=~vi_insert_mode)
    def _(event):
        # You can also use the 'auto_up' or 'auto_down'
        # functions in event.app.current_buffer 
        # if you want 'a'/'e' to move between history entries.
        event.app.current_buffer.cursor_up(count=event.

These are specific to prompt-toolkit used by litecli. The docs should provide a more in-depth explanation. This is the full script. You can save it as litecli to a folder in your PATH before /usr/bin.

#!/usr/bin/python
import litecli.key_bindings
from prompt_toolkit.enums import EditingMode
from prompt_toolkit.filters import (
    completion_is_selected,
    vi_insert_mode,
)
from prompt_toolkit.key_binding import KeyBindings


def cli_bindings(cli):
    kb = KeyBindings()

    @kb.add("h", filter=~vi_insert_mode)
    def _(event):
        event.app.current_buffer.cursor_left(count=event.arg)

    @kb.add("a", filter=~vi_insert_mode)
    def _(event):
        event.app.current_buffer.cursor_up(count=event.arg)

    @kb.add("e", filter=~vi_insert_mode)
    def _(event):
        event.app.current_buffer.cursor_down(count=event.arg)

    @kb.add("i", filter=~vi_insert_mode)
    def _(event):
        event.app.current_buffer.cursor_right(count=event.arg)

    @kb.add("f3")
    def _(event):
        cli.multi_line = not cli.multi_line

    @kb.add("f4")
    def _(event):
        if cli.key_bindings == "vi":
            event.app.editing_mode = EditingMode.EMACS
            cli.key_bindings = "emacs"
        else:
            event.app.editing_mode = EditingMode.VI
            cli.key_bindings = "vi"

    @kb.add("tab")
    def _(event):
        b = event.app.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            b.start_completion(select_first=True)

    @kb.add("s-tab")
    def _(event):
        b = event.app.current_buffer
        if b.complete_state:
            b.complete_previous()
        else:
            b.start_completion(select_last=True)

    @kb.add("c-space")
    def _(event):
        b = event.app.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            b.start_completion(select_first=False)

    @kb.add("enter", filter=completion_is_selected)
    def _(event):
        event.current_buffer.complete_state = None
        b = event.app.current_buffer
        b.complete_state = None

    @kb.add("right", filter=completion_is_selected)
    def _(event):
        b = event.app.current_buffer
        b.complete_state = None

    return kb


litecli.key_bindings.cli_bindings = cli_bindings

import re
import sys
from litecli.main import cli

if __name__ == "__main__":
    sys.argv[0] = re.sub(r"(-script\.pyw|\.exe)?$", "", sys.argv[0])
    sys.exit(cli())

More bindings can be found here.

memchr avatar Aug 15 '25 16:08 memchr