BMC icon indicating copy to clipboard operation
BMC copied to clipboard

Feature request: tag name completion from the set of existing directories

Open Hunter-Github opened this issue 9 years ago • 3 comments

Rationale: simplification of workflow, otherwise one has to keep two terminals side by side to be sure of tag spelling.

Related: https://stackoverflow.com/questions/5637124/tab-completion-in-pythons-raw-input

Hunter-Github avatar Sep 10 '16 10:09 Hunter-Github

I should have more time by now, I will try to fix the pending issues ASAP. Thanks for the reports!

Phyks avatar Sep 11 '16 11:09 Phyks

Since then I've noted the great prompt_toolkit which makes the whole endeavor much easier:

from __future__ import unicode_literals
from prompt_toolkit.contrib.completers import PathCompleter
from prompt_toolkit import prompt

pc = PathCompleter(get_paths=None, min_input_len=1)

text = prompt('Tag: ', completer=pc, complete_while_typing=False)

Something like that...

Hunter-Github avatar Sep 11 '16 14:09 Hunter-Github

Well, here goes a handy utility that does the trick in Python 3 (read_pt -C 'ls $HOME/Papers')

#!/usr/bin/env python
"""
Autocompletion example that displays the autocompletions like readline does by
binding a custom handler to the Tab key.
"""
from __future__ import unicode_literals

from prompt_toolkit import prompt
from prompt_toolkit.contrib.completers import WordCompleter
from prompt_toolkit.key_binding.bindings.completion import \
    display_completions_like_readline
from prompt_toolkit.key_binding.bindings.basic import \
    load_abort_and_exit_bindings
from prompt_toolkit.key_binding.defaults import load_key_bindings
from prompt_toolkit.key_binding.registry import MergedRegistry
from prompt_toolkit.keys import Keys
import argparse
# import os
import sys
import subprocess


# Create key bindings registry with a custom binding for the Tab key that
# displays completions like GNU readline.
registry = MergedRegistry(registries=(load_key_bindings(),
                                      load_abort_and_exit_bindings()))
registry.add_binding(Keys.ControlI)(display_completions_like_readline)

# TODO : subprocess error processing


def main():
    parser = argparse.ArgumentParser(description='Replacement for the bash\
                                        built-in read command with\
                                        programmable completion\
                                        rules. Output is dumped into stderr.\
                                        Recommended use in scripts:\
                                        myVar=$(read_pt -F FILE 3>&1 1>&2\
                                            2>&3)')

    parser.add_argument('-C', dest='completion_command', help='command string\
                        to run to get newline-separated completion candidates')
    parser.add_argument('-F', dest='completion_file', help='file with newline-\
                        separated completion candidates')
    parser.add_argument('-i', dest='initial_text', help='Use TEXT as the\
                        initial text for Readline')
    parser.add_argument('-p', dest='prompt_text', help='output the string\
                        PROMPT without a trailing newline before attempting\
                        to read')

    args = parser.parse_args()

    completion_array = []

    if args.initial_text is None:
        itext = ""
    else:
        itext = args.initial_text

    if args.prompt_text is None:
        ptext = ""
    else:
        ptext = args.prompt_text.replace('\n', '')

    if args.completion_file is not None:
        with open(args.completion_file, 'r') as cfile:
            completion_array = [x.replace('\n', '') for x in cfile.readlines()]
    else:
        if args.completion_command is not None:
            completion_array = subprocess.getoutput(args.completion_command).\
                split('\n')
        else:
            sys.exit(3)

    word_completer = WordCompleter(completion_array, ignore_case=True)

    try:
        text = prompt(ptext, completer=word_completer,
                      key_bindings_registry=registry,
                      default=itext,
                      # Important: for this to work: `complete_while_typing`
                      # needs to be False.
                      complete_while_typing=False)
        sys.stderr.write(text)

    except KeyboardInterrupt:
        pass


if __name__ == '__main__':
    main()

Hunter-Github avatar Apr 22 '17 13:04 Hunter-Github