Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazily create markers in helm-xref-candidates and change helm-xref-source accordingly #6

Closed
MaskRay opened this issue Dec 8, 2017 · 2 comments

Comments

@MaskRay
Copy link
Contributor

MaskRay commented Dec 8, 2017

Expected behavior

xref-find-definitions xref-find-references xref-find-apropos do not create new buffers for non-visiting files.

Actual behavior (from emacs-helm.sh if possible, see note at the bottom)

xref-find-definitions xref-find-references xref-find-apropos create new buffers for non-visiting files.

These three functions transitively call xref-location-marker for each candidate, which in turn calls find-file-noselect (may create undesired buffers for non-visiting files).

When using the C++ language server https://github.com/jacobdufault/cquery with lsp-mode or others, if there are say 100 different files corresponding to all the candidates, the 100 files will all be visited, which may be very slow.

Steps to reproduce (recipe)

Call any of xref-find-definitions xref-find-references xref-find-apropos

Backtraces if any (M-x toggle-debug-on-error)

xref-find-references  ;; entry point
xref--find-xrefs
xref--show-xrefs
xref-show-xrefs-function -> helm-xref-show-xrefs ;; delegates to helm-xref
helm-xref-candidates
(cl-defmethod xref-location-marker ((l xref-file-location)) ...)  ;; calls find-file-noselect which opens a new buffer for non-visiting files. 
@MaskRay
Copy link
Contributor Author

MaskRay commented Dec 8, 2017

I currently use the following snippet (only for xref-find-apropos (workspace/symbol), but could be generalized) to work around the issue (undesired opened files of candidates).

;; Adapted from helm-xref-goto-location
(defun my-xref/helm-xref-goto-location (candidate func)
  (-when-let ((_ . xref) (assoc candidate my-helm-xref-alist))
    (with-slots (summary location) xref
      (let ((marker (xref-location-marker location)))
        (helm-xref-goto-location marker func)))))

;; Adapted from helm-xref-source
(defun my-xref/helm-xref-source ()
  (helm-build-sync-source "no-find-file Helm Xref"
    :candidates (lambda () (reverse my-helm-xref-alist))
    :persistent-action (lambda (candidate)
                         (my-xref/helm-xref-goto-location candidate 'display-buffer))
    :action (lambda (candidate)
              (my-xref/helm-xref-goto-location candidate 'switch-to-buffer))
    :candidate-transformer
    (lambda (candidates)
      (mapcar #'car candidates))
    :candidate-number-limit 999))

(defvar my-helm-xref-alist nil)

;; Adapted from helm-xref-show-xrefs
(defun my-xref/helm-show-symbols (xrefs)
  (setq my-helm-xref-alist nil)
  (dolist (xref xrefs)
    (with-slots (summary location) xref
      (let* ((line (xref-location-line location))
             (file (xref-location-group location))
             candidate)
        (setq candidate
              (concat
               (propertize (car (reverse (split-string file "\\/")))
                           'font-lock-face 'helm-xref-file-name)
               (when (string= "integer" (type-of line))
                 (concat
                  ":"
                  (propertize (int-to-string line)
                              'font-lock-face 'helm-xref-line-number)))
               ":"
               summary))
        (push (cons candidate xref) my-helm-xref-alist))))
  (helm :sources (my-xref/helm-xref-source)
        :truncate-lines t
        :buffer "*helm-workspace-symbol*"))

(defun my-xref/find-apropos (pattern)
  (interactive (list (read-string
                      "Search for workspace/symbol: "
                      nil 'xref--read-pattern-history)))
  (let ((symbols (xref-backend-apropos (lsp--xref-backend) pattern)))
    (unless symbols
      (user-error "No symbol found for: %s" pattern))
    (my-xref//with-evil-jumps (evil-set-jump))
    (my-xref/helm-show-symbols symbols)))

@brotzeit
Copy link
Owner

brotzeit commented Dec 8, 2017

Yeah, that's really annoying! I would gladly merge a PR, that solves this issue.
But it seems you forgot some functions. I can't find my-xref//with-evil-jumps.

If you have a working solution just open a PR with the complete code you are using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants