mirror of
https://github.com/davidhalter/jedi.git
synced 2026-10-18 08:21:27 +08:00
Implement pyrepl completions, fixes #2069
This commit is contained in:
1 parent
91206f4c65
commit
5d3295e0f9
3 files changed
+71
-14
No files matched your search
@@ -1,8 +1,8 @@
|
|||||||
"""
|
"""
|
||||||
To use Jedi completion in Python interpreter, add the following in your shell
|
To use Jedi completion in Python interpreter, add the following in your shell
|
||||||
setup (e.g., ``.bashrc``). This works only on Linux/Mac, because readline is
|
setup (e.g., ``.bashrc``). Jedi configures the classic readline shell and
|
||||||
not available on Windows. If you still want Jedi autocompletion in your REPL,
|
Python 3.13+'s new ``_pyrepl`` shell when those hooks are available.
|
||||||
just use IPython instead::
|
You might also want to try IPython instead, which also uses Jedi::
|
||||||
|
|
||||||
export PYTHONSTARTUP="$(python -m jedi repl)"
|
export PYTHONSTARTUP="$(python -m jedi repl)"
|
||||||
|
|
||||||
|
|||||||
+41
-11
@@ -100,17 +100,10 @@ def setup_readline(namespace_module=__main__, fuzzy=False):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
jedi_rl = JediRL()
|
||||||
# Need to import this one as well to make sure it's executed before
|
|
||||||
# this code. This didn't use to be an issue until 3.3. Starting with
|
def configure_readline(readline):
|
||||||
# 3.4 this is different, it always overwrites the completer if it's not
|
readline.set_completer(jedi_rl.complete)
|
||||||
# already imported here.
|
|
||||||
import rlcompleter # noqa: F401
|
|
||||||
import readline
|
|
||||||
except ImportError:
|
|
||||||
print("Jedi: Module readline not available.")
|
|
||||||
else:
|
|
||||||
readline.set_completer(JediRL().complete)
|
|
||||||
readline.parse_and_bind("tab: complete")
|
readline.parse_and_bind("tab: complete")
|
||||||
# jedi itself does the case matching
|
# jedi itself does the case matching
|
||||||
readline.parse_and_bind("set completion-ignore-case on")
|
readline.parse_and_bind("set completion-ignore-case on")
|
||||||
@@ -122,6 +115,43 @@ def setup_readline(namespace_module=__main__, fuzzy=False):
|
|||||||
# No delimiters, Jedi handles that.
|
# No delimiters, Jedi handles that.
|
||||||
readline.set_completer_delims('')
|
readline.set_completer_delims('')
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _pyrepl.readline as pyrepl_readline # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
pyrepl_readline = None
|
||||||
|
else:
|
||||||
|
original_setup = getattr(pyrepl_readline, '_setup', None)
|
||||||
|
if original_setup is not None and not getattr(original_setup, '__jedi_wrapped__', False):
|
||||||
|
def _jedi_pyrepl_setup(namespace):
|
||||||
|
original_setup(namespace)
|
||||||
|
configure_readline(pyrepl_readline)
|
||||||
|
wrapper = getattr(pyrepl_readline, '_wrapper', None)
|
||||||
|
if wrapper is not None:
|
||||||
|
# Reset the original completer to None so Jedi's readline
|
||||||
|
# completer is preferred.
|
||||||
|
wrapper.config.module_completer = _NoPyreplModuleCompleter()
|
||||||
|
|
||||||
|
_jedi_pyrepl_setup.__jedi_wrapped__ = True # type: ignore[attr-defined]
|
||||||
|
pyrepl_readline._setup = _jedi_pyrepl_setup
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Need to import this one as well to make sure it's executed before
|
||||||
|
# this code. This didn't use to be an issue until 3.3. Starting with
|
||||||
|
# 3.4 this is different, it always overwrites the completer if it's not
|
||||||
|
# already imported here.
|
||||||
|
import rlcompleter # noqa: F401
|
||||||
|
import readline
|
||||||
|
except ImportError:
|
||||||
|
if pyrepl_readline is None:
|
||||||
|
print("Jedi: Module readline not available.")
|
||||||
|
else:
|
||||||
|
configure_readline(readline)
|
||||||
|
|
||||||
|
|
||||||
|
class _NoPyreplModuleCompleter:
|
||||||
|
def get_completions(self, line, include_values=False):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def version_info():
|
def version_info():
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
import types
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -136,3 +137,29 @@ class TestSetupReadline(unittest.TestCase):
|
|||||||
|
|
||||||
def test_version_info():
|
def test_version_info():
|
||||||
assert utils.version_info()[:2] > (0, 7)
|
assert utils.version_info()[:2] > (0, 7)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pyrepl():
|
||||||
|
try:
|
||||||
|
from _pyrepl import readline # zuban: ignore[import-not-found]
|
||||||
|
except ImportError: # This is typical before Python 3.13
|
||||||
|
pass
|
||||||
|
|
||||||
|
utils.setup_readline(types.SimpleNamespace())
|
||||||
|
readline._setup({})
|
||||||
|
|
||||||
|
def complete(text):
|
||||||
|
completer = readline.get_completer()
|
||||||
|
i = 0
|
||||||
|
completions = []
|
||||||
|
while True:
|
||||||
|
completion = completer(text, i)
|
||||||
|
if completion is None:
|
||||||
|
break
|
||||||
|
completions.append(completion)
|
||||||
|
i += 1
|
||||||
|
return completions
|
||||||
|
|
||||||
|
assert complete("str") == ["str"]
|
||||||
|
assert complete("str().upp") == ["str().upper"]
|
||||||
|
assert complete("import multiproc") == ["import multiprocessing"]
|
||||||
Reference in new issue
Block a user