Skip to content

Commit

Permalink
Merge Pull Request ipython#3801
Browse files Browse the repository at this point in the history
Autocompletion: ordering of completions for magic commands and variables with same name

closes ipython#3723
closes ipython#3801
  • Loading branch information
minrk committed Oct 28, 2013
2 parents 70e3848 + 4fc71f7 commit 2de1e66
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
44 changes: 43 additions & 1 deletion IPython/core/completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,45 @@ def compress_user(path, tilde_expand, tilde_val):
return path



def penalize_magics_key(word):
"""key for sorting that penalizes magic commands in the ordering
Normal words are left alone.
Magic commands have the initial % moved to the end, e.g.
%matplotlib is transformed as follows:
%matplotlib -> matplotlib%
[The choice of the final % is arbitrary.]
Since "matplotlib" < "matplotlib%" as strings,
"timeit" will appear before the magic "%timeit" in the ordering
For consistency, move "%%" to the end, so cell magics appear *after*
line magics with the same name.
A check is performed that there are no other "%" in the string;
if there are, then the string is not a magic command and is left unchanged.
"""

# Move any % signs from start to end of the key
# provided there are no others elsewhere in the string

if word[:2] == "%%":
if not "%" in word[2:]:
return word[2:] + "%%"

if word[:1] == "%":
if not "%" in word[1:]:
return word[1:] + "%"

return word



class Bunch(object): pass


Expand Down Expand Up @@ -888,7 +927,10 @@ def complete(self, text=None, line_buffer=None, cursor_pos=None):
# different types of objects. The rlcomplete() method could then
# simply collapse the dict into a list for readline, but we'd have
# richer completion semantics in other evironments.
self.matches = sorted(set(self.matches))

# use penalize_magics_key to put magics after variables with same name
self.matches = sorted(set(self.matches), key=penalize_magics_key)

#io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
return text, self.matches

Expand Down
28 changes: 28 additions & 0 deletions IPython/core/tests/test_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,31 @@ def _bar_cellm(line, cell):
nt.assert_not_in('%_bar_cellm', matches)
nt.assert_in('%%_bar_cellm', matches)


def test_magic_completion_order():

ip = get_ipython()
c = ip.Completer

# Test ordering of magics and non-magics with the same name
# We want the non-magic first

# Before importing matplotlib, there should only be one option:

text, matches = c.complete('mat')
nt.assert_equal(matches, ["%matplotlib"])


ip.run_cell("matplotlib = 1") # introduce name into namespace

# After the import, there should be two options, ordered like this:
text, matches = c.complete('mat')
nt.assert_equal(matches, ["matplotlib", "%matplotlib"])


ip.run_cell("timeit = 1") # define a user variable called 'timeit'

# Order of user variable and line and cell magics with same name:
text, matches = c.complete('timeit')
nt.assert_equal(matches, ["timeit", "%timeit","%%timeit"])

0 comments on commit 2de1e66

Please sign in to comment.