fix: spurious exits from faulty :wq detection (#221)

The previous mechanism used histget() to get the last command or
expression to detect if the user issued a `:wq` or similar. This had the
issue where if a user issued a `:wq`, started vim again, then entered
oil and saved via some mechanism that is _not_ a command (e.g. a
keymap), we would incorrectly detect that `:wq` and exit after saving.
The new mechanism tracks all keypresses and may end up with false
negatives (e.g. ":wqaff<backspace><backspace>ll"), but those are less
frustrating than false positives.
This commit is contained in:
Steven Arcangeli 2024-03-12 15:57:55 -07:00
parent 18dfd2458d
commit e045ee3b4e
2 changed files with 52 additions and 4 deletions

View file

@ -926,9 +926,11 @@ local function close_preview_window_if_not_in_oil()
pcall(vim.api.nvim_win_close, preview_win_id, true)
end
local _on_key_ns = 0
---Initialize oil
---@param opts nil|table
M.setup = function(opts)
local Ringbuf = require("oil.ringbuf")
local config = require("oil.config")
config.setup(opts)
@ -999,6 +1001,12 @@ M.setup = function(opts)
pattern = filetype_patterns,
})
local keybuf = Ringbuf.new(7)
if _on_key_ns == 0 then
_on_key_ns = vim.on_key(function(char)
keybuf:push(char)
end, _on_key_ns)
end
vim.api.nvim_create_autocmd("ColorScheme", {
desc = "Set default oil highlights",
group = aug,
@ -1018,12 +1026,15 @@ M.setup = function(opts)
pattern = scheme_pattern,
nested = true,
callback = function(params)
local last_keys = keybuf:as_str()
local winid = vim.api.nvim_get_current_win()
local last_cmd = vim.fn.histget("cmd", -1)
local last_expr = vim.fn.histget("expr", -1)
-- If the user issued a :wq or similar, we should quit after saving
local quit_after_save = last_cmd == "wq" or last_cmd == "x" or last_expr == "ZZ"
local quit_all = last_cmd:match("^wqal*$")
local quit_after_save = vim.endswith(last_keys, ":wq\r")
or vim.endswith(last_keys, ":x\r")
or vim.endswith(last_keys, "ZZ")
local quit_all = vim.endswith(last_keys, ":wqa\r")
or vim.endswith(last_keys, ":wqal\r")
or vim.endswith(last_keys, ":wqall\r")
local bufname = vim.api.nvim_buf_get_name(params.buf)
if vim.endswith(bufname, "/") then
vim.cmd.doautocmd({ args = { "BufWritePre", params.file }, mods = { silent = true } })