diff --git a/ivy-xref.el b/ivy-xref.el index 8a0dc5a..2531483 100644 --- a/ivy-xref.el +++ b/ivy-xref.el @@ -59,6 +59,7 @@ (let* ((line (xref-location-line location)) (file (xref-location-group location)) (candidate + (counsel--normalize-grep-match (concat (propertize (concat @@ -66,13 +67,13 @@ file (file-name-nondirectory file)) (if (integerp line) - (format ":%d: " line) - ": ")) + (format ":%d:" line) + ":")) 'face 'compilation-info) (progn (when ivy-xref-remove-text-properties (set-text-properties 0 (length summary) nil summary)) - summary)))) + summary))))) (push `(,candidate . ,location) collection)))) (nreverse collection))) @@ -88,7 +89,7 @@ ;; Emacs 27 (or (assoc-default 'fetched-xrefs alist) (funcall fetcher)) - fetcher)) + fetcher)) (buffer (xref--show-xref-buffer fetcher alist))) (quit-window) (let ((orig-buf (current-buffer)) @@ -97,24 +98,28 @@ (ivy-read "xref: " (ivy-xref-make-collection xrefs) :require-match t :action (lambda (candidate) - (setq done (eq 'ivy-done this-command)) - (condition-case err - (let* ((marker (xref-location-marker (cdr candidate))) - (buf (marker-buffer marker))) - (with-current-buffer buffer - (select-window - ;; function signature changed in - ;; 2a973edeacefcabb9fd8024188b7e167f0f9a9b6 - (if (version< emacs-version "26.0.90") - (xref--show-pos-in-buf marker buf t) - (xref--show-pos-in-buf marker buf))))) - (user-error (message (error-message-string err))))) + (let ((candidate (or candidate + (with-current-buffer (ivy--find-occur-buffer) + (get-text-property (line-beginning-position) + 'ivy-xref-candidate))))) + (setq done (eq 'ivy-done this-command)) + (condition-case err + (let* ((marker (xref-location-marker (cdr candidate))) + (buf (marker-buffer marker))) + (with-current-buffer buffer + (select-window + ;; function signature changed in + ;; 2a973edeacefcabb9fd8024188b7e167f0f9a9b6 + (if (version< emacs-version "26.0.90") + (xref--show-pos-in-buf marker buf t) + (xref--show-pos-in-buf marker buf))))) + (user-error (message (error-message-string err)))))) :unwind (lambda () (unless done (switch-to-buffer orig-buf) (goto-char orig-pos))) :caller 'ivy-xref-show-xrefs)) - ;; honor the contact of xref--show-xref-buffer by returning its original + ;; honor the contract of xref--show-xref-buffer by returning its original ;; return value buffer)) @@ -132,5 +137,48 @@ Will jump to the definition if only one is found." (cons (cons 'fetched-xrefs xrefs) alist)))))) +(defun ivy-xref--occur-insert-lines (cands) + "Insert CANDS into `ivy-occur' buffer." + (font-lock-mode -1) + (dolist (cand cands) + (let ((cand-list (assoc cand (ivy-state-collection ivy-last) #'string=))) + (setq cand + (if (string-match "\\`\\(.*:[0-9]+:\\)\\(.*\\)\\'" cand) + (let ((file-and-line (match-string 1 cand)) + (grep-line (match-string 2 cand))) + (concat + (propertize file-and-line 'face 'ivy-grep-info) + (ivy--highlight-fuzzy grep-line))) + (ivy--highlight-fuzzy (copy-sequence cand)))) + (add-text-properties + 0 (length cand) + `(mouse-face + highlight + help-echo "mouse-1: call ivy-action" + ivy-xref-candidate ,cand-list) + cand) + (insert (if (ivy--starts-with-dotslash cand) "" " ") + cand ?\n)))) + +(defun ivy-xref--occur-make-buffer (cands) + (let ((inhibit-read-only t)) + ;; Need precise number of header lines for `wgrep' to work. + (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n" + default-directory)) + (insert (format "%d candidates:\n" (length cands))) + (ivy-xref--occur-insert-lines cands) + (goto-char (point-min)) + (forward-line 4))) + +(defun ivy-xref-show-xrefs-occur (&optional cands) + "Generate a custom occur buffer for `ivy-xref-show-xrefs'" + (unless (eq major-mode 'ivy-occur-grep-mode) + (ivy-occur-grep-mode) + (setq default-directory (ivy-state-directory ivy-last))) + (ivy-xref--occur-make-buffer cands)) + +(ivy-configure 'ivy-xref-show-xrefs + :occur #'ivy-xref-show-xrefs-occur) + (provide 'ivy-xref) ;;; ivy-xref.el ends here