@tmalsburg, Lệnh sau gọi diff trên 2 bộ đệm mà không tạo tệp tạm thời. Nó sử dụng các đường ống được đặt tên như bạn đề xuất ở trên:
(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))))))
- Khi được gọi tương tác, nó hiển thị khác biệt khi bộ đệm có nội dung khác nhau.
Khi được gọi từ Lisp, nó trả về mã thoát của chương trình diff; nghĩa là 0 nếu bộ đệm có cùng nội dung, 1 nếu không.
(diff-buffers-without-temp-files (get-buffer "*scratch*") (get-buffer "*scratch*"))
=> 0
(diff-buffers-without-temp-files (get-buffer "*scratch*") (get-buffer "*Messages*"))
=> 1
Đã thử nghiệm phiên bản Emacs 24.3 trong một máy chạy Debian GNU / Linux 9.0 (kéo dài).
Các mã ở trên dường như làm việc được gọi là từ Lisp. Thật không may, hầu hết thời gian cho thấy một sự khác biệt cắt ngắn trong các cuộc gọi tương tác.
Phiên bản sau sử dụng thư viện async của bên thứ 3 ; nó không cắt bớt các khác biệt.
(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))))))