Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: inline completions #4623

Merged
merged 46 commits into from
Dec 1, 2024
Merged

Conversation

kassick
Copy link
Contributor

@kassick kassick commented Nov 25, 2024

As discussed in #4581, this PR adds support for Inline Completions

Using some server with inlineCompletionProvider capability (I'm using the copilot-node-server with this implementation), the inline completion is triggered automatically if lsp-inline-completion-enable is set to t. The user can also call lsp-inline-completion-display explicitly to have the completion displayed.

Captura de tela de 2024-11-25 10-50-01

Kooha-2024-11-25-10-51-45

Optionally, the user can add lsp-inline-completion-show-keys to the lsp-inline-completion-shown-hook and the number of available completions and the keys used to interact with the tooltips are shown in the minibuffer.
When the completion overlay is displayed, a message is shown in the minibuffer as part of the UI, so the user knows if there are more then one completion available.

image

When the inline completion tooltip is being displayed, pressing any key that is not mapped in lsp-inline-completion-active-map causes the tooltip to be hidden and the key is processed with the current active keymap. This way, if the completion is shown automatically, the user can continue typing to have the completion ignored.

@kassick kassick force-pushed the feat/inline-completions branch 5 times, most recently from bf4ab0a to 71c81dd Compare November 25, 2024 14:45
@kassick kassick force-pushed the feat/inline-completions branch from 71c81dd to f5b572b Compare November 25, 2024 15:49
@kassick kassick force-pushed the feat/inline-completions branch from 9dea79c to f9783fd Compare November 25, 2024 16:00
@kassick kassick force-pushed the feat/inline-completions branch from c32fa58 to 828875b Compare November 25, 2024 16:07
@kassick
Copy link
Contributor Author

kassick commented Nov 26, 2024

A note about company mode and the inline completion overlay: Since the completions are not provided by company, we may end up with the company popup displayed alongside (or over) the inline completion overlay (as it happened already with copilot.el).

To workaround this issue, I've added code to cancel company before showing the overlay and then restore it on cancel.

Kooha-2024-11-26-14-40-17.webm

Switching between the two completion UIs can be achieved by binding company-manual-begin and lsp-inline-completion-display.

Nonetheless, I've added a variable that can inhibit inline completion mode on certain conditions, such as company being active. For example, I have the following snippet in my user settings:

Since lsp-mode already provides some support for company-mode by default, I've added a minor mode that can add some sane interaction between company and the inline completion UI. Other frontends can replicate the minor mode, as it only adjust hooks and a few variables that control when company is triggered.

    (add-hook 'lsp-inline-completion-mode-hook #'lsp-inline-completion-company-integration-mode)

Add a list of predicates that can inhibit triggering inline completions --
e.g.:

    ```elisp
    (defun lsp-inline-completion-inhibit-if-company-active ()
        (and (bound-and-true-p company-mode) (company--active-p)))

      (push 'lsp-inline-completion-inhibit-if-company-active lsp-inline-completion-inhibit-predicates)
    ```
@kassick kassick force-pushed the feat/inline-completions branch from 04fa88a to da2d8c2 Compare November 26, 2024 18:50
lsp-protocol.el Outdated Show resolved Hide resolved
lsp-inline-completion.el Outdated Show resolved Hide resolved
lsp-inline-completion--after-change, added to lsp on-change hooks, is
triggered on a timer by `lsp--after-change`. The inline completion
maybe-display function is also triggered on a timer and it must check if the
position and current buffer did not change since the change as actually
occurred.

We can not store this state in lsp-inline-completion--after-change because the
user may have clicked somewhere before the timer activated it.

This commit introduces a `lsp--after-change-vals` plist to store the context
before the timers have been started.

lsp-inline-completion--after-change then fetches these values and forward as
arguments to the timer invocation of maybe-display, which then ensures that
the state has not changed.
Auto-substitution of tabs to space did not use the correct number of spaces
@kassick
Copy link
Contributor Author

kassick commented Nov 28, 2024

I think this looks good now, just a few nit comments you might want to consider for a smooth load of this mode.

I've resolved the discussions that have been accepted and fixed an issue with state tracking on lsp-on-change-hook functions -- quick diff for the commit range

I've left a couple of discussions opened as I'd like your input before merging @kiennq

@kassick kassick force-pushed the feat/inline-completions branch 2 times, most recently from 2bee235 to 432062a Compare November 29, 2024 02:19
lsp-inline-completion.el Outdated Show resolved Hide resolved
@kassick kassick force-pushed the feat/inline-completions branch 7 times, most recently from 7d7874b to 5b1843a Compare November 29, 2024 14:31
@kassick kassick force-pushed the feat/inline-completions branch from 5b1843a to a109f34 Compare November 29, 2024 14:41
@kiennq kiennq merged commit 57ea512 into emacs-lsp:master Dec 1, 2024
10 of 13 checks passed
@kiennq
Copy link
Member

kiennq commented Dec 1, 2024

Thanks for your contribution.

@kiennq
Copy link
Member

kiennq commented Dec 1, 2024

@kassick, do you mind provide copilot-lsp as a lsp client as well? Probably with the name of lsp-github-copilot?

@kassick
Copy link
Contributor Author

kassick commented Dec 5, 2024

@kassick, do you mind provide copilot-lsp as a lsp client as well? Probably with the name of lsp-github-copilot?

On it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants