Skip to content

Commit

Permalink
feat!: always retrieve session names from file data, deprecate old APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
jedrzejboczar committed Jun 10, 2024
1 parent 468a124 commit b980820
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 22 deletions.
28 changes: 22 additions & 6 deletions lua/possession/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,27 @@ local function complete_list(candidates, opts)
end
end

-- Limits filesystem access by caching the results by time
M.complete_session = complete_list(utils.throttle(function()
local files = vim.tbl_keys(session.list { no_read = true })
return vim.tbl_map(paths.session_name, files)
end, 3000))
-- Limits filesystem access by caching the session names per command line access
---@type table<string, string>?
local cached_names
vim.api.nvim_create_autocmd('CmdlineLeave', {
group = vim.api.nvim_create_augroup('possession.commands.complete', { clear = true }),
callback = function()
cached_names = nil
end
})

local function get_session_names()
if not cached_names then
cached_names = {}
for file, data in pairs(session.list()) do
cached_names[file] = data.name
end
end
return cached_names
end

M.complete_session = complete_list(get_session_names)

local function get_current()
local name = session.get_session_name()
Expand All @@ -54,7 +70,7 @@ local function get_last()
utils.error('Cannot find last loaded session - specify session name as an argument')
return nil
end
return paths.session_name(path)
return get_session_names()[path]
end

local function name_or(name, getter)
Expand Down
3 changes: 2 additions & 1 deletion lua/possession/migrate.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ function M.migrate(vimscript_path, opts)
callback = nil,
}, opts or {})
-- If not provided fallback to filename without extension
local name = assert(opts.name and opts.name or paths.session_name(vimscript_path))
local name = assert(opts.name and opts.name or vim.fn.fnamemodify(Path:new(vimscript_path):absolute(), ':t:r'))
local vimscript = Path:new(vimscript_path):read()


-- Try to retrieve cwd from vimscript, fall back to getcwd
local cwd
for _, line in ipairs(utils.split_lines(vimscript)) do
Expand Down
9 changes: 3 additions & 6 deletions lua/possession/paths.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@ function M.session_short(name)
return utils.relative_path(path, config.session_dir)
end

--- Get session name from a session file name
--- In general session file name should be in the form "<name>.json",
--- where <name> is the same as the value of JSON key "name", but if for some reason
--- those don't match (someone changed file name), better fall back to JSON contents.
---@param path string
---@deprecated
function M.session_name(path)
return utils.conditional_decode(vim.fn.fnamemodify(Path:new(path):absolute(), ':t:r'))
vim.deprecate('paths.session_name()', 'session.list() and get name from data', '?', 'possession')
return vim.json.decode(Path:new(path):read()).name
end

--- Get global cwd for use as session name
Expand Down
31 changes: 22 additions & 9 deletions lua/possession/session.lua
Original file line number Diff line number Diff line change
Expand Up @@ -371,25 +371,38 @@ function M.exists(name)
return true
end

---@class possession.ListOpts
---@field no_read? boolean do not read/parse session files, just scan the directory

--- Get a list of sessions as map-like table
---@param opts? possession.ListOpts
---@return table<string, table>|table<string, boolean> sessions {filename: V} with V type depending on `no_read`
---@param opts? {}
---@return table<string, table> sessions {filename: session_data}
function M.list(opts)
opts = vim.tbl_extend('force', {
no_read = true,
}, opts or {})
opts = opts or {}
if opts.no_read then
vim.deprecate('session.list().no_read', 'session files are now always read', '?', 'possession')
end

---@type table<string, string[]>
local files_by_name = {}

local sessions = {}
local glob = (Path:new(config.session_dir) / '*'):absolute()
local last = paths.last_session_link():absolute()
for _, file in ipairs(vim.fn.glob(glob, true, true)) do
local path = Path:new(file)
if path:absolute() ~= last then
local data = opts.no_read and vim.json.decode(path:read()) or path:absolute()
local data = vim.json.decode(path:read())
sessions[file] = data

files_by_name[data.name] = files_by_name[data.name] or {}
table.insert(files_by_name[data.name], file)
end
end

-- Check for name duplicates
for name, files in pairs(files_by_name) do
if #files > 1 then
utils.warn('Session name "%s" found in multiple session files, please remove one of them:\n%s',
name,
table.concat(files, '\n'))
end
end

Expand Down

0 comments on commit b980820

Please sign in to comment.