重複する行を強調表示するにはどうすればよいですか?


8

ここに私が持っているものがあります:

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

私の意図は、これを追加してpost-command-hookロジックを複製している行を見つけることですが、コマンドを2回目に実行しても効果がありません(古いフォントロックはまだ有効です)。

2番目の問題は、フォントロック自体が更新されないことが原因です。(font-lock-mode -1) (font-lock-mode 1)定義にを追加しようとしましたが、効果がありませんでした。

しかし、なぜこのコマンドが1回の実行に対してのみ有効なのかはわかりません。


highlight-lines-matching-regexp内側を包んでみてください(let ((hi-lock-mode -1)) .. )。私は同じ問題を解決するためにそれをした:github.com/kaushalmodi/.emacs.d/blob/...
Kaushalモディ

unhighlight-regexp使用することもできます。とにかく、この機能は、バッファをスキャンして重複行を探し、それらに強調表示を適用するフォントロックマッチング関数を使用して実装するのがおそらく最善です。これは、重複する行がなくなると、自動的にハイライト解除を処理します。
Jordon Biondo 2015年

@kaushalmodiそんな幸運はありません:(ありがとう
Sean Allred

@JordonBiondo私はそれについて考えましたが、highlight-lines-matching-regexpこのケースに適用できるに違いありません-それはほとんど靴のようなものです。(私はオーバーレイの使用も考えましたが、それは私があまり馴染みのない概念です。)
Sean Allred

バッファーの内容を別のバッファーにコピーし、を実行してdelete-duplicate-lines、2つのバッファーを比較することができます。
wvxvw

回答:


6
  1. font-lock-keywords関数を呼び出した後に見てください。フォント化する正規表現として、最初の行の正規表現が含まれていることがわかります。あなたがしたことは、与えられた行をピックアップしてそれに一致する正規表現を入れるfont-lock-keywordsことだけでした-そのため、その行の重複のみが強調表示されます。IOW、その最初の行の正規表現はハードコードされていfont-lock-keywordsます。

  2. 代わりに、使用することができますFUNCTIONfont-lock-keywords。しかし、私は各行の重複がないかどうかバッファを順番に検索し、に煩わされることはありませんfont-lock-keywords

これが1つの簡単な解決策です。ハイライトライブラリ()の関数hlt-highlight-regionを使用しますが、必要に応じて他の関数を使用できます。highlight.el

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

そして、これは(a)アクティブなリージョン、または(b)リージョンがアクティブでない場合はフルバッファーで動作するバージョンです。

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

そして、あなたがしたい場合はアップデートパッケージのセットごとに異なる顔そしてちょうどバインド変数faceではlet、とsetqそれへの(hlt-next-face)場所の隣にline-re設定されている、と交換してくださいfont-lock-warning-faceface。オプションhlt-auto-face-backgroundsは、使用する面を制御します。

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

私は実際にはほぼ同じに見える、機能ごとに機能するものに取り組んでいました!私が提案する1つのことは、行のテキストから先頭/末尾の空白を取り除き、[\ t] *のようなものを正規表現の先頭と末尾に追加して、異なるインデントレベルの行が一致するようにすることです。
Jordon Biondo 2015年

@JordonBiondo:しかし、それはOPが要求したものではありません。何でも可能ですが、私は質問と解決策の試みから私の手がかりを取りました:彼はどうやら実際に行テキストと正確に一致させたいと考えています。つまり、インデントや末尾の空白は無視しません。しかし、はい、多くのバリアントが可能です。Dunnoは、このようなものが本当にどれほど役立つかを説明します。それはあなたがそれで何をしたいかによりますね。
2015年

さて、私のユースケースは、ロジックがどこで複製されているかを認識して最適化を試みることができるようにすることです:)アルゴリズムをスケッチして正式な構文を使用しているため、正確な複製は不可能です。
Sean Allred、2015年

どういう意味かわかりません、ショーン。しかし、@ JordonBiondoが示唆したように、先頭と末尾の空白を無視したい場合は、彼が提案したとおりにしてください。可能な空白のプレフィックスとサフィックスを正規表現に追加します。
ドリュー

私はあなたの最後の関数を使ってみましたが、関数定義をコンパイルすると私は得setq: Symbol's value as variable is void: hlt-highlight-line-dups-ignore-regexpます。この変数はどのように定義されていますか?
Patrick、

1

フォントロックの代わりにオーバーレイを使用するのはどうですか?

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

リージョンを作成すると、次の方法でM-x my-highlight-duplicate-lines-in-region すべてのオーバーレイをクリアできますM-x ov-clear


0

これは少し大ざっぱですが、多少の努力(引数C-h fediff-buffersRETに関する情報を参照HOOK)を行うと、表示を改善したり、diffモードを終了するときにより適切なクリーンアップを実行したりできます。

(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

福山慎吾氏による上記の回答の改善。

このバージョンは、アクティブな領域で重複する行をチェックしますが、ない場合は、バッファ全体を検索します。

(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) '<)))))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.