@tmalsburg、次のコマンドは、一時ファイルを作成せずに2つのバッファーでdiffを呼び出します。上記で提案したように、名前付きパイプを使用します。
(require 'diff)
(defun diff-buffers-without-temp-files (buffer1 buffer2 &optional switches)
"Run diff program on BUFFER1 and BUFFER2.
Make the comparison without the creation of temporary files.
When called interactively with a prefix argument, prompt
interactively for diff switches. Otherwise, the switches
specified in the variable `diff-switches' are passed to the diff command."
(interactive
(list (read-buffer "buffer1: " (current-buffer))
(read-buffer "buffer2: " (current-buffer))
(diff-switches)))
(or switches (setq switches diff-switches))
(unless (listp switches) (setq switches (list switches)))
(let ((buffers (list buffer1 buffer2))
(buf (get-buffer-create "*diff-buffers*"))
fifos res)
(dotimes (_ 2) (push (make-temp-name "/tmp/pipe") fifos))
(setq fifos (nreverse fifos))
(with-current-buffer buf (erase-buffer))
(unwind-protect
(progn
(dotimes (i 2)
(let ((cmd (format "cat > %s << EOF\n%s\nEOF"
(nth i fifos)
(with-current-buffer (nth i buffers)
(buffer-string)))))
(call-process "mkfifo" nil nil nil (nth i fifos))
(start-process-shell-command (format "p%d" i) nil cmd)))
(setq res (apply #'call-process diff-command nil buf nil (car fifos) (cadr fifos) switches))
(if (zerop res)
(message "Buffers have same content")
(display-buffer buf)
(with-current-buffer buf (diff-mode))
(message "Buffer contents are different"))
res)
;; Clean up.
(dolist (x fifos)
(and (file-exists-p x) (delete-file x))))))
- インタラクティブに呼び出されると、バッファーの内容が異なる場合に差分が表示されます。
Lispから呼び出されると、diffプログラムの終了コードを返します。つまり、バッファの内容が同じ場合は0、それ以外の場合は1。
(diff-buffers-without-temp-files (get-buffer "*scratch*") (get-buffer "*scratch*"))
=> 0
(diff-buffers-without-temp-files (get-buffer "*scratch*") (get-buffer "*Messages*"))
=> 1
Debian GNU / Linux 9.0(ストレッチ)を実行しているマシンでEmacsバージョン24.3をテストしました。
(require 'diff)
(require 'async)
(defun diff-buffers-without-temp-files (buffer1 buffer2 &optional switches)
"Run diff program on BUFFER1 and BUFFER2.
Make the comparison without the creation of temporary files.
When called interactively with a prefix argument, prompt
interactively for diff switches. Otherwise, the switches
specified in the variable `diff-switches' are passed to the diff command."
(interactive
(list (read-buffer "buffer1: " (current-buffer))
(read-buffer "buffer2: " (current-buffer))
(diff-switches)))
(or switches (setq switches diff-switches))
(unless (listp switches) (setq switches (list switches)))
(let ((buffers (list buffer1 buffer2))
(buf (get-buffer-create "*diff-buffers*"))
fifos res)
(dotimes (_ 2) (push (make-temp-name "/tmp/pipe") fifos))
(setq fifos (nreverse fifos))
(with-current-buffer buf (erase-buffer))
(unwind-protect
(progn
(dotimes (i 2)
(let ((cmd (format "cat > %s" (nth i fifos))))
(call-process "mkfifo" nil nil nil (nth i fifos))
(async-start
`(lambda ()
(with-temp-buffer
(insert ,(with-current-buffer (nth i buffers) (buffer-string)))
(call-process-region
1 (point-max) shell-file-name nil nil nil
shell-command-switch ,cmd))))))
(setq res (apply #'call-process diff-command nil buf nil (car fifos) (cadr fifos) switches))
(if (zerop res)
(message "Buffers have same content")
(display-buffer buf)
(with-current-buffer buf (diff-mode))
(message "Buffer contents are different"))
res)
;; Clean up.
(dolist (x fifos)
(and (file-exists-p x) (delete-file x))))))