Xref-powered Iedit

Posted on Mar 1, 2026

iedit-mode for Emacs conveniently allows you to concurrently edit multiple occurrences of a given word or search results.

A demonstration of using Iedit to interactively renaming all identifiers of a given name

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:

A demonstration of using aj/iedit-references to interactively renaming a function parameter

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)))