feat: add defer_save, cancel_save, immediate_save trigger options (#11)

Fixes #8
This commit is contained in:
Toni Müller
2023-03-28 09:11:00 +02:00
committed by GitHub
parent 343bbfa98a
commit a5e39553c5
3 changed files with 62 additions and 42 deletions

View File

@@ -106,7 +106,11 @@ EOF
dim = 0.18, -- dim the color of `message`
cleaning_interval = 1250, -- (milliseconds) automatically clean MsgArea after displaying `message`. See :h MsgArea
},
trigger_events = {"InsertLeave", "TextChanged"}, -- vim events that trigger auto-save. See :h events
trigger_events = { -- See :h events
immediate_save = { "BufLeave", "FocusLost" }, -- vim events that trigger an immediate save
defer_save = { "InsertLeave", "TextChanged" }, -- vim events that trigger a deferred save (saves after `debounce_delay`)
cancel_defered_save = { "InsertEnter" }, -- vim events that cancel a pending deferred save
},
-- function that determines whether to save the current buffer or not
-- return true: if buffer is ok to be saved
-- return false: if it's not ok to be saved
@@ -122,7 +126,7 @@ EOF
return false -- can't save
end,
write_all_buffers = false, -- write all buffers when the current one meets `condition`
debounce_delay = 135, -- saves the file at most every `debounce_delay` milliseconds
debounce_delay = 1000, -- delay after which a pending save is executed
callbacks = { -- functions to be executed at different intervals
enabling = nil, -- ran when enabling auto-save
disabling = nil, -- ran when disabling auto-save

View File

@@ -9,7 +9,11 @@ Config = {
dim = 0.18, -- dim the color of `message`
cleaning_interval = 1250, -- (milliseconds) automatically clean MsgArea after displaying `message`. See :h MsgArea
},
trigger_events = { "InsertLeave", "TextChanged" }, -- vim events that trigger auto-save. See :h events
trigger_events = { -- See :h events
immediate_save = { "BufLeave", "FocusLost" }, -- vim events that trigger an immediate save
defer_save = { "InsertLeave", "TextChanged" }, -- vim events that trigger a deferred save (saves after `debounce_delay`)
cancel_defered_save = { "InsertEnter" }, -- vim events that cancel a pending deferred save
},
-- function that determines whether to save the current buffer or not
-- return true: if buffer is ok to be saved
-- return false: if it's not ok to be saved
@@ -23,7 +27,7 @@ Config = {
return false -- can't save
end,
write_all_buffers = false, -- write all buffers when the current one meets `condition`
debounce_delay = 135, -- saves the file at most every `debounce_delay` milliseconds
debounce_delay = 1000, -- delay after which a pending save is executed
callbacks = { -- functions to be executed at different intervals
enabling = nil, -- ran when enabling auto-save
disabling = nil, -- ran when disabling auto-save

View File

@@ -18,38 +18,26 @@ api.nvim_create_augroup("AutoSave", {
clear = true,
})
local global_vars = {}
local timers_by_buffer = {}
local function set_buf_var(buf, name, value)
if buf == nil then
global_vars[name] = value
else
if api.nvim_buf_is_valid(buf) then
api.nvim_buf_set_var(buf, "autosave_" .. name, value)
end
local function cancel_timer(buf)
local timer = timers_by_buffer[buf]
if timer ~= nil then
timer:close()
timers_by_buffer[buf] = nil
end
end
local function get_buf_var(buf, name)
if buf == nil then
return global_vars[name]
end
local success, mod = pcall(api.nvim_buf_get_var, buf, "autosave_" .. name)
return success and mod or nil
end
local function debounce(lfn, duration)
local function inner_debounce()
local buf = api.nvim_get_current_buf()
if not get_buf_var(buf, "queued") then
vim.defer_fn(function()
set_buf_var(buf, "queued", false)
lfn(buf)
end, duration)
set_buf_var(buf, "queued", true)
end
local function inner_debounce(buf)
-- instead of canceling the timer we could check if there is one already running for this buffer and restart it (`:again`)
cancel_timer(buf)
local timer = vim.defer_fn(function()
lfn(buf)
timers_by_buffer[buf] = nil
end, duration)
timers_by_buffer[buf] = timer
end
return inner_debounce
end
@@ -64,9 +52,7 @@ local function echo_execution_message()
end
end
function M.save(buf)
buf = buf or api.nvim_get_current_buf()
local function save(buf)
callback("before_asserting_save")
if cnf.opts.condition(buf) == false then
@@ -79,6 +65,8 @@ function M.save(buf)
callback("before_saving")
-- why is this needed? auto_save_abort is never set to true?
-- TODO: remove?
if g.auto_save_abort == true then
return
end
@@ -98,23 +86,48 @@ function M.save(buf)
end
end
local save_func = nil
function M.immediate_save(buf)
buf = buf or api.nvim_get_current_buf()
cancel_timer(buf)
save(buf)
end
local function perform_save()
local save_func = nil
local function defer_save(buf)
-- why is this needed? auto_save_abort is never set to true anyways?
-- TODO: remove?
g.auto_save_abort = false
-- is it really needed to cache this function
-- TODO: remove?
if save_func == nil then
save_func = (cnf.opts.debounce_delay > 0 and debounce(M.save, cnf.opts.debounce_delay) or M.save)
save_func = (cnf.opts.debounce_delay > 0 and debounce(save, cnf.opts.debounce_delay) or save)
end
save_func()
save_func(buf)
end
function M.on()
api.nvim_create_autocmd(cnf.opts.trigger_events, {
callback = function()
perform_save()
api.nvim_create_autocmd(cnf.opts.trigger_events.immediate_save, {
callback = function (opts)
M.immediate_save(opts.buf)
end,
pattern = "*",
group = "AutoSave",
desc = "Immediately save a buffer"
})
api.nvim_create_autocmd(cnf.opts.trigger_events.defer_save, {
callback = function(opts)
defer_save(opts.buf)
end,
group = "AutoSave",
desc = "Save a buffer after the `debounce_delay`"
})
api.nvim_create_autocmd(cnf.opts.trigger_events.cancel_defered_save, {
callback = function (opts)
cancel_timer(opts.buf)
end,
group = "AutoSave",
desc = "Cancel a pending save timer for a buffer"
})
api.nvim_create_autocmd({ "VimEnter", "ColorScheme", "UIEnter" }, {
@@ -144,7 +157,6 @@ function M.on()
end
end)
end,
pattern = "*",
group = "AutoSave",
})