diff options
| author | Dmitry Gutov | 2015-11-08 05:01:05 +0200 |
|---|---|---|
| committer | Dmitry Gutov | 2015-11-14 01:01:58 +0200 |
| commit | fe973fc270f231f386fc5b26c9fced8925593ecb (patch) | |
| tree | 42951017b9e7a71d075d88e9bd420a8d1daeda25 | |
| parent | 92a501022e0154cd9de41240680b7f003a833c96 (diff) | |
| download | emacs-fe973fc270f231f386fc5b26c9fced8925593ecb.tar.gz emacs-fe973fc270f231f386fc5b26c9fced8925593ecb.zip | |
Replace xref-match-bounds with xref-match-length
Relying on xref-location-marker to point to the beginning of the match
* lisp/progmodes/xref.el (xref-match-bounds): Remove.
(xref-match-length): Add.
(xref-make-match): Change the arguments.
(xref--match-buffer-bounds): Remove.
(xref-match-item): Store length, instead of end-column.
(xref-pulse-momentarily)
(xref--collect-match)
(xref--query-replace-1): Update accordingly.
(xref-query-replace): Ditto. And check that the search results
are up-to-date.
| -rw-r--r-- | lisp/progmodes/xref.el | 99 |
1 files changed, 47 insertions, 52 deletions
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 89a06046ca2..c6af6c25c90 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el | |||
| @@ -38,6 +38,11 @@ | |||
| 38 | ;; class inheriting from `xref-location' and implementing | 38 | ;; class inheriting from `xref-location' and implementing |
| 39 | ;; `xref-location-group' and `xref-location-marker'. | 39 | ;; `xref-location-group' and `xref-location-marker'. |
| 40 | ;; | 40 | ;; |
| 41 | ;; There's a special kind of xrefs we call "match xrefs", which | ||
| 42 | ;; correspond to search results. For these values, | ||
| 43 | ;; `xref-match-length' must be defined, and `xref-location-marker' | ||
| 44 | ;; must return the beginning of the match. | ||
| 45 | ;; | ||
| 41 | ;; Each identifier must be represented as a string. Implementers can | 46 | ;; Each identifier must be represented as a string. Implementers can |
| 42 | ;; use string properties to store additional information about the | 47 | ;; use string properties to store additional information about the |
| 43 | ;; identifier, but they should keep in mind that values returned from | 48 | ;; identifier, but they should keep in mind that values returned from |
| @@ -79,8 +84,8 @@ This is typically the filename.") | |||
| 79 | "Return the line number corresponding to the location." | 84 | "Return the line number corresponding to the location." |
| 80 | nil) | 85 | nil) |
| 81 | 86 | ||
| 82 | (cl-defgeneric xref-match-bounds (_item) | 87 | (cl-defgeneric xref-match-length (_item) |
| 83 | "Return a cons with columns of the beginning and end of the match." | 88 | "Return the length of the match." |
| 84 | nil) | 89 | nil) |
| 85 | 90 | ||
| 86 | ;;;; Commonly needed location classes are defined here: | 91 | ;;;; Commonly needed location classes are defined here: |
| @@ -176,22 +181,16 @@ LOCATION is an `xref-location'." | |||
| 176 | (location :initarg :location | 181 | (location :initarg :location |
| 177 | :type xref-file-location | 182 | :type xref-file-location |
| 178 | :reader xref-item-location) | 183 | :reader xref-item-location) |
| 179 | (end-column :initarg :end-column)) | 184 | (length :initarg :length :reader xref-match-length)) |
| 180 | :comment "An xref item describes a reference to a location | 185 | :comment "A match xref item describes a search result.") |
| 181 | somewhere.") | ||
| 182 | |||
| 183 | (cl-defmethod xref-match-bounds ((i xref-match-item)) | ||
| 184 | (with-slots (end-column location) i | ||
| 185 | (cons (xref-file-location-column location) | ||
| 186 | end-column))) | ||
| 187 | 186 | ||
| 188 | (defun xref-make-match (summary end-column location) | 187 | (defun xref-make-match (summary location length) |
| 189 | "Create and return a new `xref-match-item'. | 188 | "Create and return a new `xref-match-item'. |
| 190 | SUMMARY is a short string to describe the xref. | 189 | SUMMARY is a short string to describe the xref. |
| 191 | END-COLUMN is the match end column number inside SUMMARY. | 190 | LOCATION is an `xref-location'. |
| 192 | LOCATION is an `xref-location'." | 191 | LENGTH is the match length, in characters." |
| 193 | (make-instance 'xref-match-item :summary summary :location location | 192 | (make-instance 'xref-match-item :summary summary |
| 194 | :end-column end-column)) | 193 | :location location :length length)) |
| 195 | 194 | ||
| 196 | 195 | ||
| 197 | ;;; API | 196 | ;;; API |
| @@ -345,22 +344,14 @@ elements is negated." | |||
| 345 | (pcase-let ((`(,beg . ,end) | 344 | (pcase-let ((`(,beg . ,end) |
| 346 | (save-excursion | 345 | (save-excursion |
| 347 | (or | 346 | (or |
| 348 | (xref--match-buffer-bounds xref--current-item) | 347 | (let ((length (xref-match-length xref--current-item))) |
| 348 | (and length (cons (point) (+ (point) length)))) | ||
| 349 | (back-to-indentation) | 349 | (back-to-indentation) |
| 350 | (if (eolp) | 350 | (if (eolp) |
| 351 | (cons (line-beginning-position) (1+ (point))) | 351 | (cons (line-beginning-position) (1+ (point))) |
| 352 | (cons (point) (line-end-position))))))) | 352 | (cons (point) (line-end-position))))))) |
| 353 | (pulse-momentary-highlight-region beg end 'next-error))) | 353 | (pulse-momentary-highlight-region beg end 'next-error))) |
| 354 | 354 | ||
| 355 | (defun xref--match-buffer-bounds (item) | ||
| 356 | (save-excursion | ||
| 357 | (let ((bounds (xref-match-bounds item))) | ||
| 358 | (when bounds | ||
| 359 | (cons (progn (move-to-column (car bounds)) | ||
| 360 | (point)) | ||
| 361 | (progn (move-to-column (cdr bounds)) | ||
| 362 | (point))))))) | ||
| 363 | |||
| 364 | ;; etags.el needs this | 355 | ;; etags.el needs this |
| 365 | (defun xref-clear-marker-stack () | 356 | (defun xref-clear-marker-stack () |
| 366 | "Discard all markers from the marker stack." | 357 | "Discard all markers from the marker stack." |
| @@ -487,50 +478,54 @@ WINDOW controls how the buffer is displayed: | |||
| 487 | (progn | 478 | (progn |
| 488 | (save-excursion | 479 | (save-excursion |
| 489 | (goto-char (point-min)) | 480 | (goto-char (point-min)) |
| 490 | ;; TODO: Check that none of the matches are out of date; | ||
| 491 | ;; offer to re-scan otherwise. Note that saving the last | ||
| 492 | ;; modification tick won't work, as long as not all of the | ||
| 493 | ;; buffers are kept open. | ||
| 494 | (while (setq item (xref--search-property 'xref-item)) | 481 | (while (setq item (xref--search-property 'xref-item)) |
| 495 | (when (xref-match-bounds item) | 482 | (when (xref-match-length item) |
| 496 | (save-excursion | 483 | (save-excursion |
| 497 | ;; FIXME: Get rid of xref--goto-location, by making | 484 | (let* ((loc (xref-item-location item)) |
| 498 | ;; xref-match-bounds return markers already. | 485 | (beg (xref-location-marker loc)) |
| 499 | (xref--goto-location (xref-item-location item)) | 486 | (len (xref-match-length item))) |
| 500 | (let ((bounds (xref--match-buffer-bounds item)) | 487 | ;; Perform sanity check first. |
| 501 | (beg (make-marker)) | 488 | (xref--goto-location loc) |
| 502 | (end (make-marker))) | 489 | ;; FIXME: The check should probably be a generic |
| 503 | (move-marker beg (car bounds)) | 490 | ;; function, instead of the assumption that all |
| 504 | (move-marker end (cdr bounds)) | 491 | ;; matches contain the full line as summary. |
| 505 | (push (cons beg end) pairs))))) | 492 | ;; TODO: Offer to re-scan otherwise. |
| 493 | (unless (equal (buffer-substring-no-properties | ||
| 494 | (line-beginning-position) | ||
| 495 | (line-end-position)) | ||
| 496 | (xref-item-summary item)) | ||
| 497 | (user-error "Search results out of date")) | ||
| 498 | (push (cons beg len) pairs))))) | ||
| 506 | (setq pairs (nreverse pairs))) | 499 | (setq pairs (nreverse pairs))) |
| 507 | (unless pairs (user-error "No suitable matches here")) | 500 | (unless pairs (user-error "No suitable matches here")) |
| 508 | (xref--query-replace-1 from to pairs)) | 501 | (xref--query-replace-1 from to pairs)) |
| 509 | (dolist (pair pairs) | 502 | (dolist (pair pairs) |
| 510 | (move-marker (car pair) nil) | 503 | (move-marker (car pair) nil))))) |
| 511 | (move-marker (cdr pair) nil))))) | ||
| 512 | 504 | ||
| 505 | ;; FIXME: Write a nicer UI. | ||
| 513 | (defun xref--query-replace-1 (from to pairs) | 506 | (defun xref--query-replace-1 (from to pairs) |
| 514 | (let* ((query-replace-lazy-highlight nil) | 507 | (let* ((query-replace-lazy-highlight nil) |
| 515 | current-pair current-buf | 508 | current-beg current-len current-buf |
| 516 | ;; Counteract the "do the next match now" hack in | 509 | ;; Counteract the "do the next match now" hack in |
| 517 | ;; `perform-replace'. And still, it'll report that those | 510 | ;; `perform-replace'. And still, it'll report that those |
| 518 | ;; matches were "filtered out" at the end. | 511 | ;; matches were "filtered out" at the end. |
| 519 | (isearch-filter-predicate | 512 | (isearch-filter-predicate |
| 520 | (lambda (beg end) | 513 | (lambda (beg end) |
| 521 | (and current-pair | 514 | (and current-beg |
| 522 | (eq (current-buffer) current-buf) | 515 | (eq (current-buffer) current-buf) |
| 523 | (>= beg (car current-pair)) | 516 | (>= beg current-beg) |
| 524 | (<= end (cdr current-pair))))) | 517 | (<= end (+ current-beg current-len))))) |
| 525 | (replace-re-search-function | 518 | (replace-re-search-function |
| 526 | (lambda (from &optional _bound noerror) | 519 | (lambda (from &optional _bound noerror) |
| 527 | (let (found) | 520 | (let (found pair) |
| 528 | (while (and (not found) pairs) | 521 | (while (and (not found) pairs) |
| 529 | (setq current-pair (pop pairs) | 522 | (setq pair (pop pairs) |
| 530 | current-buf (marker-buffer (car current-pair))) | 523 | current-beg (car pair) |
| 524 | current-len (cdr pair) | ||
| 525 | current-buf (marker-buffer current-beg)) | ||
| 531 | (pop-to-buffer current-buf) | 526 | (pop-to-buffer current-buf) |
| 532 | (goto-char (car current-pair)) | 527 | (goto-char current-beg) |
| 533 | (when (re-search-forward from (cdr current-pair) noerror) | 528 | (when (re-search-forward from (+ current-beg current-len) noerror) |
| 534 | (setq found t))) | 529 | (setq found t))) |
| 535 | found)))) | 530 | found)))) |
| 536 | ;; FIXME: Despite this being a multi-buffer replacement, `N' | 531 | ;; FIXME: Despite this being a multi-buffer replacement, `N' |
| @@ -936,8 +931,8 @@ IGNORES is a list of glob patterns." | |||
| 936 | (xref-make-match (buffer-substring | 931 | (xref-make-match (buffer-substring |
| 937 | (line-beginning-position) | 932 | (line-beginning-position) |
| 938 | (line-end-position)) | 933 | (line-end-position)) |
| 939 | (current-column) | 934 | loc |
| 940 | loc))))))) | 935 | (- (match-end 0) (match-beginning 0))))))))) |
| 941 | 936 | ||
| 942 | (provide 'xref) | 937 | (provide 'xref) |
| 943 | 938 | ||