mirror of
https://github.com/masscollaborationlabs/emacs.git
synced 2025-07-09 05:30:50 +00:00
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.
This commit is contained in:
parent
92a501022e
commit
fe973fc270
1 changed files with 47 additions and 52 deletions
|
@ -38,6 +38,11 @@
|
||||||
;; class inheriting from `xref-location' and implementing
|
;; class inheriting from `xref-location' and implementing
|
||||||
;; `xref-location-group' and `xref-location-marker'.
|
;; `xref-location-group' and `xref-location-marker'.
|
||||||
;;
|
;;
|
||||||
|
;; There's a special kind of xrefs we call "match xrefs", which
|
||||||
|
;; correspond to search results. For these values,
|
||||||
|
;; `xref-match-length' must be defined, and `xref-location-marker'
|
||||||
|
;; must return the beginning of the match.
|
||||||
|
;;
|
||||||
;; Each identifier must be represented as a string. Implementers can
|
;; Each identifier must be represented as a string. Implementers can
|
||||||
;; use string properties to store additional information about the
|
;; use string properties to store additional information about the
|
||||||
;; identifier, but they should keep in mind that values returned from
|
;; identifier, but they should keep in mind that values returned from
|
||||||
|
@ -79,8 +84,8 @@ This is typically the filename.")
|
||||||
"Return the line number corresponding to the location."
|
"Return the line number corresponding to the location."
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(cl-defgeneric xref-match-bounds (_item)
|
(cl-defgeneric xref-match-length (_item)
|
||||||
"Return a cons with columns of the beginning and end of the match."
|
"Return the length of the match."
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
;;;; Commonly needed location classes are defined here:
|
;;;; Commonly needed location classes are defined here:
|
||||||
|
@ -176,22 +181,16 @@ LOCATION is an `xref-location'."
|
||||||
(location :initarg :location
|
(location :initarg :location
|
||||||
:type xref-file-location
|
:type xref-file-location
|
||||||
:reader xref-item-location)
|
:reader xref-item-location)
|
||||||
(end-column :initarg :end-column))
|
(length :initarg :length :reader xref-match-length))
|
||||||
:comment "An xref item describes a reference to a location
|
:comment "A match xref item describes a search result.")
|
||||||
somewhere.")
|
|
||||||
|
|
||||||
(cl-defmethod xref-match-bounds ((i xref-match-item))
|
(defun xref-make-match (summary location length)
|
||||||
(with-slots (end-column location) i
|
|
||||||
(cons (xref-file-location-column location)
|
|
||||||
end-column)))
|
|
||||||
|
|
||||||
(defun xref-make-match (summary end-column location)
|
|
||||||
"Create and return a new `xref-match-item'.
|
"Create and return a new `xref-match-item'.
|
||||||
SUMMARY is a short string to describe the xref.
|
SUMMARY is a short string to describe the xref.
|
||||||
END-COLUMN is the match end column number inside SUMMARY.
|
LOCATION is an `xref-location'.
|
||||||
LOCATION is an `xref-location'."
|
LENGTH is the match length, in characters."
|
||||||
(make-instance 'xref-match-item :summary summary :location location
|
(make-instance 'xref-match-item :summary summary
|
||||||
:end-column end-column))
|
:location location :length length))
|
||||||
|
|
||||||
|
|
||||||
;;; API
|
;;; API
|
||||||
|
@ -345,22 +344,14 @@ elements is negated."
|
||||||
(pcase-let ((`(,beg . ,end)
|
(pcase-let ((`(,beg . ,end)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(or
|
(or
|
||||||
(xref--match-buffer-bounds xref--current-item)
|
(let ((length (xref-match-length xref--current-item)))
|
||||||
|
(and length (cons (point) (+ (point) length))))
|
||||||
(back-to-indentation)
|
(back-to-indentation)
|
||||||
(if (eolp)
|
(if (eolp)
|
||||||
(cons (line-beginning-position) (1+ (point)))
|
(cons (line-beginning-position) (1+ (point)))
|
||||||
(cons (point) (line-end-position)))))))
|
(cons (point) (line-end-position)))))))
|
||||||
(pulse-momentary-highlight-region beg end 'next-error)))
|
(pulse-momentary-highlight-region beg end 'next-error)))
|
||||||
|
|
||||||
(defun xref--match-buffer-bounds (item)
|
|
||||||
(save-excursion
|
|
||||||
(let ((bounds (xref-match-bounds item)))
|
|
||||||
(when bounds
|
|
||||||
(cons (progn (move-to-column (car bounds))
|
|
||||||
(point))
|
|
||||||
(progn (move-to-column (cdr bounds))
|
|
||||||
(point)))))))
|
|
||||||
|
|
||||||
;; etags.el needs this
|
;; etags.el needs this
|
||||||
(defun xref-clear-marker-stack ()
|
(defun xref-clear-marker-stack ()
|
||||||
"Discard all markers from the marker stack."
|
"Discard all markers from the marker stack."
|
||||||
|
@ -487,50 +478,54 @@ WINDOW controls how the buffer is displayed:
|
||||||
(progn
|
(progn
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
;; TODO: Check that none of the matches are out of date;
|
|
||||||
;; offer to re-scan otherwise. Note that saving the last
|
|
||||||
;; modification tick won't work, as long as not all of the
|
|
||||||
;; buffers are kept open.
|
|
||||||
(while (setq item (xref--search-property 'xref-item))
|
(while (setq item (xref--search-property 'xref-item))
|
||||||
(when (xref-match-bounds item)
|
(when (xref-match-length item)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
;; FIXME: Get rid of xref--goto-location, by making
|
(let* ((loc (xref-item-location item))
|
||||||
;; xref-match-bounds return markers already.
|
(beg (xref-location-marker loc))
|
||||||
(xref--goto-location (xref-item-location item))
|
(len (xref-match-length item)))
|
||||||
(let ((bounds (xref--match-buffer-bounds item))
|
;; Perform sanity check first.
|
||||||
(beg (make-marker))
|
(xref--goto-location loc)
|
||||||
(end (make-marker)))
|
;; FIXME: The check should probably be a generic
|
||||||
(move-marker beg (car bounds))
|
;; function, instead of the assumption that all
|
||||||
(move-marker end (cdr bounds))
|
;; matches contain the full line as summary.
|
||||||
(push (cons beg end) pairs)))))
|
;; TODO: Offer to re-scan otherwise.
|
||||||
|
(unless (equal (buffer-substring-no-properties
|
||||||
|
(line-beginning-position)
|
||||||
|
(line-end-position))
|
||||||
|
(xref-item-summary item))
|
||||||
|
(user-error "Search results out of date"))
|
||||||
|
(push (cons beg len) pairs)))))
|
||||||
(setq pairs (nreverse pairs)))
|
(setq pairs (nreverse pairs)))
|
||||||
(unless pairs (user-error "No suitable matches here"))
|
(unless pairs (user-error "No suitable matches here"))
|
||||||
(xref--query-replace-1 from to pairs))
|
(xref--query-replace-1 from to pairs))
|
||||||
(dolist (pair pairs)
|
(dolist (pair pairs)
|
||||||
(move-marker (car pair) nil)
|
(move-marker (car pair) nil)))))
|
||||||
(move-marker (cdr pair) nil)))))
|
|
||||||
|
|
||||||
|
;; FIXME: Write a nicer UI.
|
||||||
(defun xref--query-replace-1 (from to pairs)
|
(defun xref--query-replace-1 (from to pairs)
|
||||||
(let* ((query-replace-lazy-highlight nil)
|
(let* ((query-replace-lazy-highlight nil)
|
||||||
current-pair current-buf
|
current-beg current-len current-buf
|
||||||
;; Counteract the "do the next match now" hack in
|
;; Counteract the "do the next match now" hack in
|
||||||
;; `perform-replace'. And still, it'll report that those
|
;; `perform-replace'. And still, it'll report that those
|
||||||
;; matches were "filtered out" at the end.
|
;; matches were "filtered out" at the end.
|
||||||
(isearch-filter-predicate
|
(isearch-filter-predicate
|
||||||
(lambda (beg end)
|
(lambda (beg end)
|
||||||
(and current-pair
|
(and current-beg
|
||||||
(eq (current-buffer) current-buf)
|
(eq (current-buffer) current-buf)
|
||||||
(>= beg (car current-pair))
|
(>= beg current-beg)
|
||||||
(<= end (cdr current-pair)))))
|
(<= end (+ current-beg current-len)))))
|
||||||
(replace-re-search-function
|
(replace-re-search-function
|
||||||
(lambda (from &optional _bound noerror)
|
(lambda (from &optional _bound noerror)
|
||||||
(let (found)
|
(let (found pair)
|
||||||
(while (and (not found) pairs)
|
(while (and (not found) pairs)
|
||||||
(setq current-pair (pop pairs)
|
(setq pair (pop pairs)
|
||||||
current-buf (marker-buffer (car current-pair)))
|
current-beg (car pair)
|
||||||
|
current-len (cdr pair)
|
||||||
|
current-buf (marker-buffer current-beg))
|
||||||
(pop-to-buffer current-buf)
|
(pop-to-buffer current-buf)
|
||||||
(goto-char (car current-pair))
|
(goto-char current-beg)
|
||||||
(when (re-search-forward from (cdr current-pair) noerror)
|
(when (re-search-forward from (+ current-beg current-len) noerror)
|
||||||
(setq found t)))
|
(setq found t)))
|
||||||
found))))
|
found))))
|
||||||
;; FIXME: Despite this being a multi-buffer replacement, `N'
|
;; FIXME: Despite this being a multi-buffer replacement, `N'
|
||||||
|
@ -936,8 +931,8 @@ IGNORES is a list of glob patterns."
|
||||||
(xref-make-match (buffer-substring
|
(xref-make-match (buffer-substring
|
||||||
(line-beginning-position)
|
(line-beginning-position)
|
||||||
(line-end-position))
|
(line-end-position))
|
||||||
(current-column)
|
loc
|
||||||
loc)))))))
|
(- (match-end 0) (match-beginning 0)))))))))
|
||||||
|
|
||||||
(provide 'xref)
|
(provide 'xref)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue