Repository: ipython/ipython

Issue:
`%matplotlib` is not showing when pressing tab for autocompletation after `%pylab`
The issue appears in IPython 6.1, but not in 6.0
I first realize about it using Spyder: spyder-ide/spyder#5020

Nevertheless, even if it is not shown, `%matplotlib`can be executed and it works.


Discussion:
Copying my answer from linked issue:

That's a side effect of https://github.com/ipython/ipython/pull/10542, basically %pylab injects `matplotlib` into the namespace and thus is not completed as a magic anymore. This was requested in  https://github.com/ipython/ipython/issues/4877, We should probably be less extream and still complete to magics if the text starts with `%`/`%%`

Resolving patch:
diff --git a/IPython/core/completer.py b/IPython/core/completer.py
--- a/IPython/core/completer.py
+++ b/IPython/core/completer.py
@@ -1221,7 +1221,9 @@ def magic_matches(self, text):
         cell_magics = lsm['cell']
         pre = self.magic_escape
         pre2 = pre+pre
-        
+
+        explicit_magic = text.startswith(pre)
+
         # Completion logic:
         # - user gives %%: only do cell magics
         # - user gives %: do both line and cell magics
@@ -1229,11 +1231,23 @@ def magic_matches(self, text):
         # In other words, line magics are skipped if the user gives %% explicitly
         #
         # We also exclude magics that match any currently visible names:
-        # https://github.com/ipython/ipython/issues/4877
+        # https://github.com/ipython/ipython/issues/4877, unless the user has
+        # typed a %:
+        # https://github.com/ipython/ipython/issues/10754
         bare_text = text.lstrip(pre)
         global_matches = self.global_matches(bare_text)
-        matches = lambda magic: magic.startswith(bare_text) \
-                                and magic not in global_matches
+        if not explicit_magic:
+            def matches(magic):
+                """
+                Filter magics, in particular remove magics that match
+                a name present in global namespace.
+                """
+                return ( magic.startswith(bare_text) and
+                         magic not in global_matches )
+        else:
+            def matches(magic):
+                return magic.startswith(bare_text)
+
         comp = [ pre2+m for m in cell_magics if matches(m)]
         if not text.startswith(pre2):
             comp += [ pre+m for m in line_magics if matches(m)]


Test patch:
diff --git a/IPython/core/tests/test_completer.py b/IPython/core/tests/test_completer.py
--- a/IPython/core/tests/test_completer.py
+++ b/IPython/core/tests/test_completer.py
@@ -589,6 +589,24 @@ def test_magic_completion_shadowing():
     text, matches = c.complete("mat")
     nt.assert_equal(matches, ["%matplotlib"])
 
+def test_magic_completion_shadowing_explicit():
+    """
+    If the user try to complete a shadowed magic, and explicit % start should
+    still return the completions.
+    """
+    ip = get_ipython()
+    c = ip.Completer
+
+    # Before importing matplotlib, %matplotlib magic should be the only option.
+    text, matches = c.complete("%mat")
+    nt.assert_equal(matches, ["%matplotlib"])
+
+    ip.run_cell("matplotlib = 1")
+
+    # After removing matplotlib from namespace, the magic should still be
+    # the only option.
+    text, matches = c.complete("%mat")
+    nt.assert_equal(matches, ["%matplotlib"])
 
 def test_magic_config():
     ip = get_ipython()