Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I make IPython organize tab completion possibilities by class?

When an object has hundreds of methods, tab completion is hard to use. More often than not the interesting methods are the ones defined or overridden by the inspected object's class and not its base classes.

How can I get IPython to group its tab completion possibilities so the methods and properties defined in the inspected object's class come first, followed by those in base classes?

It looks like the undocumented inspect.classify_class_attrs(cls) function along with inspect.getmro(cls) give me most of the information I need (these were originally written to implement python's help(object) feature).

By default readline displays completions alphabetically, but the function used to display completions can be replaced with ctypes or the readline module included with Python 2.6 and above. I've overridden readline's completions display and it works great.

Now all I need is a method to merge per-class information (from inspect.* per above) with per-instance information, sort the results by method resolution order, pretty print and paginate.

For extra credit, it would be great to store the chosen autocompletion, and display the most popular choices first next time autocomplete is attempted on the same object.

like image 917
joeforker Avatar asked Jan 21 '09 14:01

joeforker


2 Answers

Since I am not using Python 2.6 or 3.0 yet and don't have readline.set_completion_display_matches_hook(), I can use ctypes to set completion_display_func like so:

from ctypes import *

rl = cdll.LoadLibrary('libreadline.so')

def completion_display_func(matches, num_matches, max_length):
    print "Hello from Python"
    for i in range(num_matches):
        print matches[i]

COMPLETION_DISPLAY_FUNC = CFUNCTYPE(None, POINTER(c_char_p), c_int, c_int)
hook = COMPLETION_DISPLAY_FUNC(completion_display_func)
ptr = c_void_p.in_dll(rl, 'rl_completion_display_matches_hook')
ptr.value = cast(hook, c_void_p).value

Now, when I press 'tab' to complete, my own function prints the list of completions. So that answers the question 'how do I change the way readline displays completions'.

like image 68
joeforker Avatar answered Oct 10 '22 01:10

joeforker


I don't think this can be accomplished easily. There's no mechanism in Ipython to perform it in any case.

Initially I had thought you could modify Ipython's source to change the order (eg by changing the dir2() function in genutils.py). However it looks like readline alphabetically sorts the completions you pass to it, so this won't work (at least not without a lot more effort), though you could perhaps exclude methods on the base class completely.

like image 40
Brian Avatar answered Oct 10 '22 00:10

Brian