diff options
| author | Dmitry Gutov | 2015-07-20 04:32:58 +0300 |
|---|---|---|
| committer | Dmitry Gutov | 2015-07-20 04:32:58 +0300 |
| commit | 5330a45ebff0214cc5c5d123e7cc68f00f68ff39 (patch) | |
| tree | 5a22c9baffc0fabf48c3c73fce8b377a1d9df844 | |
| parent | 10ac9dbdcf2973bd70ea63aa79a9f3ad7dd9ff5a (diff) | |
| download | emacs-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.el | 107 |
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. |
| 90 | Line numbers start from 1 and columns from 0.") | 94 | Line numbers start from 1 and columns from 0.") |
| 91 | 95 | ||
| @@ -165,6 +169,29 @@ SUMMARY is a short string to describe the xref. | |||
| 165 | LOCATION is an `xref-location'." | 169 | LOCATION 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 | ||
| 180 | somewhere.") | ||
| 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. | ||
| 189 | SUMMARY is a short string to describe the xref. | ||
| 190 | END-COLUMN is the match end column number inside SUMMARY. | ||
| 191 | LOCATION 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. |
| 348 | WINDOW controls how the buffer is displayed: | 382 | WINDOW 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 | ||