aboutsummaryrefslogtreecommitdiffstats
path: root/plugin/50-autowrite.lua
blob: 046558e6ce952900af11c255ba57ecf592890323 (plain)
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
--[[ 50-autowrite.lua — opt-in per-buffer autosave, writing the buffer back to disk as it changes.

A buffer flagged for autowrite is written (`:update`) after every normal-mode change and on leaving
insert mode.
Only normal, named, writable buffers are written, so scratch, unnamed and read-only buffers never
trigger a write error.
AutoWrite is off by default and per-buffer: the state lives in `vim.b.autowrite` and shows as the
`+W` flag in the statusline (see 50-ui.lua).
Turning autowrite on saves the buffer immediately, so it starts out in sync with the disk.

User commands:
  `AutoWriteToggle`:  toggle autosave for the current buffer

Keymaps:
  `<Leader>bs`   toggle autosave for the current buffer
]]

-- True when `buf` is a normal, named, writable file buffer that `:update` can save.
local function writable(buf)
	return vim.bo[buf].buftype == ""
		and vim.api.nvim_buf_get_name(buf) ~= ""
		and vim.bo[buf].modifiable
		and not vim.bo[buf].readonly
end

-- Write the changed buffer when it is flagged for autowrite and safe to save.
local function write_flagged_buffer(args)
	if vim.b[args.buf].autowrite and writable(args.buf) then
		vim.api.nvim_buf_call(args.buf, vim.cmd.update)
	end
end

--[[ Flip autowrite for the current buffer.
Save immediately when turning it on so the buffer catches up with its pending changes. ]]
local function toggle_autowrite()
	vim.b.autowrite = not vim.b.autowrite
	if vim.b.autowrite and writable(0) then
		vim.cmd.update()
	end
	vim.notify(
		"Buffer autowrite " .. (vim.b.autowrite and "enabled" or "disabled") .. " for this buffer",
		vim.log.levels.INFO
	)
	vim.cmd.redrawstatus()
end

--[[ `nested` so the `:update` fires `BufWritePre`, letting the format engine (50-format.lua) run
its on-write formatter. ]]
vim.api.nvim_create_autocmd({ "TextChanged", "InsertLeave" }, {
	group = vim.g.dotfiles_augroup,
	nested = true,
	callback = write_flagged_buffer,
})

vim.api.nvim_create_user_command(
	"AutoWriteToggle",
	toggle_autowrite,
	{ desc = "Toggle buffer autowrite" }
)

vim.keymap.set("n", "<Leader>bs", toggle_autowrite, { desc = "Toggle buffer autowrite" })

local help = require("help")
help.register("General", {
	maps = { { "<Leader>bs", "Toggle buffer autowrite" } },
	commands = { { "AutoWriteToggle", "Toggle buffer autowrite" } },
})