aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2015-07-20 04:32:58 +0300
committerDmitry Gutov2015-07-20 04:32:58 +0300
commit5330a45ebff0214cc5c5d123e7cc68f00f68ff39 (patch)
tree5a22c9baffc0fabf48c3c73fce8b377a1d9df844
parent10ac9dbdcf2973bd70ea63aa79a9f3ad7dd9ff5a (diff)
downloademacs-5330a45ebff0214cc5c5d123e7cc68f00f68ff39.tar.gz
emacs-5330a45ebff0214cc5c5d123e7cc68f00f68ff39.zip
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.
-rw-r--r--lisp/progmodes/xref.el107
1 files changed, 73 insertions, 34 deletions
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index a17550f445f..0847fdaf1b9 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -78,6 +78,10 @@ This is typically the filename.")
78 "Return the line number corresponding to the location." 78 "Return the line number corresponding to the location."
79 nil) 79 nil)
80 80
81(cl-defgeneric xref-match-bounds (_item)
82 "Return a cons with columns of the beginning and end of the match."
83 nil)
84
81;;;; Commonly needed location classes are defined here: 85;;;; Commonly needed location classes are defined here:
82 86
83;; FIXME: might be useful to have an optional "hint" i.e. a string to 87;; FIXME: might be useful to have an optional "hint" i.e. a string to
@@ -85,7 +89,7 @@ This is typically the filename.")
85(defclass xref-file-location (xref-location) 89(defclass xref-file-location (xref-location)
86 ((file :type string :initarg :file) 90 ((file :type string :initarg :file)
87 (line :type fixnum :initarg :line :reader xref-location-line) 91 (line :type fixnum :initarg :line :reader xref-location-line)
88 (column :type fixnum :initarg :column)) 92 (column :type fixnum :initarg :column :reader xref-file-location-column))
89 :documentation "A file location is a file/line/column triple. 93 :documentation "A file location is a file/line/column triple.
90Line numbers start from 1 and columns from 0.") 94Line numbers start from 1 and columns from 0.")
91 95
@@ -165,6 +169,29 @@ SUMMARY is a short string to describe the xref.
165LOCATION is an `xref-location'." 169LOCATION is an `xref-location'."
166 (make-instance 'xref-item :summary summary :location location)) 170 (make-instance 'xref-item :summary summary :location location))
167 171
172(defclass xref-match-item ()
173 ((summary :type string :initarg :summary
174 :reader xref-item-summary)
175 (location :initarg :location
176 :type xref-file-location
177 :reader xref-item-location)
178 (end-column :initarg :end-column))
179 :comment "An xref item describes a reference to a location
180somewhere.")
181
182(cl-defmethod xref-match-bounds ((i xref-match-item))
183 (with-slots (end-column location) i
184 (cons (xref-file-location-column location)
185 end-column)))
186
187(defun xref-make-match (summary end-column location)
188 "Create and return a new xref match item.
189SUMMARY is a short string to describe the xref.
190END-COLUMN is the match end column number inside SUMMARY.
191LOCATION is an `xref-location'."
192 (make-instance 'xref-match-item :summary summary :location location
193 :end-column end-column))
194
168 195
169;;; API 196;;; API
170 197
@@ -309,15 +336,22 @@ elements is negated."
309 (set-marker marker nil nil) 336 (set-marker marker nil nil)
310 (run-hooks 'xref-after-return-hook)))) 337 (run-hooks 'xref-after-return-hook))))
311 338
339(defvar xref--current-item nil)
340
312(defun xref-pulse-momentarily () 341(defun xref-pulse-momentarily ()
313 (let (beg end) 342 (pcase-let ((`(,beg . ,end)
314 (save-excursion 343 (save-excursion
315 (back-to-indentation) 344 (or
316 (if (eolp) 345 (let ((bounds (xref-match-bounds xref--current-item)))
317 (setq beg (line-beginning-position) 346 (when bounds
318 end (1+ (point))) 347 (cons (progn (move-to-column (car bounds))
319 (setq beg (point) 348 (point))
320 end (line-end-position)))) 349 (progn (move-to-column (cdr bounds))
350 (point)))))
351 (back-to-indentation)
352 (if (eolp)
353 (cons (line-beginning-position) (1+ (point)))
354 (cons (point) (line-end-position)))))))
321 (pulse-momentary-highlight-region beg end 'next-error))) 355 (pulse-momentary-highlight-region beg end 'next-error)))
322 356
323;; etags.el needs this 357;; etags.el needs this
@@ -343,18 +377,19 @@ elements is negated."
343 (t (error "Location is outside accessible part of buffer"))) 377 (t (error "Location is outside accessible part of buffer")))
344 (goto-char marker))) 378 (goto-char marker)))
345 379
346(defun xref--pop-to-location (location &optional window) 380(defun xref--pop-to-location (item &optional window)
347 "Goto xref-location LOCATION and display the buffer. 381 "Go to the location of ITEM and display the buffer.
348WINDOW controls how the buffer is displayed: 382WINDOW controls how the buffer is displayed:
349 nil -- switch-to-buffer 383 nil -- switch-to-buffer
350 'window -- pop-to-buffer (other window) 384 'window -- pop-to-buffer (other window)
351 'frame -- pop-to-buffer (other frame)" 385 'frame -- pop-to-buffer (other frame)"
352 (xref--goto-location location) 386 (xref--goto-location (xref-item-location item))
353 (cl-ecase window 387 (cl-ecase window
354 ((nil) (switch-to-buffer (current-buffer))) 388 ((nil) (switch-to-buffer (current-buffer)))
355 (window (pop-to-buffer (current-buffer) t)) 389 (window (pop-to-buffer (current-buffer) t))
356 (frame (let ((pop-up-frames t)) (pop-to-buffer (current-buffer) t)))) 390 (frame (let ((pop-up-frames t)) (pop-to-buffer (current-buffer) t))))
357 (run-hooks 'xref-after-jump-hook)) 391 (let ((xref--current-item item))
392 (run-hooks 'xref-after-jump-hook)))
358 393
359 394
360;;; XREF buffer (part of the UI) 395;;; XREF buffer (part of the UI)
@@ -414,26 +449,27 @@ Used for temporary buffers.")
414(defun xref-show-location-at-point () 449(defun xref-show-location-at-point ()
415 "Display the source of xref at point in the other window, if any." 450 "Display the source of xref at point in the other window, if any."
416 (interactive) 451 (interactive)
417 (let ((loc (xref--location-at-point))) 452 (let* ((xref (xref--item-at-point))
418 (when loc 453 (xref--current-item xref))
419 (xref--show-location loc)))) 454 (when xref
455 (xref--show-location (xref-item-location xref)))))
420 456
421(defun xref-next-line () 457(defun xref-next-line ()
422 "Move to the next xref and display its source in the other window." 458 "Move to the next xref and display its source in the other window."
423 (interactive) 459 (interactive)
424 (xref--search-property 'xref-location) 460 (xref--search-property 'xref-item)
425 (xref-show-location-at-point)) 461 (xref-show-location-at-point))
426 462
427(defun xref-prev-line () 463(defun xref-prev-line ()
428 "Move to the previous xref and display its source in the other window." 464 "Move to the previous xref and display its source in the other window."
429 (interactive) 465 (interactive)
430 (xref--search-property 'xref-location t) 466 (xref--search-property 'xref-item t)
431 (xref-show-location-at-point)) 467 (xref-show-location-at-point))
432 468
433(defun xref--location-at-point () 469(defun xref--item-at-point ()
434 (save-excursion 470 (save-excursion
435 (back-to-indentation) 471 (back-to-indentation)
436 (get-text-property (point) 'xref-location))) 472 (get-text-property (point) 'xref-item)))
437 473
438(defvar-local xref--window nil 474(defvar-local xref--window nil
439 "ACTION argument to call `display-buffer' with.") 475 "ACTION argument to call `display-buffer' with.")
@@ -441,11 +477,11 @@ Used for temporary buffers.")
441(defun xref-goto-xref () 477(defun xref-goto-xref ()
442 "Jump to the xref on the current line and bury the xref buffer." 478 "Jump to the xref on the current line and bury the xref buffer."
443 (interactive) 479 (interactive)
444 (let ((loc (or (xref--location-at-point) 480 (let ((xref (or (xref--item-at-point)
445 (user-error "No reference at point"))) 481 (user-error "No reference at point")))
446 (window xref--window)) 482 (window xref--window))
447 (xref-quit) 483 (xref-quit)
448 (xref--pop-to-location loc window))) 484 (xref--pop-to-location xref window)))
449 485
450(defvar xref--xref-buffer-mode-map 486(defvar xref--xref-buffer-mode-map
451 (let ((map (make-sparse-keymap))) 487 (let ((map (make-sparse-keymap)))
@@ -470,11 +506,11 @@ Used for temporary buffers.")
470 (goto-char (point-min))) 506 (goto-char (point-min)))
471 (let ((backward (< n 0)) 507 (let ((backward (< n 0))
472 (n (abs n)) 508 (n (abs n))
473 (loc nil)) 509 (xref nil))
474 (dotimes (_ n) 510 (dotimes (_ n)
475 (setq loc (xref--search-property 'xref-location backward))) 511 (setq (xref--search-property 'xref-item backward)))
476 (cond (loc 512 (cond (xref
477 (xref--pop-to-location loc)) 513 (xref--pop-to-location xref))
478 (t 514 (t
479 (error "No %s xref" (if backward "previous" "next")))))) 515 (error "No %s xref" (if backward "previous" "next"))))))
480 516
@@ -518,7 +554,7 @@ meantime are preserved."
518 (interactive "e") 554 (interactive "e")
519 (mouse-set-point event) 555 (mouse-set-point event)
520 (forward-line 0) 556 (forward-line 0)
521 (xref--search-property 'xref-location) 557 (xref--search-property 'xref-item)
522 (xref-show-location-at-point)) 558 (xref-show-location-at-point))
523 559
524(defun xref--insert-xrefs (xref-alist) 560(defun xref--insert-xrefs (xref-alist)
@@ -546,7 +582,7 @@ GROUP is a string for decoration purposes and XREF is an
546 'face 'compilation-line-number) 582 'face 'compilation-line-number)
547 " "))) 583 " ")))
548 (xref--insert-propertized 584 (xref--insert-propertized
549 (list 'xref-location location 585 (list 'xref-item xref
550 ;; 'face 'font-lock-keyword-face 586 ;; 'face 'font-lock-keyword-face
551 'mouse-face 'highlight 587 'mouse-face 'highlight
552 'keymap xref--button-map 588 'keymap xref--button-map
@@ -603,7 +639,7 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
603 (user-error "No %s found for: %s" (symbol-name kind) input)) 639 (user-error "No %s found for: %s" (symbol-name kind) input))
604 ((not (cdr xrefs)) 640 ((not (cdr xrefs))
605 (xref-push-marker-stack) 641 (xref-push-marker-stack)
606 (xref--pop-to-location (xref-item-location (car xrefs)) window)) 642 (xref--pop-to-location (car xrefs) window))
607 (t 643 (t
608 (xref-push-marker-stack) 644 (xref-push-marker-stack)
609 (funcall xref-show-xrefs-function xrefs 645 (funcall xref-show-xrefs-function xrefs
@@ -866,11 +902,14 @@ IGNORES is a list of glob patterns."
866 (syntax-propertize (line-end-position)) 902 (syntax-propertize (line-end-position))
867 (when (re-search-forward regexp (line-end-position) t) 903 (when (re-search-forward regexp (line-end-position) t)
868 (goto-char (match-beginning 0)) 904 (goto-char (match-beginning 0))
869 (xref-make (buffer-substring 905 (let ((loc (xref-make-file-location file line
870 (line-beginning-position) 906 (current-column))))
871 (line-end-position)) 907 (goto-char (match-end 0))
872 (xref-make-file-location file line 908 (xref-make-match (buffer-substring
873 (current-column)))))))) 909 (line-beginning-position)
910 (line-end-position))
911 (current-column)
912 loc)))))))
874 913
875(provide 'xref) 914(provide 'xref)
876 915