Skip to content

Commit 08fbc16

Browse files
committed
Add a simple completion hook
1 parent e4d60e9 commit 08fbc16

3 files changed

Lines changed: 64 additions & 0 deletions

File tree

src/julia_api.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,18 @@ function setattr(mod::Module, name, value)
3030
return nothing
3131
end
3232

33+
@static if VERSION < v"0.7-"
34+
completions(_a...; __k...) = String[]
35+
else
36+
function completions(string, pos, context_module = Main)
37+
ret, _, should_complete =
38+
REPL.completions(string, pos, context_module)
39+
if should_complete
40+
return map(REPL.completion_text, ret)
41+
else
42+
return String[]
43+
end
44+
end
45+
end
46+
3347
end # module

src/replhelper/core.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ def get_api(main):
158158
return main._JuliaNameSpace__julia
159159

160160

161+
def get_cached_api():
162+
return get_api(_Main)
163+
164+
161165
def get_main(**kwargs):
162166
"""
163167
Create or get cached `Main`.
@@ -184,6 +188,11 @@ def ipython_options(**kwargs):
184188
c.TerminalIPythonApp.display_banner = False
185189
c.TerminalInteractiveShell.confirm_exit = False
186190

191+
from . import ipyext
192+
c.InteractiveShellApp.extensions = [
193+
ipyext.__name__,
194+
]
195+
187196
return dict(user_ns=user_ns, config=c)
188197

189198

@@ -233,6 +242,13 @@ def revise():
233242
Main._JuliaNameSpace__julia.__class__ = replhelper.core.JuliaAPI
234243
replhelper.core._Main = Main
235244

245+
try:
246+
replhelper.ipyext
247+
except AttributeError:
248+
pass
249+
else:
250+
reload(replhelper.ipyext)
251+
236252
try:
237253
replhelper.tests
238254
except AttributeError:

src/replhelper/ipyext.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from .core import get_cached_api
2+
3+
4+
def julia_completer(julia, self, event):
5+
pos = event.line.find("Main.eval")
6+
if pos < 0:
7+
return []
8+
pos += len("Main.eval('") # pos: beginning of Julia code
9+
julia_code = event.line[pos:]
10+
julia_pos = len(event.text_until_cursor) - pos
11+
completions = julia.completions(julia_code, julia_pos)
12+
if "." in event.symbol:
13+
# When completing "Base.Enums.s" we need to add prefix "Base.Enums"
14+
prefix = event.symbol.rsplit(".", 1)[0]
15+
completions = [".".join((prefix, c)) for c in completions]
16+
global last_completions, last_event
17+
last_completions = completions
18+
last_event = event
19+
return completions
20+
# See:
21+
# IPython.core.completer.dispatch_custom_completer
22+
23+
24+
def _julia_completer(self, event):
25+
return julia_completer(get_cached_api(), self, event)
26+
27+
28+
def load_ipython_extension(ip):
29+
ip.set_hook("complete_command", _julia_completer,
30+
re_key=r""".*\bMain\.eval\(["']""")
31+
# See:
32+
# https://ipython.readthedocs.io/en/stable/api/generated/IPython.core.hooks.html
33+
# IPython.core.interactiveshell.init_completer
34+
# IPython.core.completerlib (quick_completer etc.)

0 commit comments

Comments
 (0)