diff options
| author | João Távora | 2025-02-11 13:32:07 +0000 |
|---|---|---|
| committer | João Távora | 2025-02-11 15:29:45 +0000 |
| commit | 5f9982ededa3aa2e8890e86836eb56f57cfe4cf1 (patch) | |
| tree | c8dbbea528e4418350b4085c3290d0494f8dc35e | |
| parent | 96dc5deddc2b60210feb10e3a68b74ecd2480b34 (diff) | |
| download | emacs-5f9982ededa3aa2e8890e86836eb56f57cfe4cf1.tar.gz emacs-5f9982ededa3aa2e8890e86836eb56f57cfe4cf1.zip | |
Eglot: cosmetic refactor of eglot-completion-at-point
* lisp/progmodes/eglot.el (eglot-completion-at-point): rework.
| -rw-r--r-- | lisp/progmodes/eglot.el | 168 |
1 files changed, 84 insertions, 84 deletions
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index b7f43c18b68..ce0e388c560 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el | |||
| @@ -3343,81 +3343,79 @@ for which LSP on-type-formatting should be requested." | |||
| 3343 | (add-to-list 'completion-category-defaults '(eglot-capf (styles eglot--dumb-flex))) | 3343 | (add-to-list 'completion-category-defaults '(eglot-capf (styles eglot--dumb-flex))) |
| 3344 | (add-to-list 'completion-styles-alist '(eglot--dumb-flex eglot--dumb-tryc eglot--dumb-allc)) | 3344 | (add-to-list 'completion-styles-alist '(eglot--dumb-flex eglot--dumb-tryc eglot--dumb-allc)) |
| 3345 | 3345 | ||
| 3346 | (defun eglot-completion-at-point () | 3346 | (cl-defun eglot-completion-at-point (&aux completion-capability) |
| 3347 | "Eglot's `completion-at-point' function." | 3347 | "Eglot's `completion-at-point' function." |
| 3348 | ;; Commit logs for this function help understand what's going on. | 3348 | ;; Commit logs for this function help understand what's going on. |
| 3349 | (when-let* ((completion-capability (eglot-server-capable :completionProvider))) | 3349 | (setq completion-capability (eglot-server-capable :completionProvider)) |
| 3350 | (let* ((server (eglot--current-server-or-lose)) | 3350 | (unless completion-capability (cl-return-from eglot-completion-at-point)) |
| 3351 | (bounds (or (bounds-of-thing-at-point 'symbol) | 3351 | (let* ((server (eglot--current-server-or-lose)) |
| 3352 | (cons (point) (point)))) | 3352 | (bounds (or (bounds-of-thing-at-point 'symbol) |
| 3353 | (bounds-string (buffer-substring (car bounds) (cdr bounds))) | 3353 | (cons (point) (point)))) |
| 3354 | (sort-completions | 3354 | (bounds-string (buffer-substring (car bounds) (cdr bounds))) |
| 3355 | (lambda (completions) | 3355 | (local-cache :none) |
| 3356 | (cl-sort completions | 3356 | (orig-pos (point)) |
| 3357 | #'string-lessp | 3357 | (resolved (make-hash-table))) |
| 3358 | :key (lambda (c) | 3358 | (cl-labels |
| 3359 | (plist-get | 3359 | ((sort-completions (completions) |
| 3360 | (get-text-property 0 'eglot--lsp-item c) | 3360 | (cl-sort completions |
| 3361 | :sortText))))) | 3361 | #'string-lessp |
| 3362 | (metadata `(metadata (category . eglot-capf) | 3362 | :key (lambda (c) |
| 3363 | (display-sort-function . ,sort-completions))) | 3363 | (plist-get |
| 3364 | (local-cache :none) | 3364 | (get-text-property 0 'eglot--lsp-item c) |
| 3365 | (orig-pos (point)) | 3365 | :sortText)))) |
| 3366 | (resolved (make-hash-table)) | 3366 | (proxies () |
| 3367 | (proxies | 3367 | (if (listp local-cache) local-cache |
| 3368 | (lambda () | 3368 | (let* ((resp (eglot--request server |
| 3369 | (if (listp local-cache) local-cache | 3369 | :textDocument/completion |
| 3370 | (let* ((resp (eglot--request server | 3370 | (eglot--CompletionParams) |
| 3371 | :textDocument/completion | 3371 | :cancel-on-input t)) |
| 3372 | (eglot--CompletionParams) | 3372 | (items (append |
| 3373 | :cancel-on-input t)) | 3373 | (if (vectorp resp) resp (plist-get resp :items)) |
| 3374 | (items (append | 3374 | nil)) |
| 3375 | (if (vectorp resp) resp (plist-get resp :items)) | 3375 | (cachep (and (listp resp) items |
| 3376 | nil)) | 3376 | eglot-cache-session-completions |
| 3377 | (cachep (and (listp resp) items | 3377 | (eq (plist-get resp :isIncomplete) :json-false))) |
| 3378 | eglot-cache-session-completions | 3378 | (retval |
| 3379 | (eq (plist-get resp :isIncomplete) :json-false))) | 3379 | (mapcar |
| 3380 | (retval | 3380 | (jsonrpc-lambda |
| 3381 | (mapcar | 3381 | (&rest item &key label insertText insertTextFormat |
| 3382 | (jsonrpc-lambda | 3382 | textEdit &allow-other-keys) |
| 3383 | (&rest item &key label insertText insertTextFormat | 3383 | (let ((proxy |
| 3384 | textEdit &allow-other-keys) | 3384 | ;; Snippet or textEdit, it's safe to |
| 3385 | (let ((proxy | 3385 | ;; display/insert the label since |
| 3386 | ;; Snippet or textEdit, it's safe to | 3386 | ;; it'll be adjusted. If no usable |
| 3387 | ;; display/insert the label since | 3387 | ;; insertText at all, label is best, |
| 3388 | ;; it'll be adjusted. If no usable | 3388 | ;; too. |
| 3389 | ;; insertText at all, label is best, | 3389 | (cond ((or (eql insertTextFormat 2) |
| 3390 | ;; too. | 3390 | textEdit |
| 3391 | (cond ((or (eql insertTextFormat 2) | 3391 | (null insertText) |
| 3392 | textEdit | 3392 | (string-empty-p insertText)) |
| 3393 | (null insertText) | 3393 | (string-trim-left label)) |
| 3394 | (string-empty-p insertText)) | 3394 | (t insertText)))) |
| 3395 | (string-trim-left label)) | 3395 | (unless (zerop (length proxy)) |
| 3396 | (t insertText)))) | 3396 | (put-text-property 0 1 'eglot--lsp-item item proxy)) |
| 3397 | (unless (zerop (length proxy)) | 3397 | proxy)) |
| 3398 | (put-text-property 0 1 'eglot--lsp-item item proxy)) | 3398 | items))) |
| 3399 | proxy)) | 3399 | ;; (trace-values "Requested" (length proxies) cachep bounds) |
| 3400 | items))) | 3400 | (setq eglot--capf-session |
| 3401 | ;; (trace-values "Requested" (length proxies) cachep bounds) | 3401 | (if cachep (list bounds retval resolved orig-pos |
| 3402 | (setq eglot--capf-session | 3402 | bounds-string) |
| 3403 | (if cachep (list bounds retval resolved orig-pos | 3403 | :none)) |
| 3404 | bounds-string) :none)) | 3404 | (setq local-cache retval)))) |
| 3405 | (setq local-cache retval))))) | 3405 | (ensure-resolved (lsp-comp &optional dont-cancel-on-input) |
| 3406 | (resolve-maybe | 3406 | ;; Maybe completion/resolve JSON object `lsp-comp' into |
| 3407 | ;; Maybe completion/resolve JSON object `lsp-comp' into | 3407 | ;; another JSON object, if at all possible. Otherwise, |
| 3408 | ;; another JSON object, if at all possible. Otherwise, | 3408 | ;; just return lsp-comp. |
| 3409 | ;; just return lsp-comp. | 3409 | (or (gethash lsp-comp resolved) |
| 3410 | (lambda (lsp-comp &optional dont-cancel-on-input) | 3410 | (setf (gethash lsp-comp resolved) |
| 3411 | (or (gethash lsp-comp resolved) | 3411 | (if (and (eglot-server-capable :completionProvider |
| 3412 | (setf (gethash lsp-comp resolved) | 3412 | :resolveProvider) |
| 3413 | (if (and (eglot-server-capable :completionProvider | 3413 | (plist-get lsp-comp :data)) |
| 3414 | :resolveProvider) | 3414 | (eglot--request server :completionItem/resolve |
| 3415 | (plist-get lsp-comp :data)) | 3415 | lsp-comp :cancel-on-input |
| 3416 | (eglot--request server :completionItem/resolve | 3416 | (not dont-cancel-on-input) |
| 3417 | lsp-comp :cancel-on-input | 3417 | :immediate t) |
| 3418 | (not dont-cancel-on-input) | 3418 | lsp-comp))))) |
| 3419 | :immediate t) | ||
| 3420 | lsp-comp)))))) | ||
| 3421 | (when (and (consp eglot--capf-session) | 3419 | (when (and (consp eglot--capf-session) |
| 3422 | (= (car bounds) (car (nth 0 eglot--capf-session))) | 3420 | (= (car bounds) (car (nth 0 eglot--capf-session))) |
| 3423 | (>= (cdr bounds) (cdr (nth 0 eglot--capf-session)))) | 3421 | (>= (cdr bounds) (cdr (nth 0 eglot--capf-session)))) |
| @@ -3432,14 +3430,16 @@ for which LSP on-type-formatting should be requested." | |||
| 3432 | (cdr bounds) | 3430 | (cdr bounds) |
| 3433 | (lambda (pattern pred action) | 3431 | (lambda (pattern pred action) |
| 3434 | (cond | 3432 | (cond |
| 3435 | ((eq action 'metadata) metadata) ; metadata | 3433 | ((eq action 'metadata) ; metadata |
| 3434 | `(metadata (category . eglot-capf) | ||
| 3435 | (display-sort-function . ,#'sort-completions))) | ||
| 3436 | ((eq action 'lambda) ; test-completion | 3436 | ((eq action 'lambda) ; test-completion |
| 3437 | (test-completion pattern (funcall proxies))) | 3437 | (test-completion pattern (proxies))) |
| 3438 | ((eq (car-safe action) 'boundaries) nil) ; boundaries | 3438 | ((eq (car-safe action) 'boundaries) nil) ; boundaries |
| 3439 | ((null action) ; try-completion | 3439 | ((null action) ; try-completion |
| 3440 | (try-completion pattern (funcall proxies))) | 3440 | (try-completion pattern (proxies))) |
| 3441 | ((eq action t) ; all-completions | 3441 | ((eq action t) ; all-completions |
| 3442 | (let ((comps (funcall proxies))) | 3442 | (let ((comps (proxies))) |
| 3443 | (dolist (c comps) (eglot--dumb-flex pattern c completion-ignore-case)) | 3443 | (dolist (c comps) (eglot--dumb-flex pattern c completion-ignore-case)) |
| 3444 | (all-completions | 3444 | (all-completions |
| 3445 | "" | 3445 | "" |
| @@ -3486,14 +3486,15 @@ for which LSP on-type-formatting should be requested." | |||
| 3486 | ;; FIXME: autoImportText is specific to the pyright language server | 3486 | ;; FIXME: autoImportText is specific to the pyright language server |
| 3487 | (lambda (proxy) | 3487 | (lambda (proxy) |
| 3488 | (when-let* ((lsp-comp (get-text-property 0 'eglot--lsp-item proxy)) | 3488 | (when-let* ((lsp-comp (get-text-property 0 'eglot--lsp-item proxy)) |
| 3489 | (data (plist-get (funcall resolve-maybe lsp-comp) :data)) | 3489 | (data (plist-get (ensure-resolved lsp-comp) :data)) |
| 3490 | (import-text (plist-get data :autoImportText))) | 3490 | (import-text (plist-get data :autoImportText))) |
| 3491 | import-text)) | 3491 | import-text)) |
| 3492 | :company-doc-buffer | 3492 | :company-doc-buffer |
| 3493 | (lambda (proxy) | 3493 | (lambda (proxy) |
| 3494 | (let* ((documentation | 3494 | (let* ((resolved |
| 3495 | (let ((lsp-comp (get-text-property 0 'eglot--lsp-item proxy))) | 3495 | (ensure-resolved (get-text-property 0 'eglot--lsp-item proxy))) |
| 3496 | (plist-get (funcall resolve-maybe lsp-comp) :documentation))) | 3496 | (documentation |
| 3497 | (plist-get resolved :documentation)) | ||
| 3497 | (formatted (and documentation | 3498 | (formatted (and documentation |
| 3498 | (eglot--format-markup documentation)))) | 3499 | (eglot--format-markup documentation)))) |
| 3499 | (when formatted | 3500 | (when formatted |
| @@ -3524,15 +3525,14 @@ for which LSP on-type-formatting should be requested." | |||
| 3524 | (current-buffer)) | 3525 | (current-buffer)) |
| 3525 | (eglot--dbind ((CompletionItem) insertTextFormat | 3526 | (eglot--dbind ((CompletionItem) insertTextFormat |
| 3526 | insertText textEdit additionalTextEdits label) | 3527 | insertText textEdit additionalTextEdits label) |
| 3527 | (funcall | 3528 | (ensure-resolved |
| 3528 | resolve-maybe | ||
| 3529 | (or (get-text-property 0 'eglot--lsp-item proxy) | 3529 | (or (get-text-property 0 'eglot--lsp-item proxy) |
| 3530 | ;; When selecting from the *Completions* | 3530 | ;; When selecting from the *Completions* |
| 3531 | ;; buffer, `proxy' won't have any properties. | 3531 | ;; buffer, `proxy' won't have any properties. |
| 3532 | ;; A lookup should fix that (github#148) | 3532 | ;; A lookup should fix that (github#148) |
| 3533 | (get-text-property | 3533 | (get-text-property |
| 3534 | 0 'eglot--lsp-item | 3534 | 0 'eglot--lsp-item |
| 3535 | (cl-find proxy (funcall proxies) :test #'string=))) | 3535 | (cl-find proxy (proxies) :test #'string=))) |
| 3536 | ;; Be sure to pass non-nil here since we don't want | 3536 | ;; Be sure to pass non-nil here since we don't want |
| 3537 | ;; any quick typing after the soon-to-be-undone | 3537 | ;; any quick typing after the soon-to-be-undone |
| 3538 | ;; insertion to potentially cancel an essential | 3538 | ;; insertion to potentially cancel an essential |