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:
parent
18dfd2458d
commit
e045ee3b4e
2 changed files with 52 additions and 4 deletions
|
|
@ -926,9 +926,11 @@ local function close_preview_window_if_not_in_oil()
|
||||||
pcall(vim.api.nvim_win_close, preview_win_id, true)
|
pcall(vim.api.nvim_win_close, preview_win_id, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local _on_key_ns = 0
|
||||||
---Initialize oil
|
---Initialize oil
|
||||||
---@param opts nil|table
|
---@param opts nil|table
|
||||||
M.setup = function(opts)
|
M.setup = function(opts)
|
||||||
|
local Ringbuf = require("oil.ringbuf")
|
||||||
local config = require("oil.config")
|
local config = require("oil.config")
|
||||||
|
|
||||||
config.setup(opts)
|
config.setup(opts)
|
||||||
|
|
@ -999,6 +1001,12 @@ M.setup = function(opts)
|
||||||
pattern = filetype_patterns,
|
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", {
|
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||||
desc = "Set default oil highlights",
|
desc = "Set default oil highlights",
|
||||||
group = aug,
|
group = aug,
|
||||||
|
|
@ -1018,12 +1026,15 @@ M.setup = function(opts)
|
||||||
pattern = scheme_pattern,
|
pattern = scheme_pattern,
|
||||||
nested = true,
|
nested = true,
|
||||||
callback = function(params)
|
callback = function(params)
|
||||||
|
local last_keys = keybuf:as_str()
|
||||||
local winid = vim.api.nvim_get_current_win()
|
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
|
-- 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_after_save = vim.endswith(last_keys, ":wq\r")
|
||||||
local quit_all = last_cmd:match("^wqal*$")
|
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)
|
local bufname = vim.api.nvim_buf_get_name(params.buf)
|
||||||
if vim.endswith(bufname, "/") then
|
if vim.endswith(bufname, "/") then
|
||||||
vim.cmd.doautocmd({ args = { "BufWritePre", params.file }, mods = { silent = true } })
|
vim.cmd.doautocmd({ args = { "BufWritePre", params.file }, mods = { silent = true } })
|
||||||
|
|
|
||||||
37
lua/oil/ringbuf.lua
Normal file
37
lua/oil/ringbuf.lua
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
---@class oil.Ringbuf
|
||||||
|
---@field private size integer
|
||||||
|
---@field private tail integer
|
||||||
|
---@field private buf string[]
|
||||||
|
local Ringbuf = {}
|
||||||
|
function Ringbuf.new(size)
|
||||||
|
local self = setmetatable({
|
||||||
|
size = size,
|
||||||
|
buf = {},
|
||||||
|
tail = 0,
|
||||||
|
}, { __index = Ringbuf })
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param val string
|
||||||
|
function Ringbuf:push(val)
|
||||||
|
self.tail = self.tail + 1
|
||||||
|
if self.tail > self.size then
|
||||||
|
self.tail = 1
|
||||||
|
end
|
||||||
|
self.buf[self.tail] = val
|
||||||
|
end
|
||||||
|
|
||||||
|
---@return string
|
||||||
|
function Ringbuf:as_str()
|
||||||
|
local postfix = ""
|
||||||
|
for i = 1, self.tail, 1 do
|
||||||
|
postfix = postfix .. self.buf[i]
|
||||||
|
end
|
||||||
|
local prefix = ""
|
||||||
|
for i = self.tail + 1, #self.buf, 1 do
|
||||||
|
prefix = prefix .. self.buf[i]
|
||||||
|
end
|
||||||
|
return prefix .. postfix
|
||||||
|
end
|
||||||
|
|
||||||
|
return Ringbuf
|
||||||
Loading…
Add table
Add a link
Reference in a new issue