forked from Github/emacs
Compare commits
8 commits
master
...
scratch/ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a03bc3e98c | ||
|
|
18e790944e | ||
|
|
9eae95a823 | ||
|
|
1af23aade6 | ||
|
|
aaaa016056 | ||
|
|
9a62da21c2 | ||
|
|
a049c8f9da | ||
|
|
c807121fbd |
3 changed files with 184 additions and 50 deletions
174
lisp/external-completion.el
Normal file
174
lisp/external-completion.el
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
;;; external-completion.el --- Let external tools control completion style -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Version: 0.1
|
||||
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
;; Maintainer: João Távora <joaotavora@gmail.com>
|
||||
;; Keywords:
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Written by Stefan Monnier circa 2016. Variants of this code have
|
||||
;; been working stably in SLY and other packages for a long time.
|
||||
|
||||
;; The `external' completion style is used with a "programmable
|
||||
;; completion" table that gathers completions from an external tool
|
||||
;; such as a shell utility, an inferior process, an http server.
|
||||
|
||||
;; The table and external tool are fully in control of the matching of
|
||||
;; the pattern string to the potential candidates of completion.
|
||||
;; When `external' is in use, the usual styles configured by the user
|
||||
;; or other in `completion-styles' are ignored.
|
||||
;;
|
||||
;; This compromise is for speed: all other styles need the full data
|
||||
;; set to be available in Emacs' addressing space, which is often slow
|
||||
;; if not completely unfeasible.
|
||||
;;
|
||||
;; To make use of the `external' style the function
|
||||
;; `external-completion-table' should be used. See its docstring.
|
||||
|
||||
;;; Code:
|
||||
(require 'cl-lib)
|
||||
|
||||
(add-to-list 'completion-styles-alist
|
||||
'(external
|
||||
external-completion--try-completion
|
||||
external-completion--all-completions
|
||||
"Ad-hoc completion style provided by the completion table."))
|
||||
|
||||
(defun external-completion-table ( category lookup
|
||||
&optional metadata try-completion-function)
|
||||
"Make completion table using the `external' completion style.
|
||||
|
||||
The completion table produced foregoes any styles normally set in
|
||||
`completion-styles' and will set up an entry for the symbol
|
||||
CATEGORY in `completion-category-defaults', linking it to the
|
||||
special completion style `external'.
|
||||
|
||||
This style is useful when the caller interfaces with an external
|
||||
tool that provides completions. This may be a shell utility, an
|
||||
inferior process, an http server, etc. The external tool does
|
||||
the matching, and the full set of candidates doesn't need to be
|
||||
transferred to Emacs's address space. This often results in much
|
||||
faster overall completion at the expense of the choice of
|
||||
completion styles.
|
||||
|
||||
LOOKUP is a function taking a string PATTERN and a position POINT.
|
||||
The function should contact the backend and return a list
|
||||
of strings representing the candidates matching PATTERN given
|
||||
that POINT is the location of point within it. LOOKUP decides if
|
||||
PATTERN is interpreted as a substring, a regular expression, or
|
||||
any other type of matching key. Strings returned by LOOKUP may
|
||||
be propertized with `completions-common-part' to illustrate the
|
||||
specific interpretation. To maintain responsiveness in the face
|
||||
of all but the spiffiest external tools, LOOKUP should detect
|
||||
timeouts and pending user input with `while-no-input' or
|
||||
`sit-for' (which see), cancel the request (if that is possible)
|
||||
and immediately return any non-list.
|
||||
|
||||
Calls to LOOKUP are cached. There is no option to flush the cache,
|
||||
so if you need to do it, create a new completion table by calling
|
||||
`external-completion-table' again.
|
||||
|
||||
|
||||
CATEGORY is a symbol that should identify the kind of things
|
||||
being completed, so users can refer to it in `completion-category-override'.
|
||||
METADATA is an alist of additional properties such as `cycle-sort-function'
|
||||
to associate with CATEGORY. This means that the caller may still
|
||||
retain control the sorting of the candidates while the tool
|
||||
controls the matching.
|
||||
|
||||
TRY-COMPLETION-FUNCTION is a function taking arguments
|
||||
\(PATTERN POINT ALL-COMPLETIONS), where PATTERN
|
||||
and POINT are as described above and ALL-COMPLETIONS are all
|
||||
candidates previously gathered by LOOKUP. It should return
|
||||
a cons cell (NEWPATTERN . NEWPOINT) such that NEWPATTERN is
|
||||
as long as possible within the constraints that LOOKUP still returns
|
||||
the same set of candidates as it does for PATTERN and POINT.
|
||||
This can only be provided if you happen to know what kind of
|
||||
completion style is used by the external tool and is only worthwhile
|
||||
to provide if that completion style is fairly simple:
|
||||
if the tool is using something like \"flex\", it's probably useless."
|
||||
(unless (assq category completion-category-defaults)
|
||||
(push `(,category (styles external))
|
||||
completion-category-defaults))
|
||||
(let ((cache (make-hash-table :test #'equal)))
|
||||
(cl-flet ((lookup-internal (string point)
|
||||
(let* ((key (cons string point))
|
||||
(probe (gethash key cache 'external--notfound)))
|
||||
(if (eq probe 'external--notfound)
|
||||
(puthash key (funcall lookup string point) cache)
|
||||
probe))))
|
||||
(lambda (string pred action)
|
||||
(pcase action
|
||||
(`metadata
|
||||
`(metadata (category . ,category) . ,metadata))
|
||||
(`(external-completion--tryc . ,point)
|
||||
;; FIXME: Obey `pred'? Pass it to `try-completion-function'?
|
||||
`(external-completion--tryc
|
||||
. ,(if try-completion-function
|
||||
(funcall try-completion-function
|
||||
string
|
||||
point
|
||||
(lookup-internal string point))
|
||||
(cons string point))))
|
||||
(`(external-completion--allc . ,point)
|
||||
(let ((all (lookup-internal string point)))
|
||||
`(external-completion--allc
|
||||
. ,(if pred (cl-remove-if-not pred all) all))))
|
||||
(`(boundaries . ,_) nil)
|
||||
('lambda t) ;; `test-completion' should assume all results are valid.
|
||||
(_method
|
||||
;; FIXME: I suspect many external backends can't make much use of
|
||||
;; POINT, in which case the call below may actually be equivalent
|
||||
;; to one that's already in cache but we will fail to reuse it
|
||||
;; just because POINT is different :-(
|
||||
(let ((all (lookup-internal string (length string))))
|
||||
;; This is here for two reasons:
|
||||
;;
|
||||
;; * for when users customize `completion-category-overrides'
|
||||
;; to access this table with a non-`external' completion style.
|
||||
;; It won't work very well for styles more complex than PCM,
|
||||
;; but it should work fine for prefix completion.
|
||||
;;
|
||||
;; * for when `_method' above can also be `nil' or `lambda'
|
||||
;; which has some semantics and use I don't fully
|
||||
;; understand. It doesn't seem to do anything very
|
||||
;; useful in my tests, but since we have caching it
|
||||
;; doesn't seem to hurt much either.
|
||||
(complete-with-action action all string pred))))))))
|
||||
|
||||
;; Note: the "tryc", "allc" suffixes are made akward on purpose, so
|
||||
;; it's easy to pick them apart from the jungle of combinations of
|
||||
;; "try" and "all" and "completion" that inhabit Emacs's completion
|
||||
;; logic.
|
||||
(defun external-completion--call (op string table pred point)
|
||||
(when (functionp table)
|
||||
(let ((res (funcall table string pred (cons op point))))
|
||||
(when (eq op (car-safe res))
|
||||
(cdr res)))))
|
||||
|
||||
(defun external-completion--try-completion (string table pred point)
|
||||
(external-completion--call 'external-completion--tryc
|
||||
string table pred point))
|
||||
|
||||
(defun external-completion--all-completions (string table pred point)
|
||||
(external-completion--call 'external-completion--allc
|
||||
string table pred point))
|
||||
|
||||
(provide 'external-completion)
|
||||
;;; external-completion.el ends here
|
||||
|
|
@ -416,7 +416,6 @@ if that doesn't produce a completion match."
|
|||
icomplete-scroll (not (null icomplete-vertical-mode))
|
||||
completion-styles '(flex)
|
||||
completion-flex-nospace nil
|
||||
completion-category-defaults nil
|
||||
completion-ignore-case t
|
||||
read-buffer-completion-ignore-case t
|
||||
read-file-name-completion-ignore-case t)))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
;; Maintainer: João Távora <joaotavora@gmail.com>
|
||||
;; URL: https://github.com/joaotavora/eglot
|
||||
;; Keywords: convenience, languages
|
||||
;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.14") (flymake "1.2.1") (project "0.3.0") (xref "1.0.1") (eldoc "1.11.0") (seq "2.23"))
|
||||
;; Package-Requires: ((emacs "26.3") (jsonrpc "1.0.14") (flymake "1.2.1") (project "0.3.0") (xref "1.0.1") (eldoc "1.11.0") (seq "2.23") (external-completion "0.1"))
|
||||
|
||||
;; This is a GNU ELPA :core package. Avoid adding functionality
|
||||
;; that is not available in the version of Emacs recorded above or any
|
||||
|
|
@ -110,6 +110,7 @@
|
|||
(require 'filenotify)
|
||||
(require 'ert)
|
||||
(require 'array)
|
||||
(require 'external-completion)
|
||||
|
||||
;; ElDoc is preloaded in Emacs, so `require'-ing won't guarantee we are
|
||||
;; using the latest version from GNU Elpa when we load eglot.el. Use an
|
||||
|
|
@ -2565,7 +2566,7 @@ If BUFFER, switch to it before."
|
|||
(let ((probe (gethash pat cache :missing)))
|
||||
(if (eq probe :missing) (puthash pat (refresh pat) cache)
|
||||
probe)))
|
||||
(lookup (pat)
|
||||
(lookup (pat _point)
|
||||
(let ((res (lookup-1 pat))
|
||||
(def (and (string= pat "") (gethash :default cache))))
|
||||
(append def res nil)))
|
||||
|
|
@ -2573,16 +2574,12 @@ If BUFFER, switch to it before."
|
|||
(cl-getf (get-text-property
|
||||
0 'eglot--lsp-workspaceSymbol c)
|
||||
:score 0)))
|
||||
(lambda (string _pred action)
|
||||
(pcase action
|
||||
(`metadata `(metadata
|
||||
(cycle-sort-function
|
||||
. ,(lambda (completions)
|
||||
(cl-sort completions #'> :key #'score)))
|
||||
(category . eglot-indirection-joy)))
|
||||
(`(eglot--lsp-tryc . ,point) `(eglot--lsp-tryc . (,string . ,point)))
|
||||
(`(eglot--lsp-allc . ,_point) `(eglot--lsp-allc . ,(lookup string)))
|
||||
(_ nil))))))
|
||||
(external-completion-table
|
||||
'eglot-xref
|
||||
#'lookup
|
||||
`((cycle-sort-function
|
||||
. ,(lambda (completions)
|
||||
(cl-sort completions #'> :key #'score))))))))
|
||||
|
||||
(defun eglot--recover-workspace-symbol-meta (string)
|
||||
"Search `eglot--workspace-symbols-cache' for rich entry of STRING."
|
||||
|
|
@ -2595,7 +2592,7 @@ If BUFFER, switch to it before."
|
|||
eglot--workspace-symbols-cache)))
|
||||
|
||||
(add-to-list 'completion-category-overrides
|
||||
'(eglot-indirection-joy (styles . (eglot--lsp-backend-style))))
|
||||
'(eglot-indirection-joy (styles . (backend-completion-backend-style))))
|
||||
|
||||
(cl-defmethod xref-backend-identifier-at-point ((_backend (eql eglot)))
|
||||
(let ((attempt
|
||||
|
|
@ -3431,42 +3428,6 @@ If NOERROR, return predicate, else erroring function."
|
|||
'eglot-managed-mode-hook "1.6")
|
||||
(provide 'eglot)
|
||||
|
||||
|
||||
;;; Backend completion
|
||||
|
||||
;; Written by Stefan Monnier circa 2016. Something to move to
|
||||
;; minibuffer.el "ASAP" (with all the `eglot--lsp-' replaced by
|
||||
;; something else. The very same code already in SLY and stable for a
|
||||
;; long time.
|
||||
|
||||
;; This "completion style" delegates all the work to the "programmable
|
||||
;; completion" table which is then free to implement its own
|
||||
;; completion style. Typically this is used to take advantage of some
|
||||
;; external tool which already has its own completion system and
|
||||
;; doesn't give you efficient access to the prefix completion needed
|
||||
;; by other completion styles. The table should recognize the symbols
|
||||
;; 'eglot--lsp-tryc and 'eglot--lsp-allc as ACTION, reply with
|
||||
;; (eglot--lsp-tryc COMP...) or (eglot--lsp-allc . (STRING . POINT)),
|
||||
;; accordingly. tryc/allc names made akward/recognizable on purpose.
|
||||
|
||||
(add-to-list 'completion-styles-alist
|
||||
'(eglot--lsp-backend-style
|
||||
eglot--lsp-backend-style-try-completion
|
||||
eglot--lsp-backend-style-all-completions
|
||||
"Ad-hoc completion style provided by the completion table."))
|
||||
|
||||
(defun eglot--lsp-backend-style-call (op string table pred point)
|
||||
(when (functionp table)
|
||||
(let ((res (funcall table string pred (cons op point))))
|
||||
(when (eq op (car-safe res))
|
||||
(cdr res)))))
|
||||
|
||||
(defun eglot--lsp-backend-style-try-completion (string table pred point)
|
||||
(eglot--lsp-backend-style-call 'eglot--lsp-tryc string table pred point))
|
||||
|
||||
(defun eglot--lsp-backend-style-all-completions (string table pred point)
|
||||
(eglot--lsp-backend-style-call 'eglot--lsp-allc string table pred point))
|
||||
|
||||
|
||||
;; Local Variables:
|
||||
;; bug-reference-bug-regexp: "\\(github#\\([0-9]+\\)\\)"
|
||||
|
|
|
|||
Loading…
Reference in a new issue