1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
--[[ 50-diff_orig.lua — diff the current buffer against the file it was loaded from.
Copies the file on disk to a temp file and diffs it against the buffer in a scratch split,
so the unsaved changes in the buffer show as a regular diff.
Re-running the command replaces the previous scratch with a fresh snapshot of the file.
User commands:
`DiffOrig[!]`: show the diff between the current buffer and its file; with `!` split vertically
]]
--[[ Close the scratch window left by a previous `DiffOrig` on the current buffer, if any.
The window id is kept in the buffer-local `diff_orig_win`; closing the window wipes the scratch
(`bufhidden=wipe`) and drops the buffer out of diff mode. ]]
local function close_previous_scratch()
local prev = vim.b.diff_orig_win
if prev and vim.api.nvim_win_is_valid(prev) then
vim.api.nvim_win_close(prev, true)
end
end
--[[ Open `file` in a scratch diff split — vertical when `vertical` is true — and diff it.
The scratch takes `filetype` so the diff keeps the original's syntax highlighting. ]]
local function open_scratch_diff(file, vertical, filetype)
vim.cmd.split({ file, mods = { vertical = vertical, keepalt = true } })
vim.cmd.diffthis()
vim.opt_local.bufhidden = "wipe"
vim.opt_local.buftype = "nofile"
vim.opt_local.swapfile = false
vim.opt_local.readonly = true
if filetype ~= "" then
vim.opt_local.filetype = filetype
end
end
-- Show the diff between the current buffer and the file it was loaded from.
local function show_buf_diff_orig(opts)
local bname = vim.api.nvim_buf_get_name(0)
if bname == "" then
vim.notify("Cannot diff with original because the buffer has no file", vim.log.levels.WARN)
return
end
if not vim.uv.fs_stat(bname) then
vim.notify(
"Cannot diff with original because " .. bname .. " doesn't exist",
vim.log.levels.WARN
)
return
end
local temp = vim.fn.tempname()
local ok, err = vim.uv.fs_copyfile(bname, temp)
if not ok then
vim.notify("Could not copy file: " .. err, vim.log.levels.ERROR)
return
end
close_previous_scratch()
local cwin = vim.api.nvim_get_current_win()
local filetype = vim.bo.filetype
vim.cmd.diffthis()
open_scratch_diff(temp, opts.bang, filetype)
local swin = vim.api.nvim_get_current_win()
vim.api.nvim_set_current_win(cwin)
vim.b.diff_orig_win = swin
end
----------------------------------------------------------------------------------------------------
vim.api.nvim_create_user_command(
"DiffOrig",
show_buf_diff_orig,
{ bang = true, desc = "Show diff between current buffer and file (! splits vertically)" }
)
local help = require("help")
help.register("General", {
commands = { { "DiffOrig", "Show diff between current buffer and file (! splits vertically)" } },
})
|