I program in Haskell using lsp-mode
with lsp-haskell
. I need to have a working "jump to definition". xref-find-definitions
using lsp--xref-backend
sometimes fails to find the definition. xref-find-definitions
using etags--xref-backend
usually finds the definition together with other unrelated definitions. I want to have a command that runs lsp--xref-backend
first, and if it doesn't find anything, runs etags--xref-backend
. How do I achieve that? Simply setting xref-backend-functions
to '(lsp--xref-backend etags--xref-backend)
never invokes the etags backend even when the lsp backend doesn't find anything.
-
did you find a solution?– Matías Guzmán NaranjoCommented Dec 20, 2022 at 0:01
-
No, I did not find one– CrabManCommented Dec 20, 2022 at 8:27
Add a comment
|
1 Answer
My solution:
(defun my-hook-local-global-value (hook-sym)
"Return HOOK-SYM's local and global elements as a single list.
If HOOK-SYM is not local, return its value. If it's local, return its
value with t elements with the appropriate global elements."
(cond
((not (local-variable-p hook-sym))
(symbol-value hook-sym))
(:else
(-mapcat
(lambda (elem)
(cond
((equal t elem)
(default-value hook-sym))
(:else
(list elem))))
(buffer-local-value hook-sym (current-buffer))))))
;;;###autoload
(defun my-xref-try-fallback-backends (body-fn)
(-let* ((all-backends
(my-hook-local-global-value 'xref-backend-functions)))
(named-let
recur ((backends all-backends))
(dlet ((xref-backend-functions backends))
(cond
;; don't catch any errors if the last one
((>= 1 (length backends))
(funcall body-fn))
(:else
(condition-case _
(progn
(funcall body-fn))
((user-error) (recur (cdr backends))))))))))
;;;###autoload
(defun my-xref-goto-definition (identifier)
"(`xref-find-definitions' IDENTIFIER) that tries backends one by one."
(interactive (list
(xref--read-identifier
"`my-xref-goto-definition': ")))
(my-xref-try-fallback-backends
(lambda () (xref-find-definitions identifier))))
(keymap-global-set "M-." #'my-xref-goto-definition)
But if possible I want another package that automates this, or the behavior is upstreamed.