Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: copy session from telescope picker #382

Merged
merged 6 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ Here are the default settings:
-- Mode can be a string or a table, e.g. {"i", "n"} for both insert and normal mode
delete_session = { "i", "<C-D>" },
alternate_session = { "i", "<C-S>" },
copy_session = { "i", "<C-Y>" },
},

session_control = {
Expand Down Expand Up @@ -176,8 +177,10 @@ You can use Telescope to see, load, and delete your sessions. It's enabled by de
-- Mode can be a string or a table, e.g. {"i", "n"} for both insert and normal mode
delete_session = { "i", "<C-D>" },
alternate_session = { "i", "<C-S>" },
copy_session = { "i", "<C-Y>" },
},
-- Can also set some Telescope picker options
-- For all options, see: https://github.com/nvim-telescope/telescope.nvim/blob/master/doc/telescope.txt#L112
theme_conf = {
border = true,
-- layout_config = {
Expand Down
1 change: 1 addition & 0 deletions doc/auto-session.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ SessionLensMappings *SessionLensMappings*
Fields: ~
{delete_session} (table) mode and key for deleting a session from the picker
{alternate_session} (table) mode and key for swapping to alertnate session from the picker
{copy_session} (table) mode and key for copying a session from the picker


==============================================================================
Expand Down
42 changes: 6 additions & 36 deletions lua/auto-session/autocmds.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,39 +37,6 @@ end
---@field display_name string
---@field path string

---@return PickerItem[]
local function get_session_files()
local files = {}
local sessions_dir = M.AutoSession.get_root_dir()

if vim.fn.isdirectory(sessions_dir) == Lib._VIM_FALSE then
return files
end

local entries = vim.fn.readdir(sessions_dir, function(item)
return Lib.is_session_file(sessions_dir .. item)
end)

return vim.tbl_map(function(file_name)
-- sessions_dir is guaranteed to have a trailing separator so don't need to add another one here
local session_name
local display_name
if Lib.is_legacy_file_name(file_name) then
session_name = (Lib.legacy_unescape_session_name(file_name):gsub("%.vim$", ""))
display_name = session_name .. " (legacy)"
else
session_name = Lib.escaped_session_name_to_session_name(file_name)
display_name = Lib.get_session_display_name(file_name)
end

return {
session_name = session_name,
display_name = display_name,
path = sessions_dir .. file_name,
}
end, entries)
end

---@param files string[]
---@param prompt string
---@param callback fun(choice: PickerItem)
Expand All @@ -89,7 +56,7 @@ end

---@param data table
local function handle_autosession_command(data)
local files = get_session_files()
local files = Lib.get_session_list(M.AutoSession.get_root_dir())
if data.args:match "search" then
open_picker(files, "Select a session:", function(choice)
M.AutoSession.autosave_and_restore(choice.session_name)
Expand All @@ -105,9 +72,12 @@ end
local function purge_orphaned_sessions()
local orphaned_sessions = {}

for _, session in ipairs(get_session_files()) do
local session_files = Lib.get_session_list(M.AutoSession.get_root_dir())
for _, session in ipairs(session_files) do
if
not Lib.is_named_session(session.session_name) and vim.fn.isdirectory(session.session_name) == Lib._VIM_FALSE
not Lib.is_named_session(session.session_name)
-- don't want any annotations (e.g. git branch)
and vim.fn.isdirectory(session.display_name_component) == Lib._VIM_FALSE
then
Lib.logger.debug("purge: " .. session.session_name)
table.insert(orphaned_sessions, session.session_name)
Expand Down
10 changes: 10 additions & 0 deletions lua/auto-session/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ local M = {}
---@class SessionLensMappings
---@field delete_session table mode and key for deleting a session from the picker
---@field alternate_session table mode and key for swapping to alertnate session from the picker
---@field copy_session table mode and key for copying a session from the picker

---@type AutoSession.Config
local defaults = {
Expand Down Expand Up @@ -94,6 +95,7 @@ local defaults = {
-- Mode can be a string or a table, e.g. {"i", "n"} for both insert and normal mode
delete_session = { "i", "<C-D>" },
alternate_session = { "i", "<C-S>" },
copy_session = { "i", "<C-Y>" },
},

---@type SessionControl
Expand Down Expand Up @@ -183,6 +185,7 @@ local function check_old_config_names(config)
and type(config["cwd_change_handling"]) == "table"
and config.cwd_change_handling["restore_upcoming_session"]
then
M.has_old_config = true
local old_cwd_change_handling = config.cwd_change_handling or {} -- shouldn't be nil but placate LS
config["cwd_change_handling"] = old_cwd_change_handling.restore_upcoming_session
if old_cwd_change_handling["pre_cwd_changed_hook"] then
Expand All @@ -192,6 +195,13 @@ local function check_old_config_names(config)
config.post_cwd_changed_cmds = { old_cwd_change_handling.post_cwd_changed_hook }
end
end

if config.session_lens and config.session_lens.shorten_path ~= nil then
M.has_old_config = true
if config.session_lens.shorten_path then
config.session_lens.path_display = { "shorten" }
end
end
end

---@param config? AutoSession.Config
Expand Down
2 changes: 1 addition & 1 deletion lua/auto-session/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ end
---@private
---Gets the root directory of where to save the sessions.
---By default this resolves to `vim.fn.stdpath "data" .. "/sessions/"`
---@param with_trailing_separator? boolean whether to incude the trailing separator. A few places (telescope picker don't expect a trailing separator) (Defaults to true)
---@param with_trailing_separator? boolean whether to incude the trailing separator. A few places (e.g. telescope picker) don't expect a trailing separator (Defaults to true)
---@return string
function AutoSession.get_root_dir(with_trailing_separator)
if with_trailing_separator == nil then
Expand Down
77 changes: 77 additions & 0 deletions lua/auto-session/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -604,4 +604,81 @@ function Lib.flatten_table_and_split_strings(input)
return output
end

---Returns the list of files in a directory, sorted by modification time
---@param dir string the directory to list
---@return table The filenames, sorted by modification time
function Lib.sorted_readdir(dir)
-- Get list of files
local files = vim.fn.readdir(dir)

-- Create a table with file names and modification times
local file_times = {}
for _, file in ipairs(files) do
local full_path = dir .. "/" .. file
local mod_time = vim.fn.getftime(full_path)
table.insert(file_times, { name = file, time = mod_time })
end

-- Sort the table based on modification times (most recent first)
table.sort(file_times, function(a, b)
return a.time > b.time
end)

-- Extract just the file names from the sorted table
local sorted_files = {}
for _, file in ipairs(file_times) do
table.insert(sorted_files, file.name)
end

return sorted_files
end

---Get the list of session files. Will filter out any extra command session files
---@param sessions_dir string The directory where the sessions are stored
---@return table the list of session files
function Lib.get_session_list(sessions_dir)
if vim.fn.isdirectory(sessions_dir) == Lib._VIM_FALSE then
return {}
end

local entries = Lib.sorted_readdir(sessions_dir)

return vim.tbl_map(function(file_name)
local session_name
local display_name_component

if not Lib.is_session_file(sessions_dir .. file_name) then
return nil
end

-- an annotation about the session, added to display_name after any path processing
local annotation = ""
if Lib.is_legacy_file_name(file_name) then
session_name = (Lib.legacy_unescape_session_name(file_name):gsub("%.vim$", ""))
display_name_component = session_name
annotation = " (legacy)"
else
session_name = Lib.escaped_session_name_to_session_name(file_name)
display_name_component = session_name
local name_components = Lib.get_session_display_name_as_table(file_name)
if #name_components > 1 then
display_name_component = name_components[1]
annotation = " " .. name_components[2]
end
end

local display_name = display_name_component .. annotation

return {
session_name = session_name,
-- include the components in case telescope wants to shorten the path
display_name_component = display_name_component,
annotation_component = annotation,
display_name = display_name,
file_name = file_name,
path = sessions_dir .. file_name,
}
end, entries)
end

return Lib
22 changes: 20 additions & 2 deletions lua/auto-session/session-lens/actions.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local AutoSession = require "auto-session"
local Config = require "auto-session.config"
local Lib = require "auto-session.lib"
local transform_mod = require("telescope.actions.mt").transform_mod

local M = {}

Expand Down Expand Up @@ -66,7 +67,7 @@ M.delete_session = function(prompt_bufnr)
local current_picker = action_state.get_current_picker(prompt_bufnr)
current_picker:delete_selection(function(selection)
if selection then
AutoSession.DeleteSessionFile(selection.path, selection.display)
AutoSession.DeleteSessionFile(selection.path, selection.display())
end
end)
end
Expand All @@ -92,4 +93,21 @@ M.alternate_session = function(prompt_bufnr)
source_session(session_name, prompt_bufnr)
end

return M
---@private
---Copy session action
---Ask user for the new name and then copy the session to that name
M.copy_session = function(_)
local action_state = require "telescope.actions.state"
local selection = action_state.get_selected_entry()

local new_name = vim.fn.input("New session name: ", selection.session_name)

if not new_name or new_name == "" then
return
end

local content = vim.fn.readfile(selection.path)
vim.fn.writefile(content, AutoSession.get_root_dir() .. Lib.escape_session_name(new_name) .. ".vim")
end

return transform_mod(M)
Loading