dbcli / pgcli

Postgres CLI with autocompletion and syntax highlighting
http://pgcli.com
BSD 3-Clause "New" or "Revised" License
12.14k stars 557 forks source link

Allow deeper REPL config + dbcli config covergence #1262

Open psacawa opened 3 years ago

psacawa commented 3 years ago

The dbcli projects all use the the prompt_toolkit module, as do other popular packages like ipython. This module exposes a lot of possiblities to configure prompts, the majority of which are not used by pgcli, or the other dbcli projects.

Ipython enables users to configure the prompt in an arbitrary way, by placing code modifying the prompt application in so-called startup files in their shell profiles. For example, I can replicate the core behaviour of the popular vim plugin vim-surround with a startup file. I can also use fzf for fuzzy history search, and install my own custom key bindings. This results in a great REPL-oriented workflow. By way of comparison, dbcli projects have very limited capabilities to customize the shell.

The request is twofold:

It's unclear how that should be implemented. I am interested in hearing some use cases to understand how this relates to how people use the dbcli projects presently. Once that becomes clear, I'd like to make a PR.

psacawa commented 3 years ago

I have something in mind like the content of this diff in my fork. This dynamically loads all modules in the ~/.prompt_toolkit directory and send the PromptSession the main routine in them. Hypothetically, something like this could serve as a central location for prompt configuration for all prompt-toolkit applications.

For example, ~/.prompt_toolkit can look as follows

/home/psacawa/.prompt_toolkit/
├── 10-fzf.py
├── 20-surround.py
└── 30-misc-keys.py

while e.g. 30-misc-keys.py can look as follows:

from prompt_toolkit.shortcuts import PromptSession
from prompt_toolkit.filters import ViNavigationMode

def main(pt_session: PromptSession):
    """prompt-toolkit key mappings"""
    bindings = pt_session.key_bindings

    @bindings.add_binding('J', filter=ViNavigationMode())
    def next_history(event):
        event.current_buffer.history_forward(count=1)

    @bindings.add_binding('K', filter=ViNavigationMode())
    def prev_history(event):
        event.current_buffer.history_backward(count=1)

This mirrors a configuration scheme used by Ipython. With time, configuration of this sort can be included in all dbcli projects, leading to use advances across the project. Eager to hear thoughts.

danihodovic commented 1 year ago

fzf for history would be wonderful