Take a look at font-lock-keywords
after you have called your function. You will see that it just has the regexp for the first line as the regexp to fontify. All you did was to pick up a given line and put a regexp to match it into font-lock-keywords
- so only dups of that line get highlighted. IOW, the regexp for that first line is hard-coded in font-lock-keywords
.
Instead, you could use a FUNCTION
in font-lock-keywords
. But I would just search the buffer for dups of each line, in turn, and not bother with font-lock-keywords
.
Here is one quick solution. It uses function hlt-highlight-region
from the Highlight library (highlight.el
), but you can use something else if you like.
(defun highlight-line-dups ()
(interactive)
(let ((count 0)
line-re)
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(setq count 0
line-re (concat "^" (regexp-quote (buffer-substring-no-properties
(line-beginning-position)
(line-end-position)))
"$"))
(save-excursion
(goto-char (point-min))
(while (not (eobp))
(if (not (re-search-forward line-re nil t))
(goto-char (point-max))
(setq count (1+ count))
(unless (< count 2)
(hlt-highlight-region (line-beginning-position) (line-end-position)
'font-lock-warning-face)
(forward-line 1)))))
(forward-line 1)))))
And here is a version that works on (a) the active region or (b) the full buffer if the region is not active:
(defun highlight-line-dups-region (&optional start end face msgp)
(interactive `(,@(hlt-region-or-buffer-limits) nil t))
(let ((count 0)
line-re)
(save-excursion
(goto-char start)
(while (< (point) end)
(setq count 0
line-re (concat "^" (regexp-quote (buffer-substring-no-properties
(line-beginning-position)
(line-end-position)))
"$"))
(save-excursion
(goto-char start)
(while (< (point) end)
(if (not (re-search-forward line-re nil t))
(goto-char end)
(setq count (1+ count))
(unless (< count 2)
(hlt-highlight-region
(line-beginning-position) (line-end-position)
face)
(forward-line 1)))))
(forward-line 1)))))
And if you want a different face for each set of dups then just bind a variable face
in the let
, and setq
it to (hlt-next-face)
next to where line-re
is set, and replace font-lock-warning-face
with face
. Option hlt-auto-face-backgrounds
controls the faces used.
(defun hlt-highlight-line-dups-region (&optional start end msgp)
(interactive `(,@(hlt-region-or-buffer-limits) t))
(let ((hlt-auto-faces-flag t)
count line line-re ignore-re)
(save-excursion
(goto-char start)
(while (< (point) end)
(setq count 0
line (buffer-substring-no-properties (line-beginning-position)
(line-end-position))
ignore (and (not (string= "" line)) "[ \t]*")
line-re (concat "^" ignore (regexp-quote line) ignore "$"))
(save-excursion
(goto-char start)
(while (< (point) end)
(if (not (re-search-forward line-re end t))
(goto-char end)
(setq count (1+ count))
(unless (< count 2)
(hlt-highlight-region (line-beginning-position) (line-end-position))
(forward-line 1)))))
(forward-line 1)))))
highlight-lines-matching-regexp
inside(let ((hi-lock-mode -1)) .. )
. I did that to solve the same problem: github.com/kaushalmodi/.emacs.d/blob/…unhighlight-regexp
can also be used. Regardless this feature is probably best implemented using a font-lock matching function that scans the buffer for duplicate lines and applies highlighting to them. This would handle unhighlighting automatically once there are no duplicate lines.highlight-lines-matching-regexp
must be applicable to this case -- it's almost a shoe-in. (Though I also thought about using overlays, but that's a concept I'm less familiar with.)delete-duplicate-lines
, then diff two buffers.