Skip to content

Instantly share code, notes, and snippets.

@ricrogz
Last active July 26, 2016 07:09
Show Gist options
  • Save ricrogz/97366adf1c620009ce6859a3faf5f151 to your computer and use it in GitHub Desktop.
Save ricrogz/97366adf1c620009ce6859a3faf5f151 to your computer and use it in GitHub Desktop.
python: recursive command line completion
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
USE UNDER YOUR OWN RESPONSIBILITY!!
IMPORTANT: options with sub-levels MUST end with spaces!!!
"""
import logging
import readline
def completer(text, state):
""" Adapted from here: https://pymotw.com/2/readline/ """
global current_candidates
places = [ 'a', 'aa', 'ab', 'b', 'z', ]
stores = { 'a ': [], 'aa ': [], 'ab ': places, 'ac ': places, 'v ': [], 'e ': places, }
options = {
'#go ':
stores,
'#goto ':
places,
'#other ':
[ 'a', 'b', 'bo', 'ca', 'co', 'ee', 'eep', 'r', 'g', 'c', 'l', ]
}
if state == 0:
# This is the first time for this text, so build a match list.
origline = readline.get_line_buffer()
begin = readline.get_begidx()
end = readline.get_endidx()
being_completed = origline[begin:end]
words = origline.split()
if not words:
current_candidates = sorted(options.keys())
else:
try:
if begin == 0:
# first word
candidates = options.keys()
else:
candidates = options
# later word
for prev in words:
if prev in candidates and not origline.endswith(prev):
candidates = candidates[prev]
break
elif prev + ' ' in candidates and prev + ' ' in origline:
candidates = candidates[prev + ' ']
if type(candidates) == dict:
candidates = list(candidates.keys())
if being_completed:
# match options with portion of input
# being completed
current_candidates = [w for w in candidates if w.startswith(being_completed)]
else:
# matching empty string so use all candidates
current_candidates = candidates
except (KeyError, IndexError):
current_candidates = []
try:
response = current_candidates[state]
except IndexError:
response = None
return response
if __name__ == '__main__':
# Prepare logger
logging.getLogger(None).setLevel(logging.DEBUG)
logging.basicConfig()
# Setup command completion
# Register our completer function
current_candidates = []
readline.set_completer_delims(' ')
readline.set_completer(completer)
readline.parse_and_bind('tab: complete')
# Console reading loop
while True:
# Check for Ctrl-C; clean up and exit if found
try:
line = input('>> ').strip()
except KeyboardInterrupt:
break
# Pass inputo to handler function (only if not empy)
if line:
print("-----> " + line)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment