Skip to content

more flexibility for autocmd control #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## guard.nvim

Async formatting and linting utility for neovim.
Async formatting and linting utility for neovim.

## Features

Expand Down Expand Up @@ -49,12 +49,9 @@ require('guard').setup({
})
```

Use `GuardFmt` to manually call format, use `GuardDisable` to diable auto format. and you can create
a keymap like

```lua
vim.keymap.set({'n','v'}, '<cmd>GuardFmt<CR>')
```
- Use `GuardFmt` to manually call format, when there is a visual selection only the selection is formatted.
- `GuardDisable` disables auto format for the current buffer, you can also `GuardDisable lua` or `GuardDisable 16` (the buffer number)
- Use `GuardEnable` to re-enable auto format, usage is the same as `GuardDisable`

### Builtin tools

Expand All @@ -64,6 +61,7 @@ vim.keymap.set({'n','v'}, '<cmd>GuardFmt<CR>')
- `clang-format`
- `prettier`
- `rustfmt`
- `fnlfmt`
- `stylua`
- `golines`
- `black`
Expand All @@ -74,16 +72,17 @@ Table format for custom tool:

```
{
cmd --string tool command
args --table command arugments
fname --string insert filename to args tail
stdin --boolean pass buffer contents into stdin
timeout --integer
ignore_pattern --table ignore run format when pattern match
ignore_error --when has lsp error ignore format
cmd -- string: tool command
args -- table: command arugments
fname -- string: insert filename to args tail
stdin -- boolean: pass buffer contents into stdin
timeout -- integer
ignore_pattern -- table: ignore run format when pattern match
ignore_error -- boolean: when has lsp error ignore format
find -- string: format if the file is found in the lsp root dir

--special
fn --function if fn is set other field will not take effect
fn -- function: if fn is set other field will not take effect
}
```

Expand All @@ -95,6 +94,6 @@ Table format for custom tool:

## Troubleshooting

if guard does not auto format on save, run `checkhealth` first.
If guard does not auto format on save, run `checkhealth` first.

## License MIT
3 changes: 2 additions & 1 deletion doc/guard.nvim.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*guard.nvim.txt* For NVIM v0.8.0 Last change: 2023 July 28
*guard.nvim.txt* For NVIM v0.8.0 Last change: 2023 August 03

==============================================================================
Table of Contents *guard.nvim-table-of-contents*
Expand Down Expand Up @@ -82,6 +82,7 @@ FORMATTER
- `clang-format`
- `prettier`
- `rustfmt`
- `fnlfmt`
- `stylua`
- `golines`
- `black`
Expand Down
70 changes: 70 additions & 0 deletions lua/guard/api.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
local api = vim.api
local ft_handler = require('guard.filetype')
local events = require('guard.events')
local format = require('guard.format')

local function disable(opts)
if #opts.fargs == 0 then
local current = api.nvim_get_autocmds({ group = 'Guard', event = 'BufWritePre', buffer = api.nvim_get_current_buf() })
if #current ~= 0 then
api.nvim_del_autocmd(current[1].id)
end
return
end
local arg = opts.args
local bufnr = tonumber(arg)
if bufnr then
local bufau = api.nvim_get_autocmds({ group = 'Guard', event = 'BufWritePre', buffer = bufnr })
if #bufau ~= 0 then
api.nvim_del_autocmd(bufau[1].id)
end
else
local listener = api.nvim_get_autocmds({ group = 'Guard', event = 'FileType', pattern = arg })
if #listener ~= 0 then
api.nvim_del_autocmd(listener[1].id)
end
local bufaus = api.nvim_get_autocmds({ group = 'Guard', event = 'BufWritePre' })
for _, au in ipairs(bufaus) do
if vim.bo[au.buffer].ft == arg then
api.nvim_del_autocmd(au.id)
end
end
end
end

local function enable(opts)
if #opts.fargs == 0 then
local bufnr = api.nvim_get_current_buf()
local current = api.nvim_get_autocmds({ group = 'Guard', event = 'BufWritePre', buffer = bufnr })
if #current == 0 then
format.attach_to_buf(bufnr)
end
return
end
local arg = opts.args
local bufnr = tonumber(arg)
if bufnr then
local bufau = api.nvim_get_autocmds({ group = 'Guard', event = 'BufWritePre', buffer = bufnr })
if #bufau == 0 then
format.attach_to_buf(bufnr)
end
else
if not vim.tbl_contains(vim.tbl_keys(ft_handler), arg) then
return
end
local listener = api.nvim_get_autocmds({ group = 'Guard', event = 'FileType', pattern = arg })
if #listener == 0 then
events.watch_ft(arg)
end
for _, buf in ipairs(api.nvim_list_bufs()) do
if vim.bo[buf].ft == arg then
format.attach_to_buf(buf)
end
end
end
end

return {
disable = disable,
enable = enable,
}
49 changes: 49 additions & 0 deletions lua/guard/events.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
local api = vim.api
local group = api.nvim_create_augroup('Guard', { clear = true })
local ft_handler = require('guard.filetype')
local format = require('guard.format')

local function watch_ft(fts)
api.nvim_create_autocmd('FileType', {
group = group,
pattern = fts,
callback = function(args)
format.attach_to_buf(args.buf)
end,
desc = 'guard',
})
end

local function create_lspattach_autocmd(fmt_on_save)
api.nvim_create_autocmd('LspAttach', {
group = group,
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
---@diagnostic disable-next-line: need-check-nil
if not client.supports_method('textDocument/formatting') then
return
end
local ft = vim.bo[args.buf].filetype
if not(ft_handler[ft] and ft_handler[ft].format) then
ft_handler(ft):fmt('lsp')
end

if
fmt_on_save
and #api.nvim_get_autocmds({
group = group,
event = 'FileType',
pattern = ft,
})
== 0
then
format.attach_to_buf(args.buf)
end
end,
})
end

return {
watch_ft = watch_ft,
create_lspattach_autocmd = create_lspattach_autocmd,
}
17 changes: 14 additions & 3 deletions lua/guard/format.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ local api = vim.api
---@diagnostic disable-next-line: deprecated
local uv = vim.version().minor >= 10 and vim.uv or vim.loop
local spawn = require('guard.spawn').try_spawn
local get_prev_lines = require('guard.util').get_prev_lines
local util = require('guard.util')
local get_prev_lines = util.get_prev_lines
local filetype = require('guard.filetype')
local formatter = require('guard.tools.formatter')
local util = require('guard.util')

local function ignored(buf, patterns)
local fname = api.nvim_buf_get_name(buf)
Expand Down Expand Up @@ -110,7 +110,7 @@ local function do_fmt(buf)
end

local can_run = true
if config.ignore_patterns and ignored(buf, configs.ignore_patterns) then
if config.ignore_patterns and ignored(buf, config.ignore_patterns) then
can_run = false
elseif config.ignore_error and #vim.diagnostic.get(buf, { severity = 1 }) ~= 0 then
can_run = false
Expand Down Expand Up @@ -154,6 +154,17 @@ local function do_fmt(buf)
end))
end

local function attach_to_buf(buf)
api.nvim_create_autocmd('BufWritePre', {
group = 'Guard',
buffer = buf,
callback = function(opt)
require('guard.format').do_fmt(opt.buf)
end,
})
end

return {
do_fmt = do_fmt,
attach_to_buf = attach_to_buf,
}
77 changes: 12 additions & 65 deletions lua/guard/init.lua
Original file line number Diff line number Diff line change
@@ -1,37 +1,11 @@
local api = vim.api
local group = api.nvim_create_augroup('Guard', { clear = true })
local fts_config = require('guard.filetype')
local util = require('guard.util')
local ft_handler = require('guard.filetype')
local events = require('guard.events')

local function fmt_event(buf)
api.nvim_create_autocmd('BufWritePre', {
group = group,
buffer = buf,
callback = function(opt)
require('guard.format').do_fmt(opt.buf)
end,
})
end

local function register_event(fts)
api.nvim_create_autocmd('FileType', {
group = group,
pattern = fts,
callback = function(args)
fmt_event(args.buf)
end,
desc = 'guard',
})

api.nvim_create_user_command('GuardDisable', function()
pcall(api.nvim_del_augroup_by_id, group)
end, {})
end

local function parse_setup_cfg(fts_with_cfg)
local function register_cfg_by_table(fts_with_cfg)
for ft, cfg in pairs(fts_with_cfg or {}) do
if not vim.tbl_isempty(cfg) then
local handler = fts_config(ft)
local handler = ft_handler(ft)
local keys = vim.tbl_keys(cfg)
vim.tbl_map(function(key)
handler:register(key, util.as_table(cfg[key]))
Expand All @@ -40,16 +14,17 @@ local function parse_setup_cfg(fts_with_cfg)
end
end

local function get_fts_keys()
local keys = vim.tbl_keys(fts_config)
local function resolve_multi_ft()
local keys = vim.tbl_keys(ft_handler)
local retval = {}
vim.tbl_map(function(key)
if key:find(',') then
local t = vim.split(key, ',')
for _, item in ipairs(t) do
fts_config[item] = vim.deepcopy(fts_config[key])
ft_handler[item] = vim.deepcopy(ft_handler[key])
retval[#retval + 1] = item
end
ft_handler[key] = nil
else
retval[#retval + 1] = key
end
Expand All @@ -63,45 +38,17 @@ local function setup(opt)
lsp_as_default_formatter = false,
}

parse_setup_cfg(opt.ft)
local fts = get_fts_keys()
register_cfg_by_table(opt.ft)

if opt.fmt_on_save then
register_event(fts)
events.watch_ft(resolve_multi_ft())
end

if opt.lsp_as_default_formatter then
api.nvim_create_autocmd('LspAttach', {
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
---@diagnostic disable-next-line: need-check-nil
if not client.supports_method('textDocument/formatting') then
return
end
local fthandler = require('guard.filetype')
if fthandler[vim.bo[args.buf].filetype] and fthandler[vim.bo[args.buf].filetype].format then
table.insert(fthandler[vim.bo[args.buf].filetype].format, 1, 'lsp')
else
fthandler(vim.bo[args.buf].filetype):fmt('lsp')
end

if
opt.fmt_on_save
and #api.nvim_get_autocmds({
group = 'Guard',
event = 'FileType',
pattern = vim.bo[args.buf].filetype,
})
== 0
then
fmt_event(args.buf)
end
end,
})
events.create_lspattach_autocmd(opt.fmt_on_save)
end

local lint = require('guard.lint')
for ft, conf in pairs(fts_config) do
for ft, conf in pairs(ft_handler) do
if conf.linter then
for i, entry in ipairs(conf.linter) do
if type(entry) == 'string' then
Expand Down
6 changes: 6 additions & 0 deletions lua/guard/tools/formatter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ M.black = {
stdin = true,
}

M.fnlfmt = {
cmd = 'fnlfmt',
args = { '-' },
stdin = true,
}

M.mixformat = {
cmd = 'mix',
args = {'format', '-', '--stdin-filename'},
Expand Down
9 changes: 7 additions & 2 deletions plugin/guard.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ if loaded then
return
end
loaded = true

vim.api.nvim_create_user_command('GuardDisable', function(opts)
require('guard.api').disable(opts)
end, { nargs = '?' })
vim.api.nvim_create_user_command('GuardEnable', function(opts)
require('guard.api').enable(opts)
end, { nargs = '?' })
vim.api.nvim_create_user_command('GuardFmt', function()
require('guard.format').do_fmt()
end, {})
end, { nargs = 0 })