Skip to main content
10 of 10
Clean-ups following the refactoring
phils
  • 53.1k
  • 3
  • 84
  • 127

I guess you want a two-pass system then, whereby you firstly collect/count identifiers, and secondly discard those which appeared more than once, and then highlight what's left.

Here's one approach...

(defun my-highlight-unique-symbols ()
  "In each block, highlight all symbols which occur exactly once."
  (interactive)
  (font-lock-ensure)
  (save-excursion
    (goto-char (point-min))
    (let ((regexp "\\_<.+?\\_>")
          (case-fold-search nil)
          (blockstart (point))
          (blockdelimiter "\n\n\n"))
      ;; Establish the next block.
      (while (and (not (eobp))
                  (or (search-forward blockdelimiter nil t)
                      (goto-char (point-max))))
        (let ((blockend (point))
              (identifiers (obarray-make)))
          (goto-char blockstart)
          (while (re-search-forward regexp blockend t)
            ;; Have we seen this identifier before?
            (let* ((sym (intern (match-string 0) identifiers))
                   (seen (get sym 'region)))
              (if seen
                  ;; Mark it as a duplicate.
                  (unless (eq seen 'duplicate)
                    (put sym 'region 'duplicate))
                ;; This is the first time we've seen this identifier.
                ;; Store the region boundaries for the match.
                (put sym 'region (cons (match-beginning 0)
                                       (match-end 0))))))
          ;; Highlight the unique instances.
          (with-silent-modifications
            (obarray-map
             (lambda (sym)
               (let ((region (get sym 'region)))
                 (unless (eq region 'duplicate)
                   (put-text-property (car region) (cdr region)
                                      'face 'highlight))))
             identifiers))
          ;; Prepare for the next block.
          (setq blockstart blockend)
          (goto-char blockstart))))))

Which you can run with M-x my-highlight-unique-symbols

This version is not a permanent effect -- you can run it to highlight things, but subsequent edits to the buffer will likely cause font-lock to update the faces for that text, and clobber this highlighting.

If you don't edit the buffer, then I'm fairly sure that font-lock won't subsequently/stealthily fontify/clobber any of the highlight faces, as I've called font-lock-ensure up front; so calling this command should be good enough for read-only purposes.

phils
  • 53.1k
  • 3
  • 84
  • 127