7

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.

2
  • did you find a solution? Commented Dec 20, 2022 at 0:01
  • No, I did not find one
    – CrabMan
    Commented Dec 20, 2022 at 8:27

1 Answer 1

1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.