diff options
author | Steven Arcangeli <stevearc@stevearc.com> | 2023-09-29 11:35:00 -0700 |
---|---|---|
committer | Steven Arcangeli <stevearc@stevearc.com> | 2023-09-29 11:37:04 -0700 |
commit | 388d6e2440bccded26d5e67ce6a7039c1953ae70 (patch) | |
tree | 943e96e22065ec32db06b57024c58fb2f6ba6543 /lua/conform/init.lua | |
parent | 45edf9462d06db0809d4a4a7afc6b7896b63fa35 (diff) |
fix: format_after_save autocmd blocks nvim exit until complete
This fixes one the main issue with a BufWritePost format autocmd:
that if the user does `:wq` vim will exit before the formatting changes
are applied. Now we will block in VimLeavePre until the formatter
completes (or a timeout is reached).
Diffstat (limited to 'lua/conform/init.lua')
-rw-r--r-- | lua/conform/init.lua | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/lua/conform/init.lua b/lua/conform/init.lua index 5f8610a..271e33d 100644 --- a/lua/conform/init.lua +++ b/lua/conform/init.lua @@ -106,6 +106,8 @@ M.setup = function(opts) if type(opts.format_after_save) == "boolean" then opts.format_after_save = {} end + local exit_timeout = 1000 + local num_running_format_jobs = 0 vim.api.nvim_create_autocmd("BufWritePost", { pattern = "*", group = aug, @@ -118,12 +120,15 @@ M.setup = function(opts) format_args, callback = format_args(args.buf) end if format_args then + exit_timeout = format_args.timeout_ms or exit_timeout + num_running_format_jobs = num_running_format_jobs + 1 M.format( vim.tbl_deep_extend("force", format_args, { buf = args.buf, async = true, }), function(err) + num_running_format_jobs = num_running_format_jobs - 1 if not err and vim.api.nvim_buf_is_valid(args.buf) then vim.api.nvim_buf_call(args.buf, function() vim.b[args.buf].conform_applying_formatting = true @@ -139,6 +144,36 @@ M.setup = function(opts) end end, }) + + vim.api.nvim_create_autocmd("BufWinLeave", { + pattern = "*", + group = aug, + callback = function(args) + -- We store this because when vim is exiting it will set changedtick = -1 for visible + -- buffers right after firing BufWinLeave + vim.b[args.buf].last_changedtick = vim.api.nvim_buf_get_changedtick(args.buf) + end, + }) + + vim.api.nvim_create_autocmd("VimLeavePre", { + pattern = "*", + group = aug, + callback = function() + if num_running_format_jobs == 0 then + return + end + local uv = vim.uv or vim.loop + local start = uv.hrtime() / 1e6 + vim.wait(exit_timeout, function() + return num_running_format_jobs == 0 + end, 10) + local elapsed = uv.hrtime() / 1e6 - start + if elapsed > 200 then + local log = require("conform.log") + log.warn("Delayed Neovim exit by %dms to wait for formatting to complete", elapsed) + end + end, + }) end vim.api.nvim_create_user_command("ConformInfo", function() |