gennaro-tedesco / nvim-possession

šŸ“Œ the no-nonsense session manager
MIT License
207 stars 7 forks source link

Close session #36

Closed SlartThunder closed 5 months ago

SlartThunder commented 5 months ago

It would be nice to be able to close existing session without loading a new one. In that use case, it would be nice to close all buffers and reset status (in case of possession being in lualineā€¦)

gennaro-tedesco commented 5 months ago

Good afternoon!

It would be nice to be able to close existing session without loading a new one.

"Closing" a session is not a concept that exists in vim: essentially a session is a collection of buffers (and additionally layouts/tabs) to be loaded at startup.

What do you exactly mean by "closing" a session? If merely deleting all session buffers you can do so, but conceptually the session is still loaded (because it is loaded at VimEnter). What is the problem that you are trying to solve?

SlartThunder commented 5 months ago

If one deletes all buffers in current session (by the way, even though the autosave is set to false) the current session will be empty and still showing in the status the current session. What I would like is to close all buffers and to not have a session, like if NVIM just started

gennaro-tedesco commented 5 months ago

I think there is some confusion: a session is not something you "have", rather it is something you "load" - once the session is loaded, what happens is merely that vim loads a collection of buffers and retains the memory of the original session file in case you want to override it.

and to not have a session, like if NVIM just started

here is where the confusion arises, probably: once loaded, a session is loaded - but there is nothing you "have" (that can be deleted). Loading a new session on top means vim is looking into another session file to load the corresponding buffers on top, and so on.

Essentially do you want to just get rid of status bar indicator (after deleting all buffers) or why do you envision you want to have a clean vim state?

SlartThunder commented 5 months ago

The point I'm trying to achieve is to load a session, where I work on several files. Then I want to switch to a "null" session, so that I can start mangling around buffers until I decide I want to save the current state as a new one. If being in the "null" session, nothing would be shown in the "status" nor an update/delete can happen

gennaro-tedesco commented 5 months ago

so that I can start mangling around buffers until I decide I want to save the current state as a new one.

You can still save the new state of a session as a new session despite having loaded some others in the beginning. Do you simply want to avoid overriding a previous session (because if so, as said, you can just save to a new one instead of updating, this is why the plugin exposes those different commands).

nor an update/delete can happen

the session will not update anyway unless you explicitly override it by yourself.

nothing would be shown in the "status"

the status is nothing but a visual indicator in the statusline of the last opened session: if you want to get rid of it once all buffers are being wiped off then this is an operation that must be delegated to the statusline - the plugin merely provides a variable, the conditions on which such variable is displayed can be easily changed from the statusline components: for instance instead of

cond = function()
  return require("nvim-possession").status() ~= nil
end,

as indicated in the README you could include an additional condition that checks whether all buffers are wiped off (and if so, refresh the statusline and show an empty string).

There was another similar issue discussed some time ago: even in that case the same confusion about a session being a "state" in vim arose, and it seems that what the other user wanted too was again some sort of visual feedback when buffers are closed - but this has nothing to do with a session being closed (again, there is no such a concept).

SlartThunder commented 5 months ago

Hi, Here you are the code (feel free to add it to the repo if you wish):

local config = require("nvim-possession.config")
local utils = require('utils')
local M = {}

local function alert_session_cleared()
  utils.print_error("Action cannot be done! You are not in a session")
end

M.clear_session = function ()
    -- Close all windows
    vim.cmd('silent! %bwipeout!')

    -- Clean up the buffer list
    vim.cmd('bwipeout!')

    -- Clean up the quickfix list
    vim.cmd('silent! cclose')

    -- Clean up the location list
    vim.cmd('silent! lclose')

    -- Reset window layout to a single empty buffer
    vim.cmd('enew | only')

    -- Cleaning up lualine alike pluginsā€¦
    local user_config = vim.tbl_deep_extend("force", config, user_opts or {})
    vim.g[user_config.sessions.sessions_variable] = nil
    require("nvim-possession").status()

    -- The session itself is still there, so we avoid the default keymaps
    -- Update session remap
    vim.keymap.set("n", "<leader>su", function() alert_session_cleared() end)
    -- Delete session remap
    vim.keymap.set("n", "<leader>sd", function() alert_session_cleared() end)
    -- Clear session remap
    vim.keymap.set("n", "<leader>sc", function() alert_session_cleared() end)
end

M.set_mappings_again = function()
  local possession = require("nvim-possession")
  vim.keymap.set("n", "<leader>su", function() possession.update() end)
  vim.keymap.set("n", "<leader>sd", function() possession.delete() end)
  vim.keymap.set("n", "<leader>sc", function () require("custom-init-nvim-possession").clear_session() end)
end

return M

Then in your init:

init = function()
       local possession = require("nvim-possession")
       vim.keymap.set("n", "<leader>sl", function() possession.list() end)
       vim.keymap.set("n", "<leader>sn", function() possession.new() end)
       vim.keymap.set("n", "<leader>su", function() possession.update() end)
       vim.keymap.set("n", "<leader>sd", function() possession.delete() end)
       vim.keymap.set("n", "<leader>sc", function () require("custom-init-nvim-possession").clear_session() end)

And then:

require("nvim-possession").setup({
  autoswitch = { enable = true, },
  autosave = false,
  post_hook = require("custom-init-nvim-possession").set_mappings_again,
  fzf_winopts = {
      preview = {
        horizontal = "up:60%",
      },
    }
})

HTH!

gennaro-tedesco commented 5 months ago

When invoking require("custom-init-nvim-possession").clear_session() the mappings "<leader>su" (and the rest) are unset (or, to be more precise, they execute alert_session_cleared()); this however implies that, after clearing a session and opening a new one, such mappings will still be unset, thus you won't be able to execute them on the new session (to load, save, update and so forth).

Is this the intended behaviour?

SlartThunder commented 5 months ago

That's why I made use of the post_hook feature you implemented, so that the mappings can be set again!

Additionally, I played a bit so that it will not show in lualine plugin:

lualine_c = {
            {
               require("nvim-possession").status,
               cond = function()
                  local user_config = vim.tbl_deep_extend("force", configPossession, user_opts or {})
                  --currentSession = vim.g[user_config.sessions.sessions_variable]

                  if vim.api.nvim_win_get_width(0) < 100 then
                    vim.g[user_config.sessions.sessions_variable] = ""
                  else
                    if vim.g[user_config.sessions.sessions_variable] == "" then
                      vim.g[user_config.sessions.sessions_variable] = customPossession.getCurrentSession()
                    end
                  end

                   return require("nvim-possession").status() ~= nil
               end,
           },
           { "filename", 
               path = 1,
           }, 

Add this into the set_mappings_again method:

require("custom-init-nvim-possession").setCurrentSession(vim.g[user_config.sessions.sessions_variable])

More or less you can get the point:

local currentSession = nil

M.setCurrentSession = function(value)
  currentSession = value
end

M.getCurrentSession = function()
  return currentSession
end

Sorry I am not very skilled with Lua, Neovim so maybe things could be done more easily

gennaro-tedesco commented 5 months ago

I see, I will test it out myself too, great work and glad you've found a way to achieve it! :)