pythonfuzzy-searchprompt-toolkit

Python prompt_toolkit: Pick best fuzzy match when the user presses enter


I am using FuzzyCompleter from prompt_toolkit for by CLI. I am additionally passing complete_while_typing=True to the prompt function.

If I provide a list containing e.g. "Testing" and the user types "tst", it will show up as the first suggestion. But if the user then presses enter, the result from the prompt function will be "tst", not "Testing". If the user presses tab and then enter, it of course works.

I would like the prompt funtion to only return values from the list of completion, never nonsensical strings like "tst" that the user types to match quickly. Tab before enter should not be required. How can I achieve that?


Solution

  • You could create a custom key binding to perform a completion when the user hits enter. For example:

    from prompt_toolkit import prompt
    from prompt_toolkit.completion import FuzzyWordCompleter
    from prompt_toolkit.key_binding import KeyBindings
    from prompt_toolkit.filters import (
        has_completions,
        completion_is_selected,
    )
    
    # Override enter key to automatically perform first completion.
    key_bindings = KeyBindings()
    filter = has_completions & ~completion_is_selected
    @key_bindings.add("enter", filter=filter)
    def _(event):
        event.current_buffer.go_to_completion(0)
        event.current_buffer.validate_and_handle()
    
    completer = FuzzyWordCompleter([
        "Using", "Testing", "Building", "Designing", "Documenting"
    ])
    result = prompt("$ ",
        completer=completer,
        complete_while_typing=True,
        key_bindings=key_bindings,
    )
    if result:
        print(result)
    

    The key bindings that would be overridden are currently in shortcuts/prompt.py and key_binding/bindings/basic.py.

    If your prompt application is more complicated (e.g. multiline input or multiple buffers), then you probably need additional logic to handle those cases. prompt_toolkit.filters.is_multiline could be useful.