Xref-powered Iedit
iedit-mode for Emacs
conveniently allows you to concurrently edit multiple occurrences of a
given word or search results.
The above animation also illustrates one of my pet peeves with
Iedit. My typical intent is to rename a given identifier – not all
identifiers whose name happen to coincide. In the example OCaml code
above, both functions foo and bar have a formal parameter named
arg. To selectively rename only the parameter of bar, I’d have to
first narrow to that function and then start iedit-mode.
We can use xref instead to restrict the selection to all references of the identifier under the cursor:
I’ve implemented this in the function aj/iedit-references:
(require 'xref)
(defun aj/iedit-references (identifier)
"Iedit the xref references to the identifier under point."
(interactive (list (xref--read-identifier "IEdit references of: ")))
(let* ((fetcher (xref--create-fetcher identifier 'references identifier))
(xrefs (funcall fetcher))
(xref-alist (xref--analyze xrefs))
(group
(let ((project-root (expand-file-name
(xref--project-root (project-current))))
(bf (buffer-file-name)))
(if (and project-root (string-prefix-p project-root bf))
(substring bf (length project-root))
bf)))
(xrefs-here (assoc group xref-alist))
(points (mapcar
(lambda (xref)
(pcase-let (((cl-struct xref-item summary location) xref))
(let* ((line (xref-location-line location)))
(marker-position (xref-location-marker location))))) xrefs))
(isearch-filter-predicate (lambda (start end) (member start points))))
(iedit-mode)))