mirror of
https://github.com/neovim/neovim.git
synced 2026-05-06 08:26:45 -04:00
d788dd2811
Problem: The fallback that tokenizes `eap->arg` by unescaped whitespace (when the parser doesn't pre-split via `EX_EXPAND` etc.) lives in `nlua_do_ucmd`, so only user-command callbacks got `eap.fargs`. Builtin commands routed through `nlua_call_excmd` have to re-parse the args themselves (e.g. `M.ex_lsp`). Solution: - Move the tokenization into `nlua_push_eap` so every Lua handler sees `eap.fargs`. Keep only the `EX_NOSPC` override in `nlua_do_ucmd` (the `nargs=1`/`?` case which is genuinely user-command-specific). - Drop the re-parse in `M.ex_lsp`.
87 lines
2.7 KiB
Lua
87 lines
2.7 KiB
Lua
local api = vim.api
|
|
local N_ = vim.fn.gettext
|
|
|
|
local M = {}
|
|
|
|
--- Renders a swap file as a multi-line block:
|
|
--- ```
|
|
--- %home%foo%bar%README.md.swl
|
|
--- dated: Thu Apr 23 17:25:52 2026
|
|
--- file name: ~foo/bar/README.md
|
|
--- modified: no
|
|
--- user name: justin host name: minime
|
|
--- process ID: 10521 (STILL RUNNING)
|
|
--- ```
|
|
--- @param path string
|
|
--- @return string
|
|
local function format_swap(path)
|
|
local info = vim.fn.swapinfo(path)
|
|
local mtime = info.mtime and vim.fn.strftime('%a %b %d %H:%M:%S %Y', info.mtime) or '?'
|
|
local lines = {
|
|
vim.fs.basename(path),
|
|
(' dated: %s'):format(mtime),
|
|
}
|
|
if info.error then
|
|
lines[#lines + 1] = (' [%s]'):format(info.error)
|
|
else
|
|
lines[#lines + 1] = (' file name: %s'):format(
|
|
info.fname == '' and '[No Name]' or info.fname
|
|
)
|
|
lines[#lines + 1] = (' modified: %s'):format(info.dirty == 1 and 'YES' or 'no')
|
|
if info.user ~= '' or info.host ~= '' then
|
|
local parts = {} ---@type string[]
|
|
if info.user ~= '' then
|
|
parts[#parts + 1] = ('user name: %s'):format(info.user)
|
|
end
|
|
if info.host ~= '' then
|
|
parts[#parts + 1] = ('host name: %s'):format(info.host)
|
|
end
|
|
lines[#lines + 1] = (' %s'):format(table.concat(parts, ' '))
|
|
end
|
|
if info.pid > 0 then
|
|
lines[#lines + 1] = (' process ID: %d (STILL RUNNING)'):format(info.pid)
|
|
end
|
|
end
|
|
return table.concat(lines, '\n')
|
|
end
|
|
|
|
--- Implements `:recover` (when there are multiple swap files): let the user pick via vim.ui.select().
|
|
---
|
|
--- async: returns immediately, then schedules `:recover {path}` on the chosen swapfile.
|
|
---
|
|
--- @param items string[] List of swapfile paths.
|
|
function M.select_swap(items)
|
|
vim.ui.select(items, {
|
|
prompt = N_('Select a swapfile:'),
|
|
kind = 'swap',
|
|
format_item = format_swap,
|
|
}, function(_, idx)
|
|
if not idx then
|
|
return
|
|
end
|
|
-- Queue ":recover! <swapfile>" as user input, so the recursive recovery runs via the normal
|
|
-- input-dispatch loop. Using vim.schedule + vim.cmd can hang bc of "Press ENTER".
|
|
vim.fn.feedkeys(
|
|
vim.keycode(('<Cmd>recover! %s<CR>'):format(vim.fn.fnameescape(items[idx]))),
|
|
'in'
|
|
)
|
|
end)
|
|
end
|
|
|
|
--- Implements `nvim -r` (no arg): list every swapfile found in 'directory'.
|
|
---
|
|
--- @param items string[] List of swapfile paths.
|
|
function M.list_swaps(items)
|
|
local lines = { { N_('Swap files found:') .. '\n' } } ---@type [string][]
|
|
if #items == 0 then
|
|
lines[#lines + 1] = { ' ' .. N_('-- none --') }
|
|
else
|
|
for i, path in ipairs(items) do
|
|
lines[#lines + 1] = { ('%d. %s\n'):format(i, format_swap(path)) }
|
|
end
|
|
end
|
|
api.nvim_echo(lines, false, {})
|
|
end
|
|
|
|
return M
|