7

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.

MajesticRa
  • 13,770
  • 12
  • 63
  • 77
  • 1
    This isn't a complete answer, and it may be overkill for something this simple, but using `curses` is a good (albeit complex) way to do this sort of thing: http://docs.python.org/library/curses.html Have a look a the tutorial here: http://docs.python.org/howto/curses.html#curses-howto – Joe Kington Feb 01 '11 at 23:39
  • It could be! Thank you! But we are absolutely satisfied with the functionality readline provides. And the only thing we need is to display this options on autocompletion. We looked into curses, but it is really too complex for only one little thing like this. – MajesticRa Feb 01 '11 at 23:44
  • Interesting question, I've had ideas about a similar thing. – Skurmedel Feb 01 '11 at 23:49
  • 1
    Sorry for this dumb question, but did you tried ``? Your code shows all possible completions on both Linux and OS X if I just hit tab twice (which isn't uncommon for a shell, either). – miku Feb 01 '11 at 23:50
  • Is is tricky. I tried it on windows and arch linux machines and `` didn't worked. When I saw this comment I've tried also on fedora 14 vm - it worked! I listed a solution for windows machine below. set_completion_display_matches_hook was a solution for my arch linux. – MajesticRa Feb 02 '11 at 00:22
  • Try ipython and bpython. They are python, but customized for friendly command-line use, etc. – Apalala Feb 02 '11 at 01:37

2 Answers2

7

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 ;)

miku
  • 181,842
  • 47
  • 306
  • 310
  • Thank you! Your answer solved problems on linux. It is not working on windows. But windows has perverse version of readline and cmd so it is unfortunately ok. – MajesticRa Feb 01 '11 at 23:59
2

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.

Community
  • 1
  • 1
MajesticRa
  • 13,770
  • 12
  • 63
  • 77