summaryrefslogtreecommitdiffstats
path: root/.config/nvim
diff options
context:
space:
mode:
Diffstat (limited to '.config/nvim')
-rw-r--r--.config/nvim/plugin/50-session.lua75
1 files changed, 66 insertions, 9 deletions
diff --git a/.config/nvim/plugin/50-session.lua b/.config/nvim/plugin/50-session.lua
index 9d1a8bf..39b4c09 100644
--- a/.config/nvim/plugin/50-session.lua
+++ b/.config/nvim/plugin/50-session.lua
@@ -36,6 +36,32 @@ local function write_sidecar(path, data)
end
end
+-- :mksession can't restore man:// buffers (they're :buftype=nofile, not backed by a file), so
+-- we record them ourselves, nested as tab index -> window number -> { buffer name, cursor line }.
+-- Both indices are positional for the same reason as tab names above: :mksession recreates tabs
+-- and their windows in order, so the ordinals are stable across reloads. Nesting by tab matters
+-- because window numbers restart at 1 in each tabpage and would otherwise collide. The indices
+-- are stringified so the sparse table encodes as a JSON object, not a null-padded array.
+--
+-- Limitation: the cursor line is an index into the *rendered* man page, whose line wrapping
+-- depends on MANWIDTH. If MANWIDTH differs on load, the page re-wraps and the saved line points
+-- elsewhere. (It never changes in this setup, but the dependency is real.)
+local function man_windows()
+ local pages = {}
+ for ti, tp in ipairs(vim.api.nvim_list_tabpages()) do
+ for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tp)) do
+ local name = vim.api.nvim_buf_get_name(vim.api.nvim_win_get_buf(win))
+ if name:match("^man://") then
+ local tk = tostring(ti)
+ pages[tk] = pages[tk] or {}
+ pages[tk][tostring(vim.api.nvim_win_get_number(win))] =
+ { name = name, line = vim.api.nvim_win_get_cursor(win)[1] }
+ end
+ end
+ end
+ return pages
+end
+
local function save_session(path)
vim.cmd.mksession({ path, bang = true })
local names = {}
@@ -44,21 +70,52 @@ local function save_session(path)
local ok, name = pcall(vim.api.nvim_tabpage_get_var, tp, "tabname")
names[i] = (ok and type(name) == "string") and name or ""
end
- write_sidecar(path, { tabnames = names })
+ write_sidecar(path, { tabnames = names, manpages = man_windows() })
end
-local function load_session(path)
- vim.cmd.source(path)
- local names = read_sidecar(path).tabnames
- if not names then
+-- Reopen the man:// buffers recorded by man_windows(). Keys come back from JSON as strings,
+-- hence the tonumber(). :edit man://... re-renders the page via the man plugin's BufReadCmd; we
+-- run it window-scoped so the layout restored by :mksession is left untouched, then clamp the
+-- saved cursor line to the (possibly re-wrapped) page.
+local function restore_man_windows(manpages)
+ if not manpages then
return
end
- for i, tp in ipairs(vim.api.nvim_list_tabpages()) do
- if names[i] and names[i] ~= "" then
- vim.api.nvim_tabpage_set_var(tp, "tabname", names[i])
+ local tabpages = vim.api.nvim_list_tabpages()
+ for tk, wins in pairs(manpages) do
+ local tp = tabpages[tonumber(tk)]
+ if tp then
+ local by_number = {}
+ for _, win in ipairs(vim.api.nvim_tabpage_list_wins(tp)) do
+ by_number[vim.api.nvim_win_get_number(win)] = win
+ end
+ for wk, info in pairs(wins) do
+ local win = by_number[tonumber(wk)]
+ if win then
+ vim.api.nvim_win_call(win, function()
+ vim.cmd.edit({ args = { info.name } })
+ end)
+ local buf = vim.api.nvim_win_get_buf(win)
+ local line = math.max(1, math.min(info.line or 1, vim.api.nvim_buf_line_count(buf)))
+ vim.api.nvim_win_set_cursor(win, { line, 0 })
+ end
+ end
+ end
+ end
+end
+
+local function load_session(path)
+ vim.cmd.source(path)
+ local data = read_sidecar(path)
+ if data.tabnames then
+ for i, tp in ipairs(vim.api.nvim_list_tabpages()) do
+ if data.tabnames[i] and data.tabnames[i] ~= "" then
+ vim.api.nvim_tabpage_set_var(tp, "tabname", data.tabnames[i])
+ end
end
+ vim.cmd.redrawtabline()
end
- vim.cmd.redrawtabline()
+ restore_man_windows(data.manpages)
end
local function reload_session(path)