dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

consult-xref.el (4874B)


      1 ;;; consult-xref.el --- Xref integration for Consult -*- lexical-binding: t -*-
      2 
      3 ;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
      4 
      5 ;; This file is part of GNU Emacs.
      6 
      7 ;; This program is free software: you can redistribute it and/or modify
      8 ;; it under the terms of the GNU General Public License as published by
      9 ;; the Free Software Foundation, either version 3 of the License, or
     10 ;; (at your option) any later version.
     11 
     12 ;; This program is distributed in the hope that it will be useful,
     13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 ;; GNU General Public License for more details.
     16 
     17 ;; You should have received a copy of the GNU General Public License
     18 ;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
     19 
     20 ;;; Commentary:
     21 
     22 ;; Provides Xref integration for Consult. This is an extra package, to
     23 ;; allow lazy loading of xref.el. The `consult-xref' function is
     24 ;; autoloaded.
     25 
     26 ;;; Code:
     27 
     28 (require 'consult)
     29 (require 'xref)
     30 
     31 (defvar consult-xref--history nil)
     32 (defvar consult-xref--fetcher nil)
     33 
     34 (defun consult-xref--candidates ()
     35   "Return xref candidate list."
     36   (let ((root (consult--project-root)))
     37     (mapcar (lambda (xref)
     38               (let* ((loc (xref-item-location xref))
     39                      (group (if (fboundp 'xref--group-name-for-display)
     40                                 ;; This function is available in xref 1.3.2
     41                                 (xref--group-name-for-display
     42                                  (xref-location-group loc) root)
     43                               (xref-location-group loc)))
     44                      (cand (consult--format-location
     45                             group
     46                             (or (xref-location-line loc) 0)
     47                             (xref-item-summary xref))))
     48                 (add-text-properties
     49                  0 1 `(consult-xref ,xref consult-xref--group ,group) cand)
     50                 cand))
     51             (funcall consult-xref--fetcher))))
     52 
     53 (defun consult-xref--preview (display)
     54   "Xref preview with DISPLAY function."
     55   (let ((open (consult--temporary-files))
     56         (preview (consult--jump-preview)))
     57     (lambda (action cand)
     58       (unless cand
     59         (funcall open))
     60       (let ((consult--buffer-display display))
     61         (funcall preview action
     62                  (when-let (loc (and cand (eq action 'preview)
     63                                      (xref-item-location cand)))
     64                    (let ((type (type-of loc)))
     65                      ;; Only preview file and buffer markers
     66                      (pcase type
     67                        ('xref-buffer-location
     68                         (xref-location-marker loc))
     69                        ((or 'xref-file-location 'xref-etags-location)
     70                         (consult--position-marker
     71                          (funcall open
     72                                   ;; xref-location-group returns the file name
     73                                   (let ((xref-file-name-display 'abs))
     74                                     (xref-location-group loc)))
     75                          (xref-location-line loc)
     76                          (if (eq type 'xref-file-location)
     77                              (xref-file-location-column loc)
     78                            0)))))))))))
     79 
     80 (defun consult-xref--group (cand transform)
     81   "Return title for CAND or TRANSFORM the candidate."
     82   (if transform
     83       (substring cand (1+ (length (get-text-property 0 'consult-xref--group cand))))
     84     (get-text-property 0 'consult-xref--group cand)))
     85 
     86 ;;;###autoload
     87 (defun consult-xref (fetcher &optional alist)
     88   "Show xrefs with preview in the minibuffer.
     89 
     90 This function can be used for `xref-show-xrefs-function'.
     91 See `xref-show-xrefs-function' for the description of the
     92 FETCHER and ALIST arguments."
     93   (let* ((consult-xref--fetcher fetcher)
     94          (candidates (consult-xref--candidates))
     95          (display (alist-get 'display-action alist)))
     96     (xref-pop-to-location
     97      (if (cdr candidates)
     98          (apply
     99           #'consult--read
    100           candidates
    101           (append
    102            (consult--customize-get #'consult-xref)
    103            (list
    104             :prompt "Go to xref: "
    105             :history 'consult-xref--history
    106             :require-match t
    107             :sort nil
    108             :category 'consult-xref
    109             :group #'consult-xref--group
    110             :state
    111             ;; do not preview other frame
    112             (when-let (fun (pcase-exhaustive display
    113                              ('frame nil)
    114                              ('window #'switch-to-buffer-other-window)
    115                              ('nil #'switch-to-buffer)))
    116               (consult-xref--preview fun))
    117             :lookup (apply-partially #'consult--lookup-prop 'consult-xref))))
    118        (get-text-property 0 'consult-xref (car candidates)))
    119      display)))
    120 
    121 (provide 'consult-xref)
    122 ;;; consult-xref.el ends here