from IPython.core.completer import IPCompleter, cursor_to_position, position_to_cursor, Completion
import types
import parso
# try to avoid recursive patching if rerun.
if getattr(IPCompleter,'_patched', False) == False:
original_method = IPCompleter._completions
IPCompleter._patched = True
def my_completer(self, full_text: str, offset: int, *, _timeout):
# there is either bytes, coordinate in test, and/or rows/columns either 0 or 1 index,
# the hard part is converting between those.
# here i'm using parso to find "if" we are in a string
# and find the beginning of the string, you don't have to do do that.
pos = position_to_cursor(full_text, offset)
pos_parso = pos[0]+1, pos[1]
tree = parso.parse(full_text)
t = tree.get_leaf_for_position(pos_parso)
from there import syslogprint
syslogprint(t, t.type)
if t.type == 'string': # might not be 'string' is the string quotes is not closed, may be 'name'.
start_pos = t.start_pos[0]-1, t.start_pos[1]
start_index = cursor_to_position(full_text, *start_pos)+1
stop_index = offset
interesting_text=full_text[start_index:stop_index]
if interesting_text.startswith('test'):
# do you best logic here.
for item in ['testaa','test_bb','test-cc', 'test*dd', 'test:ee', '¯\_(ツ)_/¯ == 🤷']:
yield Completion(
start_index, # the start of what it will replace,
stop_index, # the end of what it will repalce/
item, # by what it will be replaced.
# this shoudl make the completer show "signature" next to the completion
# if you use "function"
# in the terminal at least, I don't think it's supported in JupyterLab
type='function',
_origin='jedi',
signature='(some metainfo)')
# let's keep original results, again you don't have to.
yield from original_method(self, full_text, offset, _timeout=_timeout)
# this should be sufficient in a startup file or configuration file, if it's done _before_ IPython start
IPCompleter._completions = my_completer
# this in a live IPython.
# be careful with re-running or you may end up with recursiosn errors.
ip = get_ipython()
ip.Completer._completions = types.MethodType(my_completer, ip.Completer)