BMC
BMC copied to clipboard
Feature request: tag name completion from the set of existing directories
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
I should have more time by now, I will try to fix the pending issues ASAP. Thanks for the reports!
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...
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()