Commit 5330a45e authored by Dmitry Gutov's avatar Dmitry Gutov

Add xref-match-item, and use it

* lisp/progmodes/xref.el (xref-match-bounds): New generic function.
(xref-file-location): Add reader for the column slot.
(xref-match-item): New class.
(xref-match-bounds): A method implementation for it.
(xref-make-match): New constructor function.
(xref--current-item): New private variable.
(xref-pulse-momentarily): Use it.
(xref--pop-to-location): Change the first argument to an xref
item, instead of location, bind xref--current-item.
Update all callers.
(xref-next-line, xref-prev-line, xref--next-error-function)
(xref--mouse-2): Look for the property `xref-item',
instead of `xref-location'.
(xref--item-at-point): Likewise.  This function replaces
`xref-location-at-point'.  Update all callers.
(xref--insert-xrefs): Add the `xref-item' text property, instead
of `xref-location'.
(xref--collect-match): Use xref-make-match.
parent 10ac9dbd
......@@ -78,6 +78,10 @@ This is typically the filename.")
"Return the line number corresponding to the location."
(cl-defgeneric xref-match-bounds (_item)
"Return a cons with columns of the beginning and end of the match."
;;;; Commonly needed location classes are defined here:
;; FIXME: might be useful to have an optional "hint" i.e. a string to
......@@ -85,7 +89,7 @@ This is typically the filename.")
(defclass xref-file-location (xref-location)
((file :type string :initarg :file)
(line :type fixnum :initarg :line :reader xref-location-line)
(column :type fixnum :initarg :column))
(column :type fixnum :initarg :column :reader xref-file-location-column))
:documentation "A file location is a file/line/column triple.
Line numbers start from 1 and columns from 0.")
......@@ -165,6 +169,29 @@ SUMMARY is a short string to describe the xref.
LOCATION is an `xref-location'."
(make-instance 'xref-item :summary summary :location location))
(defclass xref-match-item ()
((summary :type string :initarg :summary
:reader xref-item-summary)
(location :initarg :location
:type xref-file-location
:reader xref-item-location)
(end-column :initarg :end-column))
:comment "An xref item describes a reference to a location
(cl-defmethod xref-match-bounds ((i xref-match-item))
(with-slots (end-column location) i
(cons (xref-file-location-column location)
(defun xref-make-match (summary end-column location)
"Create and return a new xref match item.
SUMMARY is a short string to describe the xref.
END-COLUMN is the match end column number inside SUMMARY.
LOCATION is an `xref-location'."
(make-instance 'xref-match-item :summary summary :location location
:end-column end-column))
;;; API
......@@ -309,15 +336,22 @@ elements is negated."
(set-marker marker nil nil)
(run-hooks 'xref-after-return-hook))))
(defvar xref--current-item nil)
(defun xref-pulse-momentarily ()
(let (beg end)
(if (eolp)
(setq beg (line-beginning-position)
end (1+ (point)))
(setq beg (point)
end (line-end-position))))
(pcase-let ((`(,beg . ,end)
(let ((bounds (xref-match-bounds xref--current-item)))
(when bounds
(cons (progn (move-to-column (car bounds))
(progn (move-to-column (cdr bounds))
(if (eolp)
(cons (line-beginning-position) (1+ (point)))
(cons (point) (line-end-position)))))))
(pulse-momentary-highlight-region beg end 'next-error)))
;; etags.el needs this
......@@ -343,18 +377,19 @@ elements is negated."
(t (error "Location is outside accessible part of buffer")))
(goto-char marker)))
(defun xref--pop-to-location (location &optional window)
"Goto xref-location LOCATION and display the buffer.
(defun xref--pop-to-location (item &optional window)
"Go to the location of ITEM and display the buffer.
WINDOW controls how the buffer is displayed:
nil -- switch-to-buffer
'window -- pop-to-buffer (other window)
'frame -- pop-to-buffer (other frame)"
(xref--goto-location location)
(xref--goto-location (xref-item-location item))
(cl-ecase window
((nil) (switch-to-buffer (current-buffer)))
(window (pop-to-buffer (current-buffer) t))
(frame (let ((pop-up-frames t)) (pop-to-buffer (current-buffer) t))))
(run-hooks 'xref-after-jump-hook))
(let ((xref--current-item item))
(run-hooks 'xref-after-jump-hook)))
;;; XREF buffer (part of the UI)
......@@ -414,26 +449,27 @@ Used for temporary buffers.")
(defun xref-show-location-at-point ()
"Display the source of xref at point in the other window, if any."
(let ((loc (xref--location-at-point)))
(when loc
(xref--show-location loc))))
(let* ((xref (xref--item-at-point))
(xref--current-item xref))
(when xref
(xref--show-location (xref-item-location xref)))))
(defun xref-next-line ()
"Move to the next xref and display its source in the other window."
(xref--search-property 'xref-location)
(xref--search-property 'xref-item)
(defun xref-prev-line ()
"Move to the previous xref and display its source in the other window."
(xref--search-property 'xref-location t)
(xref--search-property 'xref-item t)
(defun xref--location-at-point ()
(defun xref--item-at-point ()
(get-text-property (point) 'xref-location)))
(get-text-property (point) 'xref-item)))
(defvar-local xref--window nil
"ACTION argument to call `display-buffer' with.")
......@@ -441,11 +477,11 @@ Used for temporary buffers.")
(defun xref-goto-xref ()
"Jump to the xref on the current line and bury the xref buffer."
(let ((loc (or (xref--location-at-point)
(let ((xref (or (xref--item-at-point)
(user-error "No reference at point")))
(window xref--window))
(xref--pop-to-location loc window)))
(xref--pop-to-location xref window)))
(defvar xref--xref-buffer-mode-map
(let ((map (make-sparse-keymap)))
......@@ -470,11 +506,11 @@ Used for temporary buffers.")
(goto-char (point-min)))
(let ((backward (< n 0))
(n (abs n))
(loc nil))
(xref nil))
(dotimes (_ n)
(setq loc (xref--search-property 'xref-location backward)))
(cond (loc
(xref--pop-to-location loc))
(setq (xref--search-property 'xref-item backward)))
(cond (xref
(xref--pop-to-location xref))
(error "No %s xref" (if backward "previous" "next"))))))
......@@ -518,7 +554,7 @@ meantime are preserved."
(interactive "e")
(mouse-set-point event)
(forward-line 0)
(xref--search-property 'xref-location)
(xref--search-property 'xref-item)
(defun xref--insert-xrefs (xref-alist)
......@@ -546,7 +582,7 @@ GROUP is a string for decoration purposes and XREF is an
'face 'compilation-line-number)
" ")))
(list 'xref-location location
(list 'xref-item xref
;; 'face 'font-lock-keyword-face
'mouse-face 'highlight
'keymap xref--button-map
......@@ -603,7 +639,7 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
(user-error "No %s found for: %s" (symbol-name kind) input))
((not (cdr xrefs))
(xref--pop-to-location (xref-item-location (car xrefs)) window))
(xref--pop-to-location (car xrefs) window))
(funcall xref-show-xrefs-function xrefs
......@@ -866,11 +902,14 @@ IGNORES is a list of glob patterns."
(syntax-propertize (line-end-position))
(when (re-search-forward regexp (line-end-position) t)
(goto-char (match-beginning 0))
(xref-make (buffer-substring
(xref-make-file-location file line
(let ((loc (xref-make-file-location file line
(goto-char (match-end 0))
(xref-make-match (buffer-substring
(provide 'xref)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment