aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Gutov2015-11-08 05:01:05 +0200
committerDmitry Gutov2015-11-14 01:01:58 +0200
commitfe973fc270f231f386fc5b26c9fced8925593ecb (patch)
tree42951017b9e7a71d075d88e9bd420a8d1daeda25
parent92a501022e0154cd9de41240680b7f003a833c96 (diff)
downloademacs-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.el99
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.")
181somewhere.")
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'.
190SUMMARY is a short string to describe the xref. 189SUMMARY is a short string to describe the xref.
191END-COLUMN is the match end column number inside SUMMARY. 190LOCATION is an `xref-location'.
192LOCATION is an `xref-location'." 191LENGTH 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