2

summary

If one captures diff output to a file name=*.diff and opens that file in a buffer, one gets nicely-formatted mode=Diff. How to get that directly, without first capturing to a file?

details

I use diff a lot, not only via ediff-buffers (which I love) but also for more obscure purposes, like diffing outputs of processes. I've also been using Emacs for several decades, but continue to learn new aspects and uses. So I was not so much surprised as curious to find that, when I did (from the dir/folder of a local git repo)

$ git diff master origin/master > /tmp/foo__local_vs_remote.diff

and opened the file in a buffer, it displayed in a nicely/usefully colorized (à la ediff) mode=Diff. I had just never before simultaneously

  1. captured diff output to a file
  2. named the file *.diff
  3. opened the file in Emacs

But now I'm trying to capture diff output directly to a buffer and get output like that of the happy mode=Diff, and am failing.

seeking genericity

Note also that, since I use diff in lots of contexts, I'm looking for a solution to the general problem, and not, e.g., just to the git diff problem (which I suspect Magit etc have solved). Seeking genericity, I'll test 3 usecases: "normal" file-vs-file diff, git diff, and process-substitution diff.

platform

$ lsb_release -ds
LMDE 2 Betsy
$ cat /etc/debian_version
8.3
$ uname -rv
3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt20-1+deb8u4 (2016-02-29)
$ emacs --version
GNU Emacs 24.4.1

options

shell-command

If I do the following (possibly after navigating to a buffer with an appropriate working directory)

  1. M-! <diff command/>
  2. C-x b *Shell Command Output* (where the output of M-!==M-x shell-command goes by default)
  3. M-x diff-mode

... I get the nicely-formatted output. Furthermore

  • this works for all 3 testcases
  • if one runs M-! with another diff command, the new output just overwrites the old, but the buffer maintains diff-mode without user intervention
  • no keybinding changes (as with term-mode)

Chosen answer.

shell-mode

If I either

  1. M-x shell, goto the correct dir/folder, and run git diff master origin/master
  2. am in a buffer on the correct dir/folder, and run M-& git diff master origin/master

I get the dreaded WARNING: terminal is not fully functional.

term-mode

As Emacs User points out, M-x term performs better for this usecase than M-x shell: if I M-x term, goto the correct dir/folder, and run git diff master origin/master, I get nicely colorized output. It's not exactly mode=Diff, but it does the job. Unfortunately

  • That only works for git diff: I get no colorization for either process-substitution or file diff.
  • I find the term-mode keybinding changes highly annoying.
  • I also found term-mode navigation odd: when editing history, my cursor would sometimes bounce around oddly. solved).
2

Try

  1. M-! <your diff command/>
  2. C-x b *Shell Command Output* (where the output of M-!==M-x shell-command goes by default)
  3. M-x diff-mode
  • see reasons for choosing in question section=shell-command – TomRoche Mar 4 '16 at 23:46
  • Those reading this answer should be aware that the WARNING: terminal is not fully functional is not solved by this accepted solution. It may work for this limited diff case, but if one is seeking genericity as the OP requested, please use M-x term as a complete solution. See the Emacs documentation for reasons. – Emacs User Mar 5 '16 at 3:42
3

You can always write a function to do all the repeated steps for you. This should get you started:

(defun diff-generic(command)
  (interactive "sDiff command:")
  (let ((buffer (generate-new-buffer "*diff-generic*")))
    (with-current-buffer buffer (diff-mode))
    (call-process-shell-command command nil buffer 0)
    (switch-to-buffer buffer)))

In general you can do M-x diff to get that diff output for two arbitrary files. More info on that here: (info "(emacs) Diff Mode")

Magit does provide diff functionality, but take note that it uses it's own mode called magit-diff-mode, that is different from generic emacs diff-mode.

Also emacs bundled package VC provides diff functionality for version control diffs. Unlike magit it works with backends other than git and uses diff-mode, also you can use ediff. Relevant manual: (info "(emacs) Old Revisions")

  • see section='seeking genericity'. How will this handle, e.g., process substitution? – TomRoche Mar 4 '16 at 4:11
  • I've updated my answer, this should what you want. – sg2002 Mar 5 '16 at 4:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.