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

fix: save_extra_cmds only works with single string #375

Merged
merged 5 commits into from
Sep 16, 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
29 changes: 18 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ AutoSession takes advantage of Neovim's existing session management capabilities
{
'rmagatti/auto-session',
lazy = false,
dependencies = {
'nvim-telescope/telescope.nvim', -- Only needed if you want to use session lens
},

---enables autocomplete for opts
---@module "auto-session"
Expand Down Expand Up @@ -158,9 +155,6 @@ You can use Telescope to see, load, and delete your sessions. It's enabled by de
{
'rmagatti/auto-session',
lazy = false,
dependencies = {
'nvim-telescope/telescope.nvim',
},
keys = {
-- Will use Telescope if installed or a vim.ui.select picker otherwise
{ '<leader>wr', '<cmd>SessionSearch<CR>', desc = 'Session search' },
Expand Down Expand Up @@ -281,7 +275,7 @@ require('auto-session').setup({
Command hooks exist in the format: {hook_name}

- `{pre_save}`: executes _before_ a session is saved
- `{save_extra}`: executes _after_ a session is saved, return string will save to `*x.vim`, reference `:help mks`
- `{save_extra}`: executes _after_ a session is saved, saves returned string or table to `*x.vim`, reference `:help mks`
- `{post_save}`: executes _after_ a session is saved
- `{pre_restore}`: executes _before_ a session is restored
- `{post_restore}`: executes _after_ a session is restored
Expand Down Expand Up @@ -312,12 +306,25 @@ require('auto-session').setup {
end
},

-- Save quickfix list and open it when restoring the session
save_extra_cmds = {
function()
return [[echo "hello world"]]
end
}
}
local qflist = vim.fn.getqflist()
-- return nil to clear any old qflist
if #qflist == 0 then return nil end
local qfinfo = vim.fn.getqflist({ title = 1 })

for _, entry in ipairs(qflist) do
-- use filename instead of bufnr so it can be reloaded
entry.filename = vim.api.nvim_buf_get_name(entry.bufnr)
entry.bufnr = nil
end

local setqflist = 'call setqflist(' .. vim.fn.string(qflist) .. ')'
local setqfinfo = 'call setqflist([], "a", ' .. vim.fn.string(qfinfo) .. ')'
return { setqflist, setqfinfo, 'copen' }
end,
},
```

## ➖ Statusline
Expand Down
2 changes: 1 addition & 1 deletion doc/auto-session.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ AutoSession.Config *AutoSession.Config*
{auto_create?} (boolean|function) Enables/disables auto creating new session files. Can take a function that should return true/false if a new session file should be created or not
{suppressed_dirs?} (table) Suppress auto session for directories
{allowed_dirs?} (table) Allow auto session for directories, if empty then all directories are allowed except for suppressed ones
{auto_restore_last_lession?} (boolean) On startup, loads the last saved session if session for cwd does not exist
{auto_restore_last_session?} (boolean) On startup, loads the last saved session if session for cwd does not exist
{use_git_branch?} (boolean) Include git branch name in session name to differentiate between sessions for different git branches
{lazy_support?} (boolean) Automatically detect if Lazy.nvim is being used and wait until Lazy is done to make sure session is restored correctly. Does nothing if Lazy isn't being used. Can be disabled if a problem is suspected or for debugging
{bypass_save_filetypes?} (table) List of file types to bypass auto save when the only buffer open is one of the file types listed, useful to ignore dashboards
Expand Down
4 changes: 2 additions & 2 deletions lua/auto-session/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ local M = {}
---@field auto_create? boolean|function Enables/disables auto creating new session files. Can take a function that should return true/false if a new session file should be created or not
---@field suppressed_dirs? table Suppress auto session for directories
---@field allowed_dirs? table Allow auto session for directories, if empty then all directories are allowed except for suppressed ones
---@field auto_restore_last_lession? boolean On startup, loads the last saved session if session for cwd does not exist
---@field auto_restore_last_session? boolean On startup, loads the last saved session if session for cwd does not exist
---@field use_git_branch? boolean Include git branch name in session name to differentiate between sessions for different git branches
---@field lazy_support? boolean Automatically detect if Lazy.nvim is being used and wait until Lazy is done to make sure session is restored correctly. Does nothing if Lazy isn't being used. Can be disabled if a problem is suspected or for debugging
---@field bypass_save_filetypes? table List of file types to bypass auto save when the only buffer open is one of the file types listed, useful to ignore dashboards
Expand Down Expand Up @@ -159,7 +159,7 @@ local function check_old_config_names(config)
auto_session_allowed_dirs = "allowed_dirs",
auto_session_suppress_dirs = "suppressed_dirs",
auto_session_create_enabled = "auto_create",
auto_session_enable_last_session = "auto_restore_last_lession",
auto_session_enable_last_session = "auto_restore_last_session",
auto_session_use_git_branch = "use_git_branch",
auto_restore_lazy_delay_enabled = "lazy_support",
bypass_session_save_file_types = "bypass_save_filetypes",
Expand Down
15 changes: 11 additions & 4 deletions lua/auto-session/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -355,12 +355,19 @@ end
---@return boolean Returns whether extra commands were saved
local function save_extra_cmds_new(session_path)
local data = AutoSession.run_cmds "save_extra"
if not data then
local extra_file = string.gsub(session_path, "%.vim$", "x.vim")

-- data is a table of strings or tables, one for each hook function
-- need to combine them all here into a single table of strings
local data_to_write = Lib.flatten_table_and_split_strings(data)

if not data_to_write or vim.tbl_isempty(data_to_write) then
-- Have to delete the file just in case there's an old file from a previous save
vim.fn.delete(extra_file)
return false
end

local extra_file = string.gsub(session_path, "%.vim$", "x.vim")
if vim.fn.writefile(data, extra_file) ~= 0 then
if vim.fn.writefile(data_to_write, extra_file) ~= 0 then
return false
end

Expand Down Expand Up @@ -472,7 +479,7 @@ function AutoSession.auto_restore_session_at_vim_enter()
end

-- Check to see if the last session feature is on
if Config.auto_restore_last_lession then
if Config.auto_restore_last_session then
Lib.logger.debug "Last session is enabled, checking for session"

local last_session_name = Lib.get_latest_session(AutoSession.get_root_dir())
Expand Down
41 changes: 41 additions & 0 deletions lua/auto-session/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -563,4 +563,45 @@ function Lib.run_hook_cmds(cmds, hook_name)
return results
end

---Split any strings on newlines and add each one to the output table
---Also flatten any embedded tables and and their values into the root table
---(non recursive so only one level deep)
---@param input table|nil
---@return table The flattened table
function Lib.flatten_table_and_split_strings(input)
local output = {}

if not input then
return output
end

local function add_value_to_output(value)
Lib.logger.debug("value: ", value)
if value == nil then
return
end

local value_type = type(value)
if value_type == "number" then
table.insert(output, value)
elseif value_type == "string" then
for s in value:gmatch "[^\r\n]+" do
table.insert(output, s)
end
end
end

for _, value in pairs(input) do
if type(value) == "table" then
for _, subvalue in pairs(value) do
add_value_to_output(subvalue)
end
else
add_value_to_output(value)
end
end

return output
end

return Lib
81 changes: 78 additions & 3 deletions tests/extra_sesssion_commands_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ describe("Config with extra session commands", function()
local save_extra_cmds_called = false
local as = require "auto-session"
local Lib = require "auto-session.lib"
-- WARN: this test calls setup again later to change save_extra_cmds
as.setup {
save_extra_cmds = {
function()
save_extra_cmds_called = true
return [[echo "hello world"]]
return [[
lua vim.g.extraCmdsTest = 1
lua vim.g.extraCmdsTest2 = 2
]]
end,
},
-- log_level = "debug",
Expand All @@ -36,7 +40,78 @@ describe("Config with extra session commands", function()
TL.assertSessionHasFile(TL.default_session_path, TL.test_file)

-- Make sure extra commands are there
assert.True(TL.fileHasString(default_extra_cmds_path, 'echo \\"hello world\\"'))
assert.True(TL.fileHasString(default_extra_cmds_path, "lua vim.g.extraCmdsTest = 1"))
end)

it("can restore a default session with extra commands", function()
vim.g.extraCmdsTest = 0
vim.g.extraCmdsTest2 = 0

assert.True(as.RestoreSession())

assert.True(vim.g.extraCmdsTest == 1)
assert.True(vim.g.extraCmdsTest2 == 2)
end)

it("can clear x.vim if there are no extra commands", function()
-- make sure the file is there now
assert.equals(1, vim.fn.filereadable(default_extra_cmds_path))

-- remove the handler
as.setup {
save_extra_cmds = nil,
}

-- generate default session
assert.True(as.AutoSaveSession())

-- Make sure the session was created
assert.equals(1, vim.fn.filereadable(TL.default_session_path))

-- make sure the extra commands file was removed
assert.equals(0, vim.fn.filereadable(default_extra_cmds_path))
end)

TL.clearSessionFilesAndBuffers()

it("can save a default session with extra commands in a table", function()
vim.cmd("e " .. TL.test_file)

save_extra_cmds_called = false

as.setup {
save_extra_cmds = {
function()
save_extra_cmds_called = true
return { "lua vim.g.extraCmdsTest = 1", "lua vim.g.extraCmdsTest2 = 2" }
end,
},
}

-- generate default session
assert.True(as.AutoSaveSession())

-- Make sure the session was created
assert.equals(1, vim.fn.filereadable(TL.default_session_path))
assert.equals(1, vim.fn.filereadable(default_extra_cmds_path))

assert.True(save_extra_cmds_called)

-- Make sure the session has our buffer
TL.assertSessionHasFile(TL.default_session_path, TL.test_file)

-- Make sure extra commands are there
assert.True(TL.fileHasString(default_extra_cmds_path, "lua vim.g.extraCmdsTest = 1"))
end)

it("can restore a default session with extra commands", function()
vim.g.extraCmdsTest = 0
vim.g.extraCmdsTest2 = 0

assert.True(as.RestoreSession())

assert.True(vim.g.extraCmdsTest == 1)
assert.True(vim.g.extraCmdsTest2 == 2)
end)

local session_name = "x"
Expand All @@ -61,7 +136,7 @@ describe("Config with extra session commands", function()
TL.assertSessionHasFile(session_path, TL.test_file)

-- Make sure extra commands are there
assert.True(TL.fileHasString(extra_cmds_path, 'echo \\"hello world\\"'))
assert.True(TL.fileHasString(extra_cmds_path, "lua vim.g.extraCmdsTest = 1"))
end)

it("can correctly differentiate x.vim session and xx.vim custom commands", function()
Expand Down
32 changes: 32 additions & 0 deletions tests/lib_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,36 @@ describe("Lib / Helper functions", function()
assert.equals("", Lib.current_session_name())
assert.equals("", Lib.current_session_name(true))
end)

it("flatten_table_and_split_string() works with strings and tables", function()
local data = { "one\ntwo\nthree\n" }
local output = Lib.flatten_table_and_split_strings(data)

assert.equals(#output, 3)
assert.equals(output[1], "one")
assert.equals(output[2], "two")
assert.equals(output[3], "three")

data = { { "a", "b", "c\nd" }, "e", "f\ng" }
output = Lib.flatten_table_and_split_strings(data)

assert.equals(#output, 7)
assert.equals(output[1], "a")
assert.equals(output[2], "b")
assert.equals(output[3], "c")
assert.equals(output[4], "d")
assert.equals(output[5], "e")
assert.equals(output[6], "f")
assert.equals(output[7], "g")

data = {}
output = Lib.flatten_table_and_split_strings(data)

assert.True(vim.tbl_isempty(output))

data = { {} }
output = Lib.flatten_table_and_split_strings(data)

assert.True(vim.tbl_isempty(output))
end)
end)