Make set-lookup-handlers! additive
Consecutive calls to set-lookup-handlers! would redefine *all* lookup handlers, unsetting unspecified ones, so you were forced to redefine all handlers, even if you only wanted to change one. No more. Its side effects are now additive. Also adds :async handler support, however, due to their nature, they cannot fall back to other handlers (there's no reliable way to detect they worked or not). To get around this, write a blocking wrapper around the old async method and register it as a non-async handler.
This commit is contained in:
parent
25b9a90c12
commit
37cb0e178c
2 changed files with 66 additions and 40 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
(defvar +lookup--last-provider nil)
|
||||
|
||||
(defvar +lookup--handler-alist nil)
|
||||
|
||||
;;;###autodef
|
||||
(defun set-lookup-handlers! (modes &rest plist)
|
||||
"Define a jump target for major MODES.
|
||||
|
@ -31,22 +33,42 @@ Otherwise, these properties are available to be set:
|
|||
:xref-backend FN
|
||||
Defines an xref backend for a major-mode. If you define :definition and
|
||||
:references along with :xref-backend, those will have higher precedence.
|
||||
:async BOOL
|
||||
Indicates that the supplied handlers *after* this property are asynchronous.
|
||||
Note: async handlers do not fall back to the default handlers, due to their
|
||||
nature. To get around this, you must write specialized wrappers to wait for
|
||||
the async response and return 'fallback.
|
||||
|
||||
\(fn MODE-OR-MODES &key DEFINITION REFERENCES DOCUMENTATION FILE XREF-BACKEND)"
|
||||
\(fn MODE-OR-MODES &key ASYNC DEFINITION REFERENCES DOCUMENTATION FILE XREF-BACKEND)"
|
||||
(declare (indent defun))
|
||||
(dolist (mode (doom-enlist modes))
|
||||
(let ((hook (intern (format "%s-hook" mode)))
|
||||
(fn (intern (format "+lookup|init-%s" mode))))
|
||||
(cond ((null (car plist))
|
||||
(remove-hook hook fn)
|
||||
(setq +lookup--handler-alist
|
||||
(delq (assq mode +lookup--handler-alist)
|
||||
+lookup--handler-alist))
|
||||
(unintern fn nil))
|
||||
((fset fn
|
||||
((let ((old-plist (cdr (assq mode +lookup--handler-alist)))
|
||||
async)
|
||||
(while plist
|
||||
(let ((prop (pop plist))
|
||||
(fns (pop plist)))
|
||||
(if (eq prop :async)
|
||||
(setq async t)
|
||||
(dolist (fn (doom-enlist fns))
|
||||
(put fn '+lookup-async async))
|
||||
(setq old-plist (plist-put old-plist prop fns)))))
|
||||
(setq plist old-plist)
|
||||
(setf (alist-get mode +lookup--handler-alist) plist))
|
||||
(fset fn
|
||||
(lambda ()
|
||||
(when (or (eq major-mode mode)
|
||||
(and (boundp mode)
|
||||
(symbol-value mode)))
|
||||
(cl-destructuring-bind
|
||||
(&key definition references documentation file xref-backend)
|
||||
(&key definition references documentation file xref-backend async)
|
||||
plist
|
||||
(when definition
|
||||
(add-hook '+lookup-definition-functions definition nil t))
|
||||
|
@ -86,14 +108,24 @@ Otherwise, these properties are available to be set:
|
|||
(xref-backend-identifier-at-point (xref-find-backend)))))
|
||||
|
||||
(defun +lookup--jump-to (prop identifier &optional other-window)
|
||||
(cl-loop with origin = (point-marker)
|
||||
for fn
|
||||
;; TODO Refactor me
|
||||
(let ((origin (point-marker)))
|
||||
(cl-loop for fn
|
||||
in (plist-get (list :definition +lookup-definition-functions
|
||||
:references +lookup-references-functions
|
||||
:documentation +lookup-documentation-functions
|
||||
:file +lookup-file-functions)
|
||||
prop)
|
||||
for cmd = (or (command-remapping fn) fn)
|
||||
if (get fn '+lookup-async)
|
||||
return
|
||||
(progn
|
||||
(when other-window
|
||||
;; If async, we can't catch the window change or destination buffer
|
||||
;; reliably, so we set up the new window ahead of time.
|
||||
(switch-to-buffer-other-window (current-buffer))
|
||||
(goto-char (marker-position origin)))
|
||||
(call-interactively fn))
|
||||
if (condition-case e
|
||||
(save-window-excursion
|
||||
(when (or (if (commandp cmd)
|
||||
|
@ -105,10 +137,10 @@ Otherwise, these properties are available to be set:
|
|||
return
|
||||
(progn
|
||||
(funcall (if other-window
|
||||
#'pop-to-buffer
|
||||
#'pop-to-buffer-same-window)
|
||||
#'switch-to-buffer-other-window
|
||||
#'switch-to-buffer)
|
||||
(marker-buffer it))
|
||||
(goto-char it))))
|
||||
(goto-char it)))))
|
||||
|
||||
(defun +lookup--file-search (identifier)
|
||||
(unless identifier
|
||||
|
@ -214,8 +246,7 @@ evil-mode is active."
|
|||
current-prefix-arg))
|
||||
(cond ((null identifier) (user-error "Nothing under point"))
|
||||
|
||||
((and +lookup-definition-functions
|
||||
(+lookup--jump-to :definition identifier other-window)))
|
||||
((+lookup--jump-to :definition identifier other-window))
|
||||
|
||||
((error "Couldn't find the definition of '%s'" identifier))))
|
||||
|
||||
|
@ -231,8 +262,7 @@ search otherwise."
|
|||
current-prefix-arg))
|
||||
(cond ((null identifier) (user-error "Nothing under point"))
|
||||
|
||||
((and +lookup-references-functions
|
||||
(+lookup--jump-to :references identifier other-window)))
|
||||
((+lookup--jump-to :references identifier other-window))
|
||||
|
||||
((error "Couldn't find references of '%s'" identifier))))
|
||||
|
||||
|
@ -240,18 +270,15 @@ search otherwise."
|
|||
(defun +lookup/documentation (identifier &optional other-window)
|
||||
"Show documentation for IDENTIFIER (defaults to symbol at point or selection.
|
||||
|
||||
Goes down a list of possible backends:
|
||||
|
||||
1. The :documentation spec defined with by `set-lookup-handlers!'
|
||||
2. If the +docsets flag is active for :feature lookup, use `+lookup/in-docsets'
|
||||
3. Fall back to an online search, with `+lookup/online'"
|
||||
First attempts the :documentation handler specified with `set-lookup-handlers!'
|
||||
for the current mode/buffer (if any), then falls back to the backends in
|
||||
`+lookup-documentation-functions'."
|
||||
(interactive
|
||||
(list (+lookup--symbol-or-region)
|
||||
current-prefix-arg))
|
||||
(cond ((null identifier) (user-error "Nothing under point"))
|
||||
|
||||
((and +lookup-documentation-functions
|
||||
(+lookup--jump-to :documentation identifier other-window)))
|
||||
((+lookup--jump-to :documentation identifier other-window))
|
||||
|
||||
((user-error "Couldn't find documentation for '%s'" identifier))))
|
||||
|
||||
|
@ -279,8 +306,7 @@ Otherwise, falls back on `find-file-at-point'."
|
|||
((ffap-url-p path)
|
||||
(find-file-at-point path))
|
||||
|
||||
((not (and +lookup-file-functions
|
||||
(+lookup--jump-to :file path)))
|
||||
((not (+lookup--jump-to :file path))
|
||||
(let ((fullpath (expand-file-name path)))
|
||||
(when (and buffer-file-name (file-equal-p fullpath buffer-file-name))
|
||||
(user-error "Already here"))
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
(setq-default company-backends (delq 'company-tide (default-value 'company-backends))))
|
||||
(set-company-backend! 'tide-mode 'company-tide)
|
||||
;; navigation
|
||||
(set-lookup-handlers! 'tide-mode
|
||||
(set-lookup-handlers! 'tide-mode :async t
|
||||
:definition #'tide-jump-to-definition
|
||||
:references #'tide-references
|
||||
:documentation #'tide-documentation-at-point)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue