Diffing the Current Buffer

Sometimes it can be handy to get a quick diff of the changes that have been made to the current buffer since the previous save. This can be achieved with a simple command-line mode command.

To demonstrate, let's start with the following buffer:

Initial Conditions
a·=·[
····"one",
····"two",
····"three",
····"five",
]
COMMAND
Top
1:1
:%s/two/changed

Now lets edit the buffer. To keep it simple we will make a single edit, changing "two" to "changed":

Edit the Buffer
a·=·[
····"one",
····"changed",
····"three",
····"five",
]
NORMAL
43%
3:5
 

Now, we can generate a simple diff with the command:

:write !diff % -

Let's review what this does. To start, this uses the :write command with the following call signature:

:w[rite] !{cmd}

Which passes the entire contents of the current buffer to the specified command via stdin. In this example we will use the diff shell command, which has the call signature:

diff file1 file2

where our command defines file1 and file2 as:

  • file1 = %, which contains the filename of the current file, and

  • file2 = -, which tells diff to read stdin

So, putting this all together, we pass the current buffer contents to the diff command, and generate the diff between the saved version of the current file (%) and the current buffer contents. Finally, the diff is passed back to Neovim:

Generate the Diff
a·=·[
····"one",
····"changed",
····"three",
····"five",
]
NORMAL
43%
3:5
 
:write !diff % -
3c3
<     "two",
---
>     "changed",
shell returned 1

The output window shows that the line containing "two" has been changed to "changed". diff also returns a status code if 1, meaning that the two files were different.

This is definitely not the prettiest diff in the world, but is useful when a quick diff is required. Take a look at:

diff --help

to see what options are available to suit the output to your needs. For example, by leveraging diff's options one can format the same output as a side-by-side diff:

:write !diff -yt -W 60 % -
Alternate Output
a·=·[
····"one",
····"changed",
····"three",
····"five",
]
NORMAL
43%
3:5
 
:write !diff -yt -W 60 % -
a = [                           a = [
    "one",                          "one",
    "two",                   |      "changed",
    "three",                        "three",
    "five",                         "five",
]                               ]
shell returned 1