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: support for custom Snacks picker #400

Merged
merged 2 commits into from
Jan 27, 2025
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ AutoSession exposes the following commands that can be used or mapped to any key

:SessionPurgeOrphaned " removes all orphaned sessions with no working directory left.

:SessionSearch " open a session picker, uses Telescope if installed, vim.ui.select otherwise
:SessionSearch " open a session picker, uses Telescope or Snacks if installed, vim.ui.select otherwise

:Autosession search " open a vim.ui.select picker to choose a session to load.
:Autosession delete " open a vim.ui.select picker to choose a session to delete.
Expand All @@ -153,7 +153,7 @@ If you create a manually named session via `SessionSave my_session` or you resto

## 🔭 Session Lens

You can use Telescope to see, load, and delete your sessions. It's enabled by default if you have Telescope, but here's the Lazy config that shows the configuration options:
You can use Telescope or [snacks.nvim](https://github.com/folke/snacks.nvim) to see, load, and delete your sessions. It's enabled by default if you have Telescope, but here's the Lazy config that shows the configuration options:

```lua

Expand Down Expand Up @@ -198,7 +198,7 @@ You can use Telescope to see, load, and delete your sessions. It's enabled by de
```

You can use `:SessionSearch` to launch the session picker. If `load_on_setup = false`, `:SessionSearch` will initialize the Telescope extension when called. You can also use
`:Telescope session-lens` to launch the session picker but only if `load_on_setup = true` or you've previously called `SessionSearch`.
`:Telescope session-lens` to launch the session picker but only if `load_on_setup = true` or you've previously called `SessionSearch`. If you don't have Telescope installed but do have Snacks installed (and the picker enabled), AutoSession will use Snacks as the session picker. No change in configuration is needed (e.g. it will use the same keymap config).

The following default keymaps are available when the session-lens picker is open:

Expand Down
2 changes: 1 addition & 1 deletion doc/auto-session.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ This plugin provides the following commands:

`:SessionPurgeOrphaned` - removes all orphaned sessions with no working directory left.

`:SessionSearch` - open a session picker, uses Telescope if installed, vim.ui.select otherwise
`:SessionSearch` - open a session picker, uses Telescope or Snacks if installed, vim.ui.select otherwise

==============================================================================
API *auto-session.api*
Expand Down
82 changes: 80 additions & 2 deletions lua/auto-session/autocmds.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ local SessionLens -- will be initialized later
---
--- `:SessionPurgeOrphaned` - removes all orphaned sessions with no working directory left.
---
--- `:SessionSearch` - open a session picker, uses Telescope if installed, vim.ui.select otherwise
--- `:SessionSearch` - open a session picker, uses Telescope or Snacks if installed, vim.ui.select otherwise
---@brief ]]

local M = {}
Expand Down Expand Up @@ -122,6 +122,79 @@ local function setup_session_lens()
return true
end

local function has_snacks()
local success, snacks_picker_enabled = pcall(function()
---@diagnostic disable-next-line: undefined-field
return Snacks.config.picker.enabled
end)
return success and snacks_picker_enabled
end

local function snacks_session_search()
local mappings = Config.session_lens.mappings or {}
Snacks.picker.pick {
title = "Sessions",
finder = function()
return Lib.get_session_list(M.AutoSession.get_root_dir())
end,
format = "text",
transform = function(item)
item.text = item.display_name
end,
layout = {
preview = Config.session_lens.theme_conf.preview,
},
win = {
input = {
keys = {
["dd"] = "session_delete",
[mappings.delete_session[2]] = { "session_delete", mode = mappings.delete_session[1] },
[mappings.alternate_session[2]] = { "session_alternate", mode = mappings.alternate_session[1] },
[mappings.copy_session[2]] = { "session_copy", mode = mappings.copy_session[1] },
},
},
list = { keys = { ["dd"] = "session_delete" } },
},
actions = {
confirm = function(picker, item)
picker:close()
vim.schedule(function()
M.AutoSession.autosave_and_restore(item.session_name)
end)
end,
session_delete = function(picker, item)
vim.schedule(function()
M.AutoSession.DeleteSessionFile(item.path, item.display_name)
picker:find() -- refresh picker
end)
end,
session_alternate = function(picker, _)
vim.schedule(function()
local altername_session_name = Lib.get_alternate_session_name(Config.session_lens.session_control)
if not altername_session_name then
return
end
picker:close()
vim.defer_fn(function()
M.AutoSession.autosave_and_restore(altername_session_name)
end, 50)
end)
end,
session_copy = function(picker, item)
vim.schedule(function()
local new_name = vim.fn.input("New session name: ", item.text)
if not new_name or new_name == "" or new_name == item.text then
return
end
local content = vim.fn.readfile(item.path)
vim.fn.writefile(content, M.AutoSession.get_root_dir() .. Lib.escape_session_name(new_name) .. ".vim")
picker:find() -- refresh picker
end)
end,
},
}
end

