1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
-- Sidecar specification for :mksession. :mksession can't persist everything we want (tab-local
-- variables, man:// buffers, ...), so we keep a JSON object in a sidecar file alongside each `.vim`
-- session. Features register a `save`/`restore` pair: `save` returns the data to stash, `restore`
-- reapplies it after the session has been sourced. The engine owns reading, writing and dispatch;
-- it does not touch :mksession itself. Providers are wired up in plugin/50-session.lua.
--
-- API:
-- register(key, save, restore) — add a provider (provider contract below)
-- write(path) — collect every provider and write `path`'s sidecar
-- read(path) — read `path`'s sidecar and run each provider's restore
-- remove(path) — delete `path`'s sidecar if it exists
-- providers — the ordered registry: a list of { key, save, restore }
local M = {}
-- Ordered registry of sidecar providers (the "global table"):
-- { key = string, save = fun(): table, restore = fun(data: table) }
-- `save` returns a JSON-encodable table stored under `key`; `restore` receives it back (never nil)
-- after the session is sourced. Registration order is the restore order.
M.providers = {}
-- The sidecar JSON path that pairs with a `.vim` session file.
local function sidecar_path(path)
return (path:gsub("%.vim$", "")) .. ".json"
end
-- Register a sidecar provider. `save` and `restore` are both required (passed together) so a
-- provider can never be half-defined.
function M.register(key, save, restore)
assert(
type(save) == "function" and type(restore) == "function",
"session.register: both save and restore are required"
)
M.providers[#M.providers + 1] = { key = key, save = save, restore = restore }
end
-- Collect every provider's data and write the sidecar for `path`.
function M.write(path)
local data = {}
for _, p in ipairs(M.providers) do
data[p.key] = p.save()
end
local f = io.open(sidecar_path(path), "w")
if f then
f:write(vim.json.encode(data))
f:close()
end
end
-- Read `path`'s sidecar and dispatch each provider's restore. A missing or malformed sidecar is
-- silently ignored (sessions predating a provider simply won't have its key).
function M.read(path)
local f = io.open(sidecar_path(path), "r")
if not f then
return
end
local content = f:read("*a")
f:close()
local ok, data = pcall(vim.json.decode, content)
if not (ok and type(data) == "table") then
return
end
for _, p in ipairs(M.providers) do
if data[p.key] ~= nil then
p.restore(data[p.key])
end
end
end
-- Delete the sidecar paired with `path`, if present.
function M.remove(path)
local sidecar = sidecar_path(path)
if vim.uv.fs_stat(sidecar) then
vim.fs.rm(sidecar)
end
end
return M
|