« ^ »

2つのリージョンの差分を比較する

所要時間: 約 2分

2つの異なるファイルを部分的に比較したい事がある。つまり2つの異なるバッファとリージョンを比較したい。

これを行う時、サードパーティのライブラリである multi-cursorexpand-regioniedit を使って実現しようと考えるかも知れない。その考えは間違いではないんだけれど、この単純な事を行いたいだけの為に、いくつもライブラリを入れて知らないコードを走らせる必要があるんだろうか。そのコードを眺めたり、仕様を理解するような必要があるのだろうか。サードパーティのコードに依存する事による潜在的なセキュリティ上のリスクに怯えないといけないのだろうか。

僕は、こういった単純な事をしたいだけであれば、無理にサードパーティのコードを利用するのではなく、必要な部分だけを自前実装した方が良いと考えている。サードパーティのコードを使う事自体は素晴らしいけれど、小さなコードまで再利用にこだわり車輪の再発明を嫌うと、柔軟性を失ったりリスクを抱えないといけない事になる。

この要求を実現したければ、次のようなコードをスクラッチバッファで評価しておけばいい。

(setq selectable-diff-a nil)  ;; format '(buffer . (beg . end))
(setq selectable-diff-b nil)  ;; format '(buffer . (beg . end))

(defun selectable-diff-a (beg end)
  (interactive "r")
  (setq selectable-diff-a
	`(,(current-buffer) . (,beg . ,end))))

(defun selectable-diff-b (beg end)
  (interactive "r")
  (setq selectable-diff-b
	`(,(current-buffer) . (,beg . ,end))))

(defun selectable-diff ()
  (interactive)
  (with-current-buffer (car selectable-diff-a)
    (write-region (car (cdr selectable-diff-a))
		  (cdr (cdr selectable-diff-a))
		  "/tmp/a.txt"))
  
  (with-current-buffer (car selectable-diff-b)
    (write-region (car (cdr selectable-diff-b))
		  (cdr (cdr selectable-diff-b))
		  "/tmp/b.txt"))
  
  (diff "/tmp/a.txt" "/tmp/b.txt"))

まず、1つ目の比較対象のリージョンを選択し M-x selectable-diff-a で登録する。この時、バッファとリージョンの位置が記録される。

次に、2つ目の比較対象のリージョンを選択し M-x selectable-diff-b で登録する。この時、バッファとリージョンの位置が記録される。

最後に、 M-x selectable-diff を実行する事で、diffが実行され差分が表示される。実装もとても単純なはずだ。気に入らない所があってもすぐに修正できる。日常的に使うツールは、これぐらい柔軟性があって良い。何でもかんでもシステマチックになっている必要はないし、綺麗にパッケージになっている必要もないし、体裁が整っている必要もない。僕にとって必要な要素は、把握のしやすさであり、好き勝手に動きを変えられる柔軟性だ。