local function setup_dirchanged_autocmds(AutoSession)
if not Config.cwd_change_handling then
Lib.logger.debug "cwd_change_handling is disabled, skipping setting DirChangedPre and DirChanged autocmd handling"
Expand Down Expand Up @@ -256,12 +329,17 @@ function M.setup_autocmds(AutoSession)
})

vim.api.nvim_create_user_command("SessionSearch", function()
-- If Telescope is installed, use that otherwise use vim.ui.select
-- Use telescope if installed, otherwise snacks, otherwise vim.ui.select
if setup_session_lens() and SessionLens then
vim.cmd "Telescope session-lens"
return
end

if has_snacks() then
snacks_session_search()
return
end

handle_autosession_command { args = "search" }
end, {
desc = "Open a session picker",
Expand Down
34 changes: 34 additions & 0 deletions lua/auto-session/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -681,4 +681,38 @@ function Lib.get_session_list(sessions_dir)
end, entries)
end

---Get the name of the altnernate session stored in the session control file
---@return string|nil name of the alternate session, suitable for calls to LoadSession
function Lib.get_alternate_session_name(session_control_conf)
if not session_control_conf then
Lib.logger.error "No session_control in config!"
return nil
end

local filepath = vim.fn.expand(session_control_conf.control_dir) .. session_control_conf.control_filename

if vim.fn.filereadable(filepath) == 0 then
return nil
end

local json = Lib.load_session_control_file(filepath)

local sessions = {
current = json.current,
alternate = json.alternate,
}

Lib.logger.debug("get_alternate_session_name", { sessions = sessions, json = json })

if sessions.current == sessions.alternate then
Lib.logger.info "Current session is the same as alternate, returning nil"
return nil
end
local file_name = vim.fn.fnamemodify(sessions.alternate, ":t")
if Lib.is_legacy_file_name(file_name) then
return (Lib.legacy_unescape_session_name(file_name):gsub("%.vim$", ""))
end
return Lib.escaped_session_name_to_session_name(file_name)
end

return Lib
43 changes: 3 additions & 40 deletions lua/auto-session/session-lens/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,6 @@ local transform_mod = require("telescope.actions.mt").transform_mod
local M = {}

---@private
local function get_alternate_session()
---@diagnostic disable-next-line: undefined-field
local session_control_conf = Config.session_lens.session_control

if not session_control_conf then
Lib.logger.error "No session_control in config!"
return
end

local filepath = vim.fn.expand(session_control_conf.control_dir) .. session_control_conf.control_filename

if vim.fn.filereadable(filepath) == 1 then
local json = Lib.load_session_control_file(filepath)

local sessions = {
current = json.current,
alternate = json.alternate,
}

Lib.logger.debug("get_alternate_session", { sessions = sessions, json = json })

if sessions.current ~= sessions.alternate then
return sessions.alternate
end

Lib.logger.info "Current session is the same as alternate!"
end
end

local function source_session(session_name, prompt_bufnr)
if prompt_bufnr then
Expand Down Expand Up @@ -74,23 +46,14 @@ end

---@private
M.alternate_session = function(prompt_bufnr)
local alternate_session = get_alternate_session()

if not alternate_session then
local alternate_session_name = Lib.get_alternate_session_name(Config.session_lens.session_control)
if not alternate_session_name then
vim.notify "There is no alternate session"
-- Keep the picker open in case they want to select a session to load
return
end

local file_name = vim.fn.fnamemodify(alternate_session, ":t")
local session_name
if Lib.is_legacy_file_name(file_name) then
session_name = (Lib.legacy_unescape_session_name(file_name):gsub("%.vim$", ""))
else
session_name = Lib.escaped_session_name_to_session_name(file_name)
end

source_session(session_name, prompt_bufnr)
source_session(alternate_session_name, prompt_bufnr)
end

---@private
Expand Down
Loading