How to add new autocompletions

I want to add autocompletions for unicode characters (like ‘->’ becoming ‘→’) so I can use it similar to a shortcut, but cannot find out how to implement this functionality as a JupyterLab extension. I have read the docs on the completer module, but it doesn’t seem to be able to do what I want. I have also tried googling for an answer and looking through Jupyter LSP github, but have been unsuccessful. Are there any examples, templates or explanations on how to add new autocompletions?

1 Like

This depends on the language/kernel that you are using. For example, if you use IPython you could do something like this:

from IPython.core.latex_symbols import latex_symbols

# >l<eft a>r<row (okay, I could have chosen a better alias)
latex_symbols['\\lr'] = '→'

lr

See https://stackoverflow.com/a/50647764/6646912

I am making the extension in typescript and want to make it not specific to any language or notebook that is opened.

Also, as mentioned in my other question, the end goal is to add these types of auto completions to markdown cells and it doesn’t seem like IPython shortcuts can work in the markdown cells.

Oh, that’s a completely different situation. Sorry I did not realise you are writing an extension. It is not currently easy I am afraid. I will be working to make it possible (see Refactor completer to support external providers by krassowski · Pull Request #600 · krassowski/jupyterlab-lsp · GitHub and Completer public API refactor wishlist · Issue #9763 · jupyterlab/jupyterlab · GitHub) in July/August but this will only arrive for JupyterLab 4.0. If you absolutely have to have this functionality, then in the meantime you would likely need to follow the same path as jupyterlab-lsp.

Hi @krassowski, I’ve been trying to learn how to create custom completers (by IPython, and do want it per notebook as opposed to @jaysun_n) and it’s been quite a struggle. IPython’s documentation (IPython Completer) on this is not good (barely anything more than API docs, and those are bad too). There aren’t any good examples elsewhere either. It also seems there are different APIs for different versions of IPython with strange compatibility issues between them.

Can you point me to any good resources, examples, or whatever, on the subject?

My specific goal is similar to the Latex example you provided. I want to have some keyword that is replaced by a suggested completion. The replacement is important, so it’s not really a “completion”.

I’ve managed to implement something that works:

from IPython.core.completer import context_matcher, CompletionContext, SimpleCompletion
import re

@context_matcher()
def custom_matcher(context: CompletionContext):
    completions = []
    m = re.search(r"^_p(.*)", context.token)
    if m:
        completions.append(
            SimpleCompletion(f"jobs = get_jobs("{m.group(1)}"), type="MyStuff")
        )
    return dict(completions = completions, suppress = True)

get_ipython().Completer.custom_matchers.append(custom_matcher)

But I get different behavior depending on the versions of IPython and Jupyter, and whether I’m directly in IPython or in a notebook.

I would also like to fully customize a completer (or it is a “matcher”? I don’t know what I’m doing). I guess I would need to define a class (Inherit from what?) instead of the @context_matcher() decorator, and perhaps return something other than SimpleCompletion? I would also like to customize the tokenization. Etc, etc.

Is there something I need to implement differently for completions in notebooks versus IPython console?

Nowadays we have lsp. Should we be implementing these things through different lsp servers instead of IPython?

IPython’s documentation mentions Jedi. Should I be looking at Jedi’s ways instead?

Sorry for the long post. I’d be happy to start another thread if that will help other better. Thanks!

IPython’s documentation (IPython Completer) on this is not good (barely anything more than API docs, and those are bad too). There aren’t any good examples elsewhere either.

Ouch. Contributions are welcome feel free to tag me for a review. Though any examples would need to be maintained by someone and I did not see too many folks volunteer to contribute here :wink:

It also seems there are different APIs for different versions of IPython with strange compatibility issues between them.

What do you mean specifically? Are there any incompatibilities that you found? Or do you just mean that we added an arguably a better API which was not available in older IPython versions?

I’ve managed to implement something that works:

Looks good I guess? There is a missing " in your code I believe. Using regex on a token is a bit naive for anything more complex, the intent of exposing token is not that it will solve all your problems but is good enough for 80% of custom completion matchers.

But I get different behavior depending on the versions of IPython and Jupyter, and whether I’m directly in IPython or in a notebook.

Which is?

I want to have some keyword that is replaced by a suggested completion. The replacement is important, so it’s not really a “completion”.

That should work, except that depending on what extensions you have installed (wink jupyterlab-lsp) pre-filtering may be enabled rejecting compeltions which do not start with the prefix; this will be fixed in jupyterlab-lsp in the future.

I would also like to customize the tokenization.

You may want to have a look at:

Nowadays we have lsp. Should we be implementing these things through different lsp servers instead of IPython?

No. LSP will not give you completions in IPython

IPython’s documentation mentions Jedi. Should I be looking at Jedi’s ways instead?

No. Jedi has a scope for helping with code completions not emmet completions AFAIK.

1 Like