Làm thế nào tôi có thể làm nổi bật các dòng trùng lặp?


8

Đây là những gì tôi có:

(defun my-show-duplicate-lines ()
  (interactive)
  (highlight-lines-matching-regexp
   (concat "^"
           (regexp-quote
            (substring-no-properties
             (thing-at-point 'line) 0 -1))
           "$")
   font-lock-warning-face))

Ý định của tôi là thêm cái này để post-command-hooktìm các dòng trong đó tôi đang sao chép logic, nhưng khi tôi chạy lệnh lần thứ hai, nó không hiệu quả (và khóa phông chữ cũ vẫn còn hiệu lực).

Vấn đề thứ hai là do font-lock không tự làm mới. Tôi đã thử thêm một (font-lock-mode -1) (font-lock-mode 1)định nghĩa, nhưng nó không hiệu quả.

Tôi không biết tại sao lệnh sẽ chỉ tốt cho một lần chạy.


Hãy thử bọc highlight-lines-matching-regexpbên trong (let ((hi-lock-mode -1)) .. ). Tôi đã làm điều đó để giải quyết vấn đề tương tự: github.com/kaushalmodi/.emacs.d/blob/ mẹo
Kaushal Modi

unhighlight-regexpcũng có thể được sử dụng. Bất kể tính năng này có thể được triển khai tốt nhất bằng cách sử dụng chức năng khớp khóa phông chữ để quét bộ đệm cho các dòng trùng lặp và áp dụng tô sáng cho chúng. Điều này sẽ tự động xử lý việc làm nổi bật một khi không có dòng trùng lặp.
Jordon Biondo

@kaushalmodi không có may mắn như vậy :( mặc dù cảm ơn
Sean Allred

@JordonBiondo Tôi đã nghĩ về điều đó, nhưng highlight-lines-matching-regexpphải áp dụng cho trường hợp này - nó gần như là một chiếc giày. (Mặc dù tôi cũng đã nghĩ đến việc sử dụng lớp phủ, nhưng đó là một khái niệm tôi ít quen thuộc hơn.)
Sean Allred

Bạn có thể sao chép nội dung của bộ đệm vào bộ đệm khác, sau đó chạy delete-duplicate-lines, sau đó tìm hai bộ đệm.
wvxvw

Câu trả lời:


6
  1. Hãy xem font-lock-keywordssau khi bạn đã gọi chức năng của bạn. Bạn sẽ thấy rằng nó chỉ có regrec cho dòng đầu tiên là regrec để phông chữ. Tất cả những gì bạn đã làm là chọn một dòng nhất định và đặt biểu thức chính quy để khớp với nó font-lock-keywords- vì vậy chỉ các phần của dòng đó được tô sáng. IOW, biểu thức chính quy cho dòng đầu tiên được mã hóa cứng font-lock-keywords.

  2. Thay vào đó, bạn có thể sử dụng một FUNCTIONtrong font-lock-keywords. Nhưng tôi sẽ chỉ tìm kiếm bộ đệm cho dups của từng dòng, và không bận tâm đến font-lock-keywords.

Đây là một giải pháp nhanh chóng. Nó sử dụng chức năng hlt-highlight-regiontừ thư viện Highlight ( highlight.el), nhưng bạn có thể sử dụng cái gì đó khác nếu bạn thích.

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

Và đây là phiên bản hoạt động trên (a) vùng hoạt động hoặc (b) bộ đệm đầy đủ nếu vùng đó không hoạt động:

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

Và nếu bạn muốn có một khuôn mặt khác nhau cho mỗi bộ dups sau đó chỉ cần ràng buộc một biến facetrong let, và setqnó đến (hlt-next-face)bên cạnh nơi line-ređược thiết lập, và thay thế font-lock-warning-facevới face. Tùy chọn hlt-auto-face-backgroundskiểm soát các khuôn mặt được sử dụng.

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

Tôi thực sự chỉ đang làm việc trên một cái gì đó trông gần giống nhau, chức năng cho chức năng! Một điều tôi muốn đề xuất là tước khoảng trắng đầu / cuối từ văn bản của dòng và thêm một cái gì đó như [\ t] * vào đầu và cuối của biểu thức chính quy để các dòng ở các mức thụt lề khác nhau vẫn khớp.
Jordon Biondo

@JordonBiondo: Nhưng đó không phải là những gì OP yêu cầu. Bất cứ điều gì cũng có thể, nhưng tôi đã lấy gợi ý của mình từ câu hỏi và nỗ lực giải pháp: Anh ta rõ ràng thực sự muốn khớp chính xác văn bản dòng, và bắt đầu từ bol, tức là không bỏ qua khoảng cách thụt đầu dòng hoặc dấu cách. Nhưng có, rất nhiều biến thể là có thể. Làm thế nào hữu ích bất cứ điều gì như thế này thực sự là. Tôi đoán nó phụ thuộc vào những gì bạn muốn làm với nó.
vẽ

Chà, trường hợp sử dụng của tôi là nhận ra nơi logic đang được sao chép để tôi có thể cố gắng tối ưu hóa :) Tôi đang phác thảo một thuật toán và sử dụng một cú pháp chính thức, vì vậy các bản sao chính xác là nhiều hơn có thể.
Sean Allred

Không chắc ý của bạn là gì, Sean. Nhưng nếu bạn muốn bỏ qua khoảng trắng hàng đầu và dấu, như @JordonBiondo đã đề xuất, thì hãy làm như anh ấy đề xuất: thêm tiền tố khoảng trắng có thể và hậu tố vào biểu thức chính quy.
vẽ

Tôi đã thử sử dụng hàm cuối cùng của bạn nhưng khi biên dịch định nghĩa hàm tôi nhận được setq: Symbol's value as variable is void: hlt-highlight-line-dups-ignore-regexp. Biến này được định nghĩa như thế nào?
Patrick

1

Làm thế nào về việc sử dụng lớp phủ thay vì khóa phông chữ?

;; https://github.com/ShingoFukuyama/ov.el
(require 'ov)

(defun my-highlight-duplicate-lines-in-region ()
  (interactive)
  (if mark-active
      (let* (($beg (region-beginning))
             ($end (region-end))
             ($st (buffer-substring-no-properties
                   $beg $end))
             ($lines)
             $dup)
        (deactivate-mark t)
        (save-excursion
          (goto-char $beg)
          (while (< (point) $end)
            (let* (($b (point))
                   ($e (point-at-eol))
                   ($c (buffer-substring-no-properties $b $e))
                   ($a (assoc $c $lines)))
              (when (not (eq $b $e))
                (if $a
                    (progn
                      (setq $dup (cons $b $dup))
                      (setq $dup (cons (cdr $a) $dup)))
                  (setq $lines
                        (cons (cons $c $b) $lines)))))
            (forward-line 1))
          (mapc (lambda ($p)
                  (ov-set (ov-line $p) 'face '(:foreground "red")))
                (sort (delete-dups $dup) '<))))))

Tạo vùng và sau đó M-x my-highlight-duplicate-lines-in-region Bạn có thể xóa tất cả các lớp phủ bằng cáchM-x ov-clear


0

Đây là một chút sơ sài, nhưng với một số nỗ lực (xem C-h fediff-buffersRETthông tin về HOOKđối số), bạn có thể làm cho nó hiển thị tốt hơn / thực hiện việc dọn dẹp tốt hơn khi thoát khỏi chế độ khác:

(defun my/show-duplicate-lines (beg end)
  (interactive "r")
  (unless (region-active-p)
    (setf beg (point-min)
          end (point-max)))
  (let ((copy (buffer-substring beg end))
        (original (current-buffer))
        (dupes-buffer (get-buffer-create (format "%s[dupes]" (buffer-name)))))
    (with-current-buffer dupes-buffer
      (erase-buffer)
      (insert copy)
      (delete-duplicate-lines (point-min) (point-max))
      (ediff-buffers original dupes-buffer))))

0

Cải thiện câu trả lời ở trên của Shingo Fukuyama.

Phiên bản này kiểm tra các dòng trùng lặp trong vùng hoạt động nhưng nếu không có, tìm kiếm toàn bộ bộ đệm.

(require 'ov)
(defun highlight-duplicate-lines-in-region-or-buffer ()
(interactive)

  (let* (
    ($beg (if mark-active (region-beginning) (point-min)))
    ($end (if mark-active (region-end) (point-max)))
    ($st (buffer-substring-no-properties $beg $end))
    ($lines)
    ($dup))
  (deactivate-mark t)
  (save-excursion
    (goto-char $beg)
    (while (< (point) $end)
      (let* (($b (point))
         ($e (point-at-eol))
         ($c (buffer-substring-no-properties $b $e))
         ($a (assoc $c $lines)))
    (when (not (eq $b $e))
      (if $a
          (progn
        (setq $dup (cons $b $dup))
        (setq $dup (cons (cdr $a) $dup)))
        (setq $lines
          (cons (cons $c $b) $lines)))))
      (forward-line 1))
    (mapc (lambda ($p)
        (ov-set (ov-line $p) 'face '(:foreground "red")))
      (sort (delete-dups $dup) '<)))))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.