BREAKING CHANGES: plugin rewrite

This commit is contained in:
Pocco81
2022-07-31 00:27:43 -05:00
parent 8df684bcb3
commit 0288839edd
18 changed files with 430 additions and 807 deletions
-7
View File
@@ -1,7 +0,0 @@
# 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)
+14
View File
@@ -0,0 +1,14 @@
SHELL:=/usr/bin/env bash
LOG_INFO=$(shell date +"%H:%M:%S") \e[0;34mINFO\e[0m
LOG_ERROR=$(shell date +"%H:%M:%S") \e[1;31mERROR\e[0m
LOG_WARNING=$(shell date +"%H:%M:%S") \e[0;33mWARNING\e[0m
LOG_SUCCESS=$(shell date +"%H:%M:%S") \e[0;32mSUCCESS\e[0m
GIT_ROOT=$(shell git rev-parse --show-toplevel)
.DEFAULT_GOAL := load
load:
@echo -e "$(LOG_INFO) Loading dev env..."
@echo -e "$(LOG_WARNING) Opening $(GIT_ROOT)"
nvim --cmd "set rtp+=$(GIT_ROOT)"
+89 -263
View File
@@ -1,306 +1,132 @@
<h1 align="center">🦴 AutoSave.nvim</h1>
<p align="center">
A NeoVim plugin for saving your work before the world collapses or you type :qa!
<h2 align="center">🧶 auto-save.nvim</h2>
</p>
<p align="center">
<a href="https://github.com/Pocco81/AutoSave.nvim/stargazers"
><img
src="https://img.shields.io/github/stars/Pocco81/AutoSave.nvim"
alt="Repository's starts"
/></a>
<a href="https://github.com/Pocco81/AutoSave.nvim/issues"
><img
src="https://img.shields.io/github/issues-raw/Pocco81/AutoSave.nvim"
alt="Issues"
/></a>
<a href="https://github.com/Pocco81/AutoSave.nvim/blob/main/LICENSE"
><img
src="https://img.shields.io/github/license/Pocco81/AutoSave.nvim"
alt="License"
/><br />
<a href="https://saythanks.io/to/Pocco81%40gmail.com"
><img
src="https://img.shields.io/badge/say-thanks-modal.svg"
alt="Say thanks"/></a
></a> <a href="https://github.com/Pocco81/whid.nvim/commits/main"
<a href="https://github.com/Pocco81/AutoSave.nvim/commits/main"
><img
src="https://img.shields.io/github/last-commit/Pocco81/AutoSave.nvim/dev"
alt="Latest commit"
/></a>
<a href="https://github.com/Pocco81/AutoSave.nvim"
><img
src="https://img.shields.io/github/repo-size/Pocco81/AutoSave.nvim"
alt="GitHub repository size"
/></a>
Automatically save your changes in NeoVim
</p>
<kbd><img src ="https://raw.githubusercontent.com/Pocco81/AutoSave.nvim/dev/resources/demo.gif"></kbd>
<p align="center">
Demo
</p><hr>
<a href="https://github.com/Pocco81/auto-save.nvim/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/Pocco81/auto-save.nvim?style=for-the-badge&logo=starship&color=C9CBFF&logoColor=D9E0EE&labelColor=302D41"></a>
<a href="https://github.com/Pocco81/auto-save.nvim/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/Pocco81/auto-save.nvim?style=for-the-badge&logo=bilibili&color=F5E0DC&logoColor=D9E0EE&labelColor=302D41"></a>
<a href="https://github.com/Pocco81/auto-save.nvim">
<img alt="Repo Size" src="https://img.shields.io/github/repo-size/Pocco81/auto-save.nvim?color=%23DDB6F2&label=SIZE&logo=codesandbox&style=for-the-badge&logoColor=D9E0EE&labelColor=302D41"/></a>
</p>
&nbsp;
# TL;DR
### 📋 Features
<div style="text-align: justify">
AutoSave.nvim is a NeoVim plugin written in Lua that aims to provide the simple functionality of automatically saving your work whenever you make changes to it. You can filter under which conditions which files are saved and when the auto-save functionality should be triggered (events). To get started simply install the plugin with your favorite plugin manager!
</div>
- automatically save your changes so the world doesn't collapse
- highly customizable:
- conditionals to assert whether to save or not
- execution message (it can be dimmed and personalized)
- events that trigger auto-save
- debounce the save with a delay
- multiple callbacks
- automatically clean the message area
# 🌲 Table of Contents
&nbsp;
* [Features](#-features)
* [Notices](#-notices)
* [Installation](#-installation)
* [Prerequisites](#prerequisites)
* [Adding the plugin](#adding-the-plugin)
* [Setup Configuration](#setup-configuration)
* [For init.lua](#for-initlua)
* [For init.vim](#for-initvim)
* [Updating](#updating)
* [Usage](#-usage)
* [Commands](#commands)
* [Default](#default)
* [Extra](#extra)
* [General](#general)
* [Configuration](#-configuration)
* [General](#general)
* [Conditions](#conditions)
* [Hooks](#hooks)
* [Recommendations](#recommendations)
* [Contribute](#-contribute)
* [Inspirations](#-inspirations)
* [License](#-license)
* [FAQ](#-faq)
* [To-Do](#-to-do)
### 📚 Requirements
# 🎁 Features
+ Automatically save current file(s).
+ Set conditions that files must meet to be saved (e.g. filetype, existence, ...).
+ Set events that will trigger the plugin.
+ Add custom hooks (e.g. print a message when the plugin is turned off).
+ Toggle the plugin on and off.
- Neovim >= 0.5.0
# 📺 Notices
Checkout the [CHANGELOG.md](https://github.com/Pocco81/AutoSave.nvim/blob/main/CHANGELOG.md) file for more information on the notices below:
&nbsp;
+ **15-07-21**: Implemented debounce_delay setting thanks to #7 and "Preserve cursor marks" feature when saving thanks to #8.
+ **04-07-21**: Fixed #1.
+ **01-07-21**: Just released!
### 📦 Installation
# 📦 Installation
## Prerequisites
- [NeoVim nightly](https://github.com/neovim/neovim/releases/tag/nightly) (>=v0.5.0)
## Adding the plugin
You can use your favorite plugin manager for this. Here are some examples with the most popular ones:
### Vim-plug
```lua
Plug 'Pocco81/AutoSave.nvim'
```
### Packer.nvim
```lua
use "Pocco81/AutoSave.nvim"
```
### Vundle
```lua
Plugin 'Pocco81/AutoSave.nvim'
```
### NeoBundle
```lua
NeoBundleFetch 'Pocco81/AutoSave.nvim'
```
## Setup (configuration)
As it's stated in the TL;DR, there are already some sane defaults that you may like, however you can change them to match your taste. These are the defaults:
```lua
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true,
},
write_all_buffers = false,
on_off_commands = false,
clean_command_line_interval = 0,
debounce_delay = 135
```
The way you setup the settings on your config varies on whether you are using vimL for this or Lua.
Install the plugin with your favourite package manager:
<details>
<summary>For init.lua</summary>
<p>
<summary><a href="https://github.com/wbthomason/packer.nvim">Packer.nvim</a></summary>
```lua
local autosave = require("autosave")
autosave.setup(
{
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true
},
write_all_buffers = false,
on_off_commands = true,
clean_command_line_interval = 0,
debounce_delay = 135
}
)
use({
"Pocco81/auto-save.nvim",
config = function()
require("auto-save").setup {
-- your config goes here
-- or just leave it empty :)
}
end,
})
```
<br />
</details>
<details>
<summary>For init.vim</summary>
<p>
<summary><a href="https://github.com/junegunn/vim-plug">vim-plug</a></summary>
```lua
```vim
Plug 'Pocco81/auto-save.nvim'
lua << EOF
local autosave = require("autosave")
autosave.setup(
{
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true
},
write_all_buffers = false,
on_off_commands = true,
clean_command_line_interval = 0,
debounce_delay = 135
}
)
require("auto-save").setup {
-- your config goes here
-- or just leave it empty :)
}
EOF
```
<br />
</details>
For instructions on how to configure the plugin, check out the [configuration](#configuration) section.
&nbsp;
## Updating
This depends on your plugin manager. If, for example, you are using Packer.nvim, you can update it with this command:
```lua
:PackerUpdate
```
### ⚙️ Configuration
# 🤖 Usage
## Commands
All the commands follow the *camel casing* naming convention and have the `AS` prefix so that it's easy to remember that they are part of this plugin. These are all of them:
### Default
+ `:ASToggle`: toggles AutoSave.nvim on and off.
### Extra
+ `:ASOn`: turns AutoSave.nvim on.
+ `:ASOff`: turns AutoSave.nvim off.
## General
+ `vim.g.autosave_state`: use this to check whether AutoSave is on (`true`) or off (`false`).
# 🐬 Configuration
Although settings already have self-explanatory names, here is where you can find info about each one of them and their classifications!
## General
+ `enabled:`: (Boolean) if true, enables AutoSave.nvim at startup (Note: this is not for loading the plugin it self but rather the "auto-save" functionality. This is like running `:ASOn`).
+ `execution_message`: (String) message to be displayed when saving [a] file[s].
+ `events`: (Table): events that will trigger the plugin.
+ `write_all_buffers`: (Boolean) if true, writes to all modifiable buffers that meet the `conditions`.
+ `on_off_commands`: (Boolean) if true, enables extra commands for toggling the plugin on and off (`:ASOn` and `:ASOff`).
+ `clean_command_line_interval` (Integer) if greater than 0, cleans the command line after *x* amount of milliseconds after printing the `execution_message`.
+ `debounce_delay` (Integer) if greater than 0, saves the file at most every `debounce_delay` milliseconds, vastly improving editing performance. If 0 then saves are performed immediately after `events` occur. It's recommend to leave the default value (`135`), which is just long enough to reduce unnecessary saves, but short enough that you don't notice the delay.
## Conditions
These are the conditions that every file must meet so that it can be saved. If every file to be auto-saved doesn't meet all of the conditions it won't be saved.
+ `exists`: (Boolean) if true, enables this condition. If the file doesn't exist it won't save it (e.g. if you `nvim stuff.txt` and don't save the file then this condition won't be met)
+ `modifiable`: (Boolean) if true, enables this condition. If the file isn't modifiable, then this condition isn't met.
+ `filename_is_not`: (Table, Strings) if there is one or more filenames (should be strings) in the table, it enables this condition. Use this to exclude filenames that you don't want to automatically save.
+ `filetype_is_not`: (Table, Strings) if there is one or more filetypes (should be strings) in the table, it enables this condition. Use this to exclude filetypes that you don't want to automatically save.
## Hooks
Use them to execute code at certain events [described by their names]. These are the ones available:
| Function | Description |
|----------------------|--------------------------------------------------------------------|
| hook_before_on() | Before toggling the plugin on |
| hook_after_on() | After toggling the plugin on |
| hook_before_off() | Before toggling the plugin off |
| hook_after_off() | After toggling the plugin off |
| hook_before_saving() | Before its even checked if the current file(s) meet the conditions |
| hook_after_saving | After saving the file(s) |
They can be used like so:
**auto-save** comes with the following defaults:
```lua
local autosave = require("autosave")
{
enabled = true, -- start auto-save when the plugin is loaded (i.e. when your package manager loads it)
execution_message = {
message = function() -- message to print on save
return ("AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"))
end,
dim = 0.18, -- dim the color of `message`
cleaning_interval = 4000, -- (milliseconds) automatically clean MsgArea after displaying `message`. See :h MsgArea
},
trigger_events = {"InsertLeave", "TextChanged"}, -- vim events that trigger auto-save. See :h events
-- 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
condition = function(buf)
local fn = vim.fn
local utils = require("auto-save.utils.data")
autosave.hook_after_off = function ()
print("I was toggled off!")
end
if
fn.getbufvar(buf, "&modifiable") == 1 or
utils.not_in(fn.getbufvar(buf, "&filetype"), {}) then
return true -- met condition(s), can save
end
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
callbacks = { -- functions to be executed at different intervals
enabling = nil, -- ran when enabling auto-save
disabling = nil, -- ran when disabling auto-save
before_asserting_save = nil, -- ran before checking `condition`
before_saving = nil, -- ran before doing the actual save
after_saving = nil -- ran after doing the actual save
}
}
```
## Recommendations
+ Many other plugins/stuff that you may use rely on using the same events as the ones AutoSave uses by default or may need to interact with the buffer before it's saved. Mainly being plugins for snippets support. If this is your case, consider increasing the `debounce_delay` setting to your needs.
Additionally you may want to set up a key mapping to toggle auto-save:
# 🙋 FAQ
```lua
vim.api.nvim_set_keymap("n", "<leader>n", ":ASToggle<CR>", {})
```
- Q: ***"How can I view the doc from NeoVim?"***
- A: Use `:help AutoSave.nvim`
&nbsp;
# 🫂 Contribute
### 🪴 Usage
Pull Requests are welcomed as long as they are properly justified and there are no conflicts. If your PR has something to do with the README or in general related with the documentation, I'll gladly merge it! Also, when writing code for the project **you must** use the [.editorconfig](https://github.com/Pocco81/AutoSave.nvim/blob/main/.editorconfig) file on your editor so as to "maintain consistent coding styles". For instructions on how to use this file refer to [EditorConfig's website](https://editorconfig.org/).
Besides running auto-save at startup (if you have `enabled = true` in your config), you may as well:
# 💭 Inspirations
- `ASToggle`: toggle auto-save
The following projects inspired the creation of AutoSave.nvim. If possible, go check them out to see why they are so amazing :]
- [907th/vim-auto-save](https://github.com/907th/vim-auto-save): Automatically save changes to disk in Vim.
# 📜 License
AutoSave.nvim is released under the GPL v3.0 license. It grants open-source permissions for users including:
- The right to download and run the software freely
- The right to make changes to the software as desired
- The right to redistribute copies of the software
- The right to modify and distribute copies of new versions of the software
For more convoluted language, see the [LICENSE file](https://github.com/Pocco81/AutoSave.nvim/blob/main/LICENSE.md).
# 📋 TO-DO
**High Priority**
+ None
**Low Priority**
+ None
<hr>
<p align="center">
Enjoy!
</p>
&nbsp;
-201
View File
@@ -1,201 +0,0 @@
*AutoSave.nvim* *AutoSave-help* A NeoVim plugin for saving your work before the world collapses or you type :qa!
Author: Pocco81 <https://github.com/Pocco81>
License: GPL-3.0 License
CONTENTS *truezen-contents*
TL;DR |autosave-tldr|
Installation |autosave-installation|
Prerequisites |autosave-prerequisites|
Adding the plugin |autosave-adding-the-plugin|
Setup Configuration |autosave-setup-configuration|
For init.lua |autosave-for-initlua|
For init.vim |autosave-for-initvim|
Updating |autosave-updating|
Features |autosave-features|
Usage (commands) |autosave-usage-commands|
Default |autosave-default|
Extra |autosave-extra|
Configuration |autosave-configuration|
General |autosave-general|
Conditions |autosave-conditions|
Hooks |autosave-hooks|
==============================================================================
# TL;DR *autosave-tldr*
AutoSave.nvim is a NeoVim plugin written in Lua that aims to provide the simple functionality of automatically saving your work whenever you make changes to it. You can filter under which conditions which files are saved and when the auto-save functionality should triggered (events). To get started simply install the plugin with your favorite plugin manager!
# Installation *autosave-installation*
## Prerequisites *autosave-prerequisites*
- [NeoVim nightly](https://github.com/neovim/neovim/releases/tag/nightly) (>=v0.5.0)
## Adding the plugin *AutoSave-adding-the-plugin*
You can use your favorite plugin manager for this. Here are some examples with the most popular ones:
### Vim-plug
```lua
Plug 'Pocco81/AutoSave.nvim'
```
### Packer.nvim
```lua
use "Pocco81/AutoSave.nvim"
```
### Vundle
```lua
Plugin 'Pocco81/AutoSave.nvim'
```
### NeoBundle
```lua
NeoBundleFetch 'Pocco81/AutoSave.nvim'
```
## Setup (configuration) *AutoSave-setup-configuration*
As it's stated in the TL;DR, there are already some sane defaults that you may like, however you can change them to match your taste. These are the defaults:
```lua
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true,
},
write_all_buffers = false,
on_off_commands = false,
clean_command_line_interval = 0
debounce_delay = 135
```
The way you setup the settings on your config varies on whether you are using vimL for this or Lua.
For init.lua *AutoSave-for-initlua*
```lua
local autosave = require("autosave")
autosave.setup(
{
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true
},
write_all_buffers = false,
on_off_commands = true,
clean_command_line_interval = 0
debounce_delay = 135
}
)
```
For init.vim *AutoSave-for-initvim*
```lua
lua << EOF
local autosave = require("autosave")
autosave.setup(
{
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true
},
write_all_buffers = false,
on_off_commands = true,
clean_command_line_interval = 0
debounce_delay = 135
}
)
EOF
```
<br />
</details>
For instructions on how to configure the plugin, check out the [configuration](#configuration) section.
## Updating *autosave-updating*
This depends on your plugin manager. If, for example, you are using Packer.nvim, you can update it with this command:
```lua
:PackerUpdate
```
# Usage (commands) *autosave-usage-commands*
All the commands follow the *camel casing* naming convention and have the `AS` prefix so that it's easy to remember that they are part of this plugin. These are all of them:
## Default
+ `:ASToggle`: toggles AutoSave.nvim on and off.
## Extra
+ `:ASOn`: turns AutoSave.nvim on.
+ `:ASOff`: turns AutoSave.nvim off.
# Configuration *autosave-configuration*
Although settings already have self-explanatory names, here is where you can find info about each one of them and their classifications!
## General
+ `enabled:`: (Boolean) if true, enables AutoSave.nvim at startup (Note: this is not for loading the plugin it self but rather the "auto-save" functionality. This is like running `:ASOn`).
+ `execution_message`: (String) message to be displayed when saving [a] file[s]. If the string is empty, no message will be displayed.
+ `events`: (Table): events that will trigger the plugin.
+ `write_all_buffers`: (Boolean) if true, writes to all modifiable buffers that meet the `conditions`.
+ `on_off_commands`: (Boolean) if true, enables extra commands for toggling the plugin on and off (`:ASOn` and `:ASOff`).
+ `clean_command_line_interval` (Integer) if greater than 0, cleans the command line after *x* amount of milliseconds after printing the `execution_message`.
+ `debounce_delay` (Integer) if greater than 0, saves the file at most every `debounce_delay` milliseconds, vastly improving editing performance. If 0 then saves are performed immediately after `events` occur. It's recommend to leave the default value (`135`), which is just long enough to reduce unnecessary saves, but short enough that you don't notice the delay.
## Conditions
These are the conditions that every file must meet so that it can be saved. If every file to be auto-saved doesn't meet all of the conditions it won't be saved.
+ `exists`: (Boolean) if true, enables this condition. If the file doesn't exist it won't save it (e.g. if you `nvim stuff.txt` and don't save the file then this condition won't be met)
+ `modifiable`: (Boolean) if true, enables this condition. If the file isn't modifiable, then this condition isn't met.
+ `filename_is_not`: (Table, Strings) if there is one or more filenames (should be strings) in the table, it enables this condition. Use this to exclude filenames that you don't want to automatically save.
+ `filetype_is_not`: (Table, Strings) if there is one or more filetypes (should be strings) in the table, it enables this condition. Use this to exclude filetypes that you don't want to automatically save.
## Hooks
Use them to execute code at certain events [described by their names]. These are the ones available:
| Function | Description |
|----------------------|----------------------------------------------------------------------|
| hook_before_on() | Before toggling the plugin on |
| hook_after_on() | After toggling the plugin on |
| hook_before_off() | Before toggling the plugin off |
| hook_after_off() | After toggling the plugin off |
| hook_before_saving() | Before its even checked if the file meets the conditions to be saved |
| hook_after_saving | After successfully saving the file or not |
They can be used like so:
```lua
local autosave = require("autosave")
autosave.hook_after_off = function ()
print("I was toggled off!")
end
```
# License *AutoSave-license*
AutoSave.nvim is released under the GPL v3.0 license. It grants open-source permissions for users including:
- The right to download and run the software freely
- The right to make changes to the software as desired
- The right to redistribute copies of the software
- The right to modify and distribute copies of new versions of the software
For more convoluted language, see the [LICENSE file](https://github.com/Pocco81/AutoSave.nvim/blob/main/README.md).
+43
View File
@@ -0,0 +1,43 @@
local config = {}
config.options = {
enabled = true, -- start auto-save when the plugin is loaded (i.e. when your package manager loads it)
execution_message = {
message = function() -- message to print on save
return ("AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"))
end,
dim = 0.18, -- dim the color of `message`
cleaning_interval = 4000, -- (milliseconds) automatically clean MsgArea after displaying `message`. See :h MsgArea
},
trigger_events = {"InsertLeave", "TextChanged"}, -- vim events that trigger auto-save. See :h events
-- 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
condition = function(buf)
local fn = vim.fn
local utils = require("auto-save.utils.data")
if
fn.getbufvar(buf, "&modifiable") == 1 or
utils.not_in(fn.getbufvar(buf, "&filetype"), {}) then
return true -- met condition(s), can save
end
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
callbacks = { -- functions to be executed at different intervals
enabling = nil, -- ran when enabling auto-save
disabling = nil, -- ran when disabling auto-save
before_asserting_save = nil, -- ran before checking `condition`
before_saving = nil, -- ran before doing the actual save
after_saving = nil -- ran after doing the actual save
}
}
function config.set_options(opts)
opts = opts or {}
config.options = vim.tbl_deep_extend("keep", opts, config.options)
end
return config
+149
View File
@@ -0,0 +1,149 @@
local M = {}
local cnf = require("auto-save.config").options
local callback = require("auto-save.utils.data").do_callback
local colors = require("auto-save.utils.colors")
local echo = require("auto-save.utils.echo")
local autosave_running
local api = vim.api
local g = vim.g
local fn = vim.fn
local cmd = vim.cmd
local o = vim.o
api.nvim_create_augroup("AutoSave", {
clear = true,
})
local global_vars = {}
local function set_buf_var(buf, name, value)
if buf == nil then
global_vars[name] = value
else
api.nvim_buf_set_var(buf, 'autosave_' .. name, value)
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
end
return inner_debounce
end
function M.save(buf)
buf = buf or api.nvim_get_current_buf()
callback("before_asserting_save")
if cnf.condition(buf) == false then
return
end
if not api.nvim_buf_get_option(buf, 'modified') then
return
end
callback("before_saving")
if g.auto_save_abort == true then
return
end
if cnf.write_all_buffers then
cmd("silent! wall")
else
api.nvim_buf_call(buf, function () cmd("silent! write") end)
end
callback("after_saving")
api.nvim_echo({ { (type(cnf.execution_message.message) == "function" and cnf.execution_message.message() or cnf.execution_message.message), 'AutoSaveText' } }, true, {})
if cnf.execution_message.cleaning_interval > 0 then
fn.timer_start(
cnf.execution_message.cleaning_interval,
function()
cmd([[echon '']])
end
)
end
end
local save_func = (cnf.debounce_delay > 0 and debounce(M.save, cnf.debounce_delay) or M.save)
local function perform_save()
g.auto_save_abort = false
save_func()
end
function M.on()
api.nvim_create_autocmd(cnf.trigger_events, {
callback = function()
perform_save()
end,
pattern = "*",
group = "AutoSave",
})
api.nvim_create_autocmd("VimEnter", {
callback = function()
if cnf.execution_message.dim > 0 then
MSG_AREA = colors.get_hl("MsgArea")
MSG_AREA.background = (MSG_AREA.background or colors.get_hl("Normal")["background"])
local foreground = (
o.background == "dark" and
colors.darken((MSG_AREA.background or "#000000"), cnf.execution_message.dim, MSG_AREA.foreground) or
colors.lighten((MSG_AREA.background or "#ffffff"), cnf.execution_message.dim, MSG_AREA.foreground)
)
colors.highlight("AutoSaveText", { fg = foreground })
end
end,
once = true,
group = "AutoSave",
})
callback("enabling")
autosave_running = true
end
function M.off()
api.nvim_create_augroup("AutoSave", {
clear = true,
})
callback("disabling")
autosave_running = false
end
function M.toggle()
if autosave_running then
M.off()
else
M.on()
end
end
function M.setup(custom_opts)
require("auto-save.config").set_options(custom_opts)
end
return M
+70
View File
@@ -0,0 +1,70 @@
local M = {}
---@param hex_str string hexadecimal value of a color
local hex_to_rgb = function(hex_str)
local hex = "[abcdef0-9][abcdef0-9]"
local pat = "^#(" .. hex .. ")(" .. hex .. ")(" .. hex .. ")$"
hex_str = string.lower(hex_str)
assert(string.find(hex_str, pat) ~= nil, "hex_to_rgb: invalid hex_str: " .. tostring(hex_str))
local red, green, blue = string.match(hex_str, pat)
return { tonumber(red, 16), tonumber(green, 16), tonumber(blue, 16) }
end
function M.highlight(group, color, force)
if color.link then
vim.api.nvim_set_hl(0, group, {
link = color.link,
})
else
if color.style then
for _, style in ipairs(color.style) do
color[style] = true
end
end
color.style = nil
if force then
vim.cmd("hi " .. group .. " guifg=" .. (color.fg or "NONE") .. " guibg=" .. (color.bg or "NONE"))
return
end
vim.api.nvim_set_hl(0, group, color)
end
end
function M.get_hl(name)
local ok, hl = pcall(vim.api.nvim_get_hl_by_name, name, true)
if not ok then
return
end
for _, key in pairs({ "foreground", "background", "special" }) do
if hl[key] then
hl[key] = string.format("#%06x", hl[key])
end
end
return hl
end
---@param fg string forecrust color
---@param bg string background color
---@param alpha number number between 0 and 1. 0 results in bg, 1 results in fg
function M.blend(fg, bg, alpha)
bg = hex_to_rgb(bg)
fg = hex_to_rgb(fg)
local blendChannel = function(i)
local ret = (alpha * fg[i] + ((1 - alpha) * bg[i]))
return math.floor(math.min(math.max(0, ret), 255) + 0.5)
end
return string.format("#%02X%02X%02X", blendChannel(1), blendChannel(2), blendChannel(3))
end
function M.darken(hex, amount, bg)
return M.blend(hex, bg or M.bg, math.abs(amount))
end
function M.lighten(hex, amount, fg)
return M.blend(hex, fg or M.fg, math.abs(amount))
end
return M
+25
View File
@@ -0,0 +1,25 @@
local M = {}
local cnf = require("auto-save.config").options
function M.set_of(list)
local set = {}
for i = 1, #list do
set[list[i]] = true
end
return set
end
function M.not_in(var, arr)
if M.set_of(arr)[var] == nil then
return true
end
end
function M.do_callback(callback_name)
if type(cnf.callbacks[callback_name]) == "function" then
cnf.callbacks[callback_name]()
end
end
return M
+25
View File
@@ -0,0 +1,25 @@
local TITLE = "auto-save"
return function(msg, kind)
local has_notify_plugin = pcall(require, "notify")
local level = {}
if kind == "error" then
level.log = vim.log.levels.ERROR
level.type = "error"
elseif kind == "warn" then
level.log = vim.log.levels.WARN
level.type = "error"
else
level.log = kind or vim.log.levels.INFO
level.type = "info"
end
if has_notify_plugin then
vim.notify(msg, level.log, {
title = TITLE,
})
else
vim.notify(("%s (%s): %s"):format(TITLE, level.type, msg), level.log)
end
end
-29
View File
@@ -1,29 +0,0 @@
local config = {}
config.options = {
enabled = true,
execution_message = "AutoSave: saved at " .. vim.fn.strftime("%H:%M:%S"),
events = {"InsertLeave", "TextChanged"},
conditions = {
exists = true,
filename_is_not = {},
filetype_is_not = {},
modifiable = true,
},
write_all_buffers = false,
on_off_commands = false,
clean_command_line_interval = 0,
debounce_delay = 135
}
function config.set_options(opts)
opts = opts or {}
for opt, _ in pairs(opts) do
if (config.options[opt] ~= nil) then -- not nil
config.options[opt] = opts[opt]
end
end
end
return config
-28
View File
@@ -1,28 +0,0 @@
local opts = require("autosave.config").options
local cmd = vim.cmd
local M = {}
local function setup_load()
if opts["enabled"] == true then
vim.g.autosave_state = true
require("autosave.main").main("on")
else
vim.g.autosave_state = false
end
end
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_load()
setup_commands()
end
return M
-51
View File
@@ -1,51 +0,0 @@
local autocmds = require("autosave.modules.autocmds")
local autosave = require("autosave")
local g = vim.g
local M = {}
require("autosave.utils.viml_funcs")
local function on()
if (autosave.hook_before_on ~= nil) then
autosave.hook_before_on()
end
autocmds.load_autocommands()
g.autosave_state = true
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()
g.autosave_state = false
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 (g.autosave_state == true) then
off()
else
on()
end
elseif (option == 'on') then
on()
elseif (option == 'off') then
off()
end
end
return M
-192
View File
@@ -1,192 +0,0 @@
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
-12
View File
@@ -1,12 +0,0 @@
local api = vim.api
api.nvim_exec(
[[
function! g:AutoSaveClearCommandLine(timer)
if mode() != 'c'
echon ''
endif
endfunction
]],
false
)
-19
View File
@@ -1,19 +0,0 @@
" 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
" 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
+15
View File
@@ -0,0 +1,15 @@
if vim.g.loaded_auto_save then
return
end
vim.g.loaded_auto_save = true
local command = vim.api.nvim_create_user_command
local cnf = require("auto-save.config").options
command("AToggle", function()
require("auto-save").toggle()
end, {})
if cnf.enabled then
require("auto-save").on()
end
-5
View File
@@ -1,5 +0,0 @@
This plugin is for automatically saving files.
it should only write if:
1. buffer has been modified
Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB