From 2c8790b0068262c958c824c571a61c86980cd985 Mon Sep 17 00:00:00 2001 From: kdav5758 Date: Thu, 1 Jul 2021 16:55:41 -0500 Subject: [PATCH] first commit --- .editorconfig | 21 +++++++ CHANGELOG.md | 7 +++ LICENSE => LICENSE.md | 0 doc/autosave.txt | 0 lua/autosave/config.lua | 36 ++++++++++++ lua/autosave/init.lua | 19 +++++++ lua/autosave/main.lua | 66 ++++++++++++++++++++++ lua/autosave/modules/autocmds.lua | 91 +++++++++++++++++++++++++++++++ lua/autosave/utils/viml_funcs.lua | 15 +++++ plugin/ascmds.vim | 22 ++++++++ research.txt | 5 ++ 11 files changed, 282 insertions(+) create mode 100644 .editorconfig create mode 100644 CHANGELOG.md rename LICENSE => LICENSE.md (100%) create mode 100644 doc/autosave.txt create mode 100644 lua/autosave/config.lua create mode 100644 lua/autosave/init.lua create mode 100644 lua/autosave/main.lua create mode 100644 lua/autosave/modules/autocmds.lua create mode 100644 lua/autosave/utils/viml_funcs.lua create mode 100644 plugin/ascmds.vim create mode 100644 research.txt diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..144c015 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# EditorConfig is awesome: https://EditorConfig.org + +root = true + + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = tabs +indent_size = 4 + +[*.txt] +indent_style = tab +indent_size = 4 + +[*.{diff,md}] +trim_trailing_whitespace = false diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e69f8fc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html) + diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/doc/autosave.txt b/doc/autosave.txt new file mode 100644 index 0000000..e69de29 diff --git a/lua/autosave/config.lua b/lua/autosave/config.lua new file mode 100644 index 0000000..1c692dd --- /dev/null +++ b/lua/autosave/config.lua @@ -0,0 +1,36 @@ +local config = {} + +-- + +config.options = { + enabled = true, + execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"), + events = {"InsertLeave", "TextChanged"}, + write_all_buffers = false, + on_off_commands = false, + save_only_if_exists = true, + excluded_filetypes = {}, +} + +function config.set_options(opts) + opts = opts or {} + + for opt, _ in pairs(opts) do + -- check if option exists in the config's table + if (config.options[opt] ~= nil) then -- not nil + -- chec if option is a table + if (type(opts[opt]) == "table") then -- if table + for inner_opt, _ in pairs(opts[opt]) do + -- table contains element by that key + if (config.options[opt][inner_opt] ~= nil) then -- not nil + config.options[opt][inner_opt] = opts[opt][inner_opt] + end + end + else + config.options[opt] = opts[opt] + end + end + end +end + +return config diff --git a/lua/autosave/init.lua b/lua/autosave/init.lua new file mode 100644 index 0000000..a6c9ea4 --- /dev/null +++ b/lua/autosave/init.lua @@ -0,0 +1,19 @@ + +local opts = require("autosave.config").options +local cmd = vim.cmd + +local M = {} + +local function setup_commands() + if (opts["on_off_commands"] == true) then + cmd([[command! ASOn lua require'autosave.main'.main('on')]]) + cmd([[command! ASOff lua require'autosave.main'.main('off')]]) + end +end + +function M.setup(custom_opts) + require("autosave.config").set_options(custom_opts) + setup_commands() +end + +return M diff --git a/lua/autosave/main.lua b/lua/autosave/main.lua new file mode 100644 index 0000000..5b3bf06 --- /dev/null +++ b/lua/autosave/main.lua @@ -0,0 +1,66 @@ +local cmd = vim.cmd + +local opts = require("autosave.config").options +local autocmds = require("autosave.modules.autocmds") +local autosave = require("autosave") + +local M = {} + + +local function set_status(value) + status_autosave = value +end + +local function get_status() + return status_autosave +end + +local function on() + + if (autosave.hook_before_on ~= nil) then + autosave.hook_before_on() + end + + autocmds.load_autocommands() + set_status('on') + + if (autosave.hook_after_on ~= nil) then + autosave.hook_after_on() + end +end + +local function off() + + if (autosave.hook_before_off ~= nil) then + autosave.hook_before_off() + end + + autocmds.unload_autocommands() + set_status('off') + + if (autosave.hook_after_off ~= nil) then + autosave.hook_after_off() + end +end + +function M.main(option) + option = option or 'load' + + if (option == 'toggle') then + if (get_status() == 'on') then + off() + else + on() + end + elseif (option == 'on') then + on() + elseif (option == 'off') then + off() + elseif (option == 'startup') then + if (opts["enabled"] == true) then + on() + end + end +end + +return M diff --git a/lua/autosave/modules/autocmds.lua b/lua/autosave/modules/autocmds.lua new file mode 100644 index 0000000..4e86d0a --- /dev/null +++ b/lua/autosave/modules/autocmds.lua @@ -0,0 +1,91 @@ +local opts = require("autosave.config").options + +local api = vim.api +local fn = vim.fn +local cmd = vim.cmd + +local M = {} + +local function table_has_value(tbl, value) + for key, value 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 do_save() + if (opts["save_only_if_exists"] == true) then + if (fn.filereadable(fn.expand("%:p")) == 1) then + if not (next(opts["excluded_filetypes"]) == nil) then + if not (table_has_value(opts["excluded_filetypes"], api.nvim_eval([[&filetype]]))) then + -- might use update, but in that case it can't be checekd if a file was modified and so it will always + -- print opts["execution_message"] + if (api.nvim_eval([[&modified]]) == 1) then + cmd("write") + if (get_modified() == nil) then set_modified(true) end + end + end + end + end + end +end + +local function save() + if (opts["write_all_buffers"] == true) then + cmd([[call g:AutoSaveBufDo("lua require'autosave.modules.autocmds'.do_save()")]]) + else + do_save() + end + + if (opts["execution_message"] ~= "" and get_modified() == true) then + print(opts["execution_message"]) + end +end + +local function parse_events() + local events = "" + + if (next(opts["events"]) == nil) then + events = "InsertLeave" + else + for event, _ in pairs(opts["events"]) do + events = events .. opts["events"][event] .. "," + end + end + + return events +end + +function M.load_autocommands() + api.nvim_exec( + [[ + augroup autosave_save + autocmd! + autocmd ]] .. + parse_events() .. [[ * execute "lua require'autosave.modules.autocmds'.save()" + augroup END + ]], + false + ) +end + +function M.unload_autocommands() + api.nvim_exec([[ + augroup autosave_save + autocmd! + augroup END + ]], false) +end + +return M diff --git a/lua/autosave/utils/viml_funcs.lua b/lua/autosave/utils/viml_funcs.lua new file mode 100644 index 0000000..2d8a6a8 --- /dev/null +++ b/lua/autosave/utils/viml_funcs.lua @@ -0,0 +1,15 @@ +local api = vim.api + +-- original source: https://vim.fandom.com/wiki/Run_a_command_in_multiple_buffers +-- like bufdo but restore the current buffer. +api.nvim_exec( + [[ + function! g:AutoSaveBufDo(command) + let currBuff=bufnr("%") + execute 'bufdo ' . a:command + execute 'buffer ' . currBuff + endfunction + com! -nargs=+ -complete=command Bufdo call BufDo() +]], + false +) diff --git a/plugin/ascmds.vim b/plugin/ascmds.vim new file mode 100644 index 0000000..d0aee2f --- /dev/null +++ b/plugin/ascmds.vim @@ -0,0 +1,22 @@ +" GPL-3.0 License + +" prevent the plugin from loading twice +if exists('g:loaded_autosave') | finish | endif + +let s:save_cpo = &cpo " save user coptions +set cpo&vim " reset them to defaults + +" main {{{ +lua require('autosave.main').main('startup') +" }}} + +" Interface {{{ +command! ASToggle lua require'autosave.main'.main('toggle') +" }}} + + +let &cpo = s:save_cpo " restore after +unlet s:save_cpo + +" set to true the var that controls the plugin's loading +let g:loaded_autosave = 1 diff --git a/research.txt b/research.txt new file mode 100644 index 0000000..06ecedb --- /dev/null +++ b/research.txt @@ -0,0 +1,5 @@ +This plugin is for automatically saving files. + + +it should only write if: + 1. buffer has been modified