How to make python autocompletion display matches?

2020-07-09 08:31发布

I have kind of a completer class with an autocompletion function. Simple version:

class Completer:
    def __init__(self):
        self.words = ["mkdir","mktbl", "help"]
        self.prefix = None

    def complete(self, prefix, index):
        if prefix != self.prefix:
            self.matching_words = [w for w in self.words if w.startswith(prefix)]
            self.prefix = prefix
        else:
            pass                
        try:
            return self.matching_words[index]
        except IndexError:
            return None

And execute something like this to get auto-completion with readline:

import readline
readline.parse_and_bind("tab: complete")

completer = Completer()
readline.set_completer(completer.complete)
user_input =raw_input("> ")

So, there are 3 words for auto-completion ["help", "mkdir","mktbl"] in the example.

if a user executes:
> he<tab>
the user gets:
> help

but if the user executes
> mk<tab>
nothing is happening because there are not a single match (mkdir and mktbl)

How to display options in case there are several matches? Like the Bash do with a file names autocompletion?

Thus user whold get something like:
> mk<tab>
mktbl mkdir
> mk<cursor>


P.S. I have tried to put
_readline.insert_text(...)_
and
print ...
into completer function but it brakes the insertion, so a user gets something like this:
> mk<tab>
> mkmktbl mkdir <cursor>

P.P.S I need a linux solution.

2条回答
甜甜的少女心
2楼-- · 2020-07-09 08:50

Set the readline option

set show-all-if-ambiguous on

if you want completions after the first <tab>. Otherwise just hit <tab> twice.

Reference: http://caliban.org/bash/, Section readline Tips and Tricks

PS. Tested your code on OS X and Linux, it works well (on my machines ;)

查看更多
SAY GOODBYE
3楼-- · 2020-07-09 08:59

I was suggested a solution that complete the answer. It allows to organize completion output of autocompletion options.

For linux readline there are function readline.set_completion_display_matches_hook
http://docs.python.org/library/readline.html?highlight=readline#readline.set_completion_display_matches_hook

So, for the example listed above this code

def print_suggestions(self, substitution, matches, longest_match_length) :
    print "useless text to be displayed"
    print substitution
    print " ".join[match for match in matches]
    print longest_match_length

readline.set_completion_display_matches_hook(print_suggestions)

this will produse:
> mk<tab>

useless text to be displayed
mk
mkdir mktbl
5  

> mk<cursor>

For windows readline there is an answer at stack overflow:
How do I make IPython organize tab completion possibilities by class?

Don't know how it works for mac.

查看更多
登录 后发表回答