Skip to content

Commit 8d0c023

Browse files
committed
refactor: make executable check async
executable is sync version when one of formatter is not executable it will cause nvim block, make executable check async and move to FileType callback we don't need check all when config. just lazied check when need.
1 parent 612b1a7 commit 8d0c023

File tree

2 files changed

+50
-19
lines changed

2 files changed

+50
-19
lines changed

lua/guard/events.lua

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,22 +175,48 @@ end
175175
---@param ft string
176176
---@param formatters FmtConfig[]
177177
function M.fmt_on_filetype(ft, formatters)
178-
-- check if all cmds executable before registering formatter
179-
iter(formatters):any(function(config)
180-
if type(config) == 'table' and config.cmd and vim.fn.executable(config.cmd) ~= 1 then
181-
report_error(config.cmd .. ' not executable')
182-
return false
183-
end
184-
return true
185-
end)
178+
-- safely check do we need?
179+
if #formatters == 0 then
180+
return
181+
end
186182

187183
au('FileType', {
188184
group = M.group,
189185
pattern = ft,
190186
callback = function(args)
191-
M.try_attach_fmt_to_buf(args.buf)
187+
coroutine.resume(coroutine.create(function()
188+
local co = assert(coroutine.running())
189+
local it = iter(formatters)
190+
local ok = true
191+
while true do
192+
local config = it:next()
193+
if not config then
194+
break
195+
end
196+
if type(config) == 'table' and config.cmd then
197+
vim.uv.fs_stat(vim.fn.exepath(config.cmd), function(err, stat)
198+
if err or not stat or stat.type ~= 'file' then
199+
ok = false
200+
end
201+
coroutine.resume(co)
202+
end)
203+
coroutine.yield()
204+
if not ok then
205+
vim.schedule(function()
206+
report_error(('%s not executable'):format(config.cmd))
207+
api.nvim_del_autocmd(args.id)
208+
end)
209+
return
210+
end
211+
end
212+
end
213+
214+
vim.schedule(function()
215+
M.try_attach_fmt_to_buf(args.buf)
216+
end)
217+
end))
192218
end,
193-
desc = 'guard',
219+
desc = '[Guard] register BufWritePre for auto format when save',
194220
})
195221
end
196222

lua/guard/format.lua

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ local function fail(msg)
5151
vim.notify('[Guard]: ' .. msg, vim.log.levels.WARN)
5252
end
5353

54+
--- Error handler
55+
---@param errno table
56+
local function err_handler(errno)
57+
if errno.reason:match('exited with errors$') then
58+
fail(('%s exited with code %d\n%s'):format(errno.cmd, errno.code, errno.stderr))
59+
elseif errno.reason == 'buf changed' then
60+
fail('buffer changed during formatting')
61+
else
62+
fail(errno.reason)
63+
end
64+
end
65+
5466
local function do_fmt(buf)
5567
buf = buf or api.nvim_get_current_buf()
5668
local ft_conf = filetype[vim.bo[buf].filetype]
@@ -169,18 +181,11 @@ local function do_fmt(buf)
169181
vim.schedule(function()
170182
-- handle errors
171183
if errno then
172-
if errno.reason:match('exited with errors$') then
173-
fail(('%s exited with code %d\n%s'):format(errno.cmd, errno.code, errno.stderr))
174-
elseif errno.reason == 'buf changed' then
175-
fail('buffer changed during formatting')
176-
else
177-
fail(errno.reason)
178-
end
179-
return
184+
return err_handler(errno)
180185
end
181186
-- check buffer one last time
182187
if api.nvim_buf_get_changedtick(buf) ~= changedtick then
183-
fail('buffer changed during formatting')
188+
return fail('buffer changed during formatting')
184189
end
185190
if not api.nvim_buf_is_valid(buf) then
186191
fail('buffer no longer valid')

0 commit comments

Comments
 (0)