diff --git a/README.md b/README.md index e83ac99..ab85dcd 100644 --- a/README.md +++ b/README.md @@ -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" @@ -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 { 'wr', 'SessionSearch', desc = 'Session search' }, @@ -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 @@ -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 diff --git a/doc/auto-session.txt b/doc/auto-session.txt index 73a1ff8..2f0138c 100644 --- a/doc/auto-session.txt +++ b/doc/auto-session.txt @@ -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 diff --git a/lua/auto-session/config.lua b/lua/auto-session/config.lua index 30bb350..3973609 100644 --- a/lua/auto-session/config.lua +++ b/lua/auto-session/config.lua @@ -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 @@ -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", diff --git a/lua/auto-session/init.lua b/lua/auto-session/init.lua index afaca64..65fbed6 100644 --- a/lua/auto-session/init.lua +++ b/lua/auto-session/init.lua @@ -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 @@ -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()) diff --git a/lua/auto-session/lib.lua b/lua/auto-session/lib.lua index 1d0210a..34edaa5 100644 --- a/lua/auto-session/lib.lua +++ b/lua/auto-session/lib.lua @@ -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 diff --git a/tests/extra_sesssion_commands_spec.lua b/tests/extra_sesssion_commands_spec.lua index 46cf933..70af2c6 100644 --- a/tests/extra_sesssion_commands_spec.lua +++ b/tests/extra_sesssion_commands_spec.lua @@ -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", @@ -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" @@ -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() diff --git a/tests/lib_spec.lua b/tests/lib_spec.lua index fbd790f..728df6e 100644 --- a/tests/lib_spec.lua +++ b/tests/lib_spec.lua @@ -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)