Files
auto-save.nvim/lua/autosave/modules/autocmds.lua
2021-09-23 12:44:11 +09:00

193 lines
3.9 KiB
Lua

local api = vim.api
local fn = vim.fn
local cmd = vim.cmd
local opts = require("autosave.config").options
local autosave = require("autosave")
local default_events = { "InsertLeave", "TextChanged" }
local modified
local M = {}
local function table_has_value(tbl, value)
for key, _ in pairs(tbl) do
if tbl[key] == value then
return true
end
end
return false
end
local function set_modified(value)
modified = value
end
local function get_modified()
return modified
end
local function actual_save()
-- might use update, but in that case it can't be checked if a file was modified and so it will always
-- print opts["execution_message"]
if api.nvim_eval([[&modified]]) == 1 then
local first_char_pos = fn.getpos("'[")
local last_char_pos = fn.getpos("']")
if opts["write_all_buffers"] then
cmd("silent! wall")
else
cmd("silent! write")
end
fn.setpos("'[", first_char_pos)
fn.setpos("']", last_char_pos)
if get_modified() == nil or get_modified() == false then
set_modified(true)
end
M.message_and_interval()
end
end
local function assert_user_conditions()
local sc_exists, sc_filename, sc_filetype, sc_modifiable = true, true, true, true
for condition, value in pairs(opts["conditions"]) do
if condition == "exists" then
if value == true then
if fn.filereadable(fn.expand("%:p")) == 0 then
sc_exists = false
break
end
end
elseif condition == "modifiable" then
if value == true then
if api.nvim_eval([[&modifiable]]) == 0 then
sc_modifiable = false
break
end
end
elseif condition == "filename_is_not" then
if not (next(opts["conditions"]["filename_is_not"]) == nil) then
if table_has_value(opts["conditions"]["filename_is_not"], vim.fn.expand('%:t')) == true then
sc_filename = false
break
end
end
elseif condition == "filetype_is_not" then
if not (next(opts["conditions"]["filetype_is_not"]) == nil) then
if table_has_value(opts["conditions"]["filetype_is_not"], api.nvim_eval([[&filetype]])) == true then
sc_filetype = false
break
end
end
end
end
return { sc_exists, sc_filename, sc_filetype, sc_modifiable }
end
local function assert_return(values, expected)
for key, value in pairs(values) do
if value ~= expected then
return false
end
end
return true
end
function M.message_and_interval()
if get_modified() == true then
set_modified(false)
if opts["execution_message"] ~= "" then
print(opts["execution_message"])
end
if opts["clean_command_line_interval"] > 0 then
cmd(
[[call timer_start(]]
.. opts["clean_command_line_interval"]
.. [[, funcref('g:AutoSaveClearCommandLine'))]]
)
end
end
end
local function debounce(lfn, duration)
local queued = false
local function inner_debounce()
if not queued then
vim.defer_fn(function()
queued = false
lfn()
end, duration)
queued = true
end
end
return inner_debounce
end
function M.do_save()
if assert_return(assert_user_conditions(), true) then
M.debounced_save()
end
end
function M.save()
if autosave.hook_before_saving ~= nil then
autosave.hook_before_saving()
end
M.do_save()
if autosave.hook_after_saving ~= nil then
autosave.hook_after_saving()
end
end
local function get_events()
if next(opts["events"]) == nil or opts["events"] == nil then
return default_events
else
return opts["events"]
end
end
local function parse_events()
return table.concat(get_events(), ",")
end
function M.load_autocommands()
if opts["debounce_delay"] == 0 then
M.debounced_save = actual_save
else
M.debounced_save = debounce(actual_save, opts["debounce_delay"])
end
api.nvim_exec([[
aug autosave_save
au!
au ]] .. parse_events() .. [[ * execute "lua require'autosave.modules.autocmds'.save()"
aug END
]], false)
end
function M.unload_autocommands()
api.nvim_exec(
[[
aug autosave_save
au!
aug END
]],
false
)
end
return M