@tmalsburg, el siguiente comando llama a diff en 2 buffers sin la creación de archivos temporales. Utiliza tuberías con nombre como sugirió anteriormente:
(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))))))
- Cuando se llama interactivamente, muestra la diferencia cuando los buffers tienen contenido diferente.
Cuando se llama desde Lisp, devuelve el código de salida del programa diff; es decir, 0 si los búferes tienen el mismo contenido, 1 de lo contrario.
(diff-buffers-without-temp-files (get-buffer "*scratch*") (get-buffer "*scratch*"))
=> 0
(diff-buffers-without-temp-files (get-buffer "*scratch*") (get-buffer "*Messages*"))
=> 1
Probado para Emacs versión 24.3 en una máquina que ejecuta Debian GNU / Linux 9.0 (stretch).
El código anterior parece funcionar cuando se llama desde Lisp. Desafortunadamente, la mayoría de las veces muestra una diferencia truncada en las llamadas interactivas.
La siguiente versión usa la biblioteca asíncrona de terceros ; no trunca las diferencias.
(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))))))