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

refactor!: big cleanup of plugin #144

Merged
merged 20 commits into from
Aug 8, 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
211 changes: 107 additions & 104 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
## :sparkles: Features

- :evergreen_tree: Supports sessions across multiple git branches
- :telescope: Telescope extension to work with saved sessions
- :tickets: Custom events which users can hook into for tighter integration
- :telescope: Telescope extension to manage sessions
- :tickets: Custom events which users can hook into for tighter integrations
- :memo: Simple API to save/stop/restore/delete/list the current session(s)
- :open_file_folder: Supports autosaving and autoloading of sessions with allowed/ignored directories
- :floppy_disk: Automatically saves the active session under `.local/share/nvim/sessions` on exiting Neovim
Expand All @@ -35,7 +35,7 @@

## :package: Installation

Install the plugin with your preferred package manager:
Install and configure the plugin with your preferred package manager:

**[Lazy.nvim](https://github.com/folke/lazy.nvim)**

Expand Down Expand Up @@ -110,7 +110,7 @@ require('telescope').setup({
The plugin comes with a number of commands:

- `:SessionToggle` - Determines whether to load, start or stop a session
- `:SessionStart` - Start recording a session. Useful if `autosave = false`
- `:SessionStart` - Start recording a session. Useful if `autostart = false`
- `:SessionStop` - Stop recording a session
- `:SessionSave` - Save the current session
- `:SessionLoad` - Load the session for the current directory and current branch (if `git_use_branch = true`)
Expand All @@ -123,12 +123,12 @@ The plugin comes with a number of commands:
<!-- panvimdoc-ignore-start -->

<p align="center">
<img src="https://github.com/olimorris/persisted.nvim/assets/9512444/5bfd6f94-ff70-4f2b-9193-53cdf7140d75" alt="Telescope">
<img src="https://github.com/user-attachments/assets/3ff91790-b61a-4089-b87d-432e8b4969c2" alt="Telescope">
</p>

<!-- panvimdoc-ignore-end -->

The Telescope extension may be opened via `:Telescope persisted`. The available actions are:
The Telescope extension may be opened via `:Telescope persisted`. The default actions are:

- `<CR>` - Open/source the session file
- `<C-b>` - Add/update the git branch for the session file
Expand All @@ -140,8 +140,8 @@ The Telescope extension may be opened via `:Telescope persisted`. The available
The plugin sets a number of global variables throughout its lifecycle:

- `vim.g.persisting` - (bool) Determines if the plugin is active for the current session
- `vim.g.persisted_exists` - (bool) Determines if a session exists for the current working directory
- `vim.g.persisted_loaded_session` - (string) The file path to the current session
- `vim.g.persisting_session` - (string) The file path to the current session (if `follow_cwd` is false)
- `vim.g.persisted_loaded_session` - (string) The file path to the last loaded session

## :wrench: Configuration

Expand All @@ -150,42 +150,49 @@ The plugin sets a number of global variables throughout its lifecycle:
The plugin comes with the following defaults:

```lua
require("persisted").setup({
log_level = "ERROR", -- One of "TRACE", "DEBUG", "ERROR"
save_dir = vim.fn.expand(vim.fn.stdpath("data") .. "/sessions/"), -- directory where session files are saved
silent = false, -- silent nvim message when sourcing session file
use_git_branch = false, -- create session files based on the branch of a git enabled repository
default_branch = "main", -- the branch to load if a session file is not found for the current branch
autosave = true, -- automatically save session files when exiting Neovim
should_autosave = nil, -- function to determine if a session should be autosaved
autoload = false, -- automatically load the session for the cwd on Neovim startup
on_autoload_no_session = nil, -- function to run when `autoload = true` but there is no session to load
follow_cwd = true, -- change session file name to match current working directory if it changes
allowed_dirs = nil, -- table of dirs that the plugin will auto-save and auto-load from
ignored_dirs = nil, -- table of dirs that are ignored when auto-saving and auto-loading
ignored_branches = nil, -- table of branch patterns that are ignored for auto-saving and auto-loading
{
autostart = true, -- Automatically start the plugin on load?

-- Function to determine if a session should be saved
---@type fun(): boolean
should_save = function()
return true
end,

save_dir = vim.fn.expand(vim.fn.stdpath("data") .. "/sessions/"), -- Directory where session files are saved

follow_cwd = true, -- Change the session file to match any change in the cwd?
use_git_branch = false, -- Include the git branch in the session file name?
autoload = false, -- Automatically load the session for the cwd on Neovim startup?

-- Function to run when `autoload = true` but there is no session to load
---@type fun(): any
on_autoload_no_session = function() end,

allowed_dirs = {}, -- Table of dirs that the plugin will start and autoload from
ignored_dirs = {}, -- Table of dirs that are ignored for starting and autoloading

telescope = {
reset_prompt = true, -- Reset the Telescope prompt after an action?
mappings = { -- table of mappings for the Telescope extension
change_branch = "<c-b>",
copy_session = "<c-c>",
delete_session = "<c-d>",
mappings = { -- Mappings for managing sessions in Telescope
copy_session = "<C-c>",
change_branch = "<C-b>",
delete_session = "<C-d>",
},
icons = { -- icons displayed in the picker, set to nil to disable entirely
icons = { -- icons displayed in the Telescope picker
selected = " ",
dir = " ",
branch = " ",
dir = " ",
selected = " ",
},
},
})
}
```

**What is saved in the session?**

As the plugin uses Vim's `:mksession` command then you may change the `vim.o.sessionoptions` value to determine what to write into the session. Please see `:h sessionoptions` for more information.

> [!NOTE]
> The author uses: `vim.o.sessionoptions = "buffers,curdir,folds,tabpages,winpos,winsize"`
> The author uses: `vim.o.sessionoptions = "buffers,curdir,folds,globals,tabpages,winpos,winsize"`

**Session save location**

Expand All @@ -210,24 +217,27 @@ require("persisted").setup({
})
```

**Autosaving**
**Autostart**

By default, the plugin will automatically save a Neovim session to disk when the `VimLeavePre` event is triggered. Autosaving can be turned off by:
By default, the plugin will automatically start when the setup function is called. This results in a Neovim session being saved to disk when the `VimLeavePre` event is triggered. This can be disabled by:

```lua
require("persisted").setup({
autosave = false,
autostart = false,
})
```

Autosaving can be further controlled for certain directories by specifying `allowed_dirs` and `ignored_dirs`.
Autostarting can be further controlled for certain directories by specifying `allowed_dirs` and `ignored_dirs`.

**`should_save`**

There may be occasions when you do not wish to autosave; perhaps when a dashboard or a certain buftype is present. To control this, a callback function, `should_autosave`, may be used which should return a boolean value.
There may be occasions when you do not wish to save the session; perhaps when a dashboard or a certain filetype is present. To handle this, the `should_save` function may be used which should return a boolean value.

```lua
require("persisted").setup({
should_autosave = function()
-- do not autosave if the alpha dashboard is the current filetype
---@return bool
should_save = function()
-- Do not save if the alpha dashboard is the current filetype
if vim.bo.filetype == "alpha" then
return false
end
Expand All @@ -236,10 +246,7 @@ require("persisted").setup({
})
```

Of course, if you wish to manually save the session when autosaving is disabled, the `:SessionSave` command can be used.

> [!NOTE]
> If `autosave = false` then the `should_autosave` callback will not be executed.
Of course, if you wish to manually save the session the `:SessionSave` command can be used.

**Autoloading**

Expand All @@ -251,7 +258,7 @@ require("persisted").setup({
})
```

You can also provide a function to run when `autoload = true` but there is no session to be loaded:
You can also provide a function to run when `autoload = true` and there is no session to load:

```lua
require("persisted").setup({
Expand All @@ -262,29 +269,14 @@ require("persisted").setup({
})
```

Autoloading can be further controlled for certain directories by specifying `allowed_dirs` and `ignored_dirs`.

> [!NOTE]
> Autoloading will not occur if the plugin is lazy loaded or a user opens Neovim with arguments other than a single directory argument. For example: `nvim some_file.rb` will not result in autoloading but `nvim some/existing/path` or `nvim .` will.

**Following current working directory**

There may be a need to change the working directory to quickly access files in other directories without changing the current session's name on save. This behavior can be configured with `follow_cwd = false`.

By default, the session name will match the current working directory:

```lua
require("persisted").setup({
follow_cwd = true,
})
```
Autoloading can be further controlled for directories in the `allowed_dirs` and `ignored_dirs` config tables.

> [!NOTE]
> If `follow_cwd = false` the session name is stored upon loading under the global variable `vim.g.persisting_session`. This variable can be manually adjusted if changes to the session name are needed. Alternatively, if `follow_cwd = true` then `vim.g.persisting_session = nil`.
> [!IMPORTANT]
> By design, the plugin will not autoload a session when any arguments are passed to Neovim such as `nvim my_file.py`

**Allowed directories**

You may specify a table of directories for which the plugin will autosave and/or autoload from. For example:
You may specify a table of directories for which the plugin will start and/or autoload from. For example:

```lua
require("persisted").setup({
Expand All @@ -295,14 +287,14 @@ require("persisted").setup({
})
```

Specifying `~/Code` will autosave and autoload from that directory as well as all its sub-directories.
Specifying `~/Code` will start and autoload from that directory as well as all its sub-directories.

> [!NOTE]
> If `allowed_dirs` is left at its default value and `autosave` and/or `autoload` are set to `true`, then the plugin will autoload/autosave from _any_ directory
> If `allowed_dirs` is left at its default value and `autostart` and/or `autoload` are set to `true`, then the plugin will start and autoload from _any_ directory

**Ignored directories**

You may specify a table of directories for which the plugin will **never** autosave and autoload from. For example:
You may specify a table of directories for which the plugin will **never** start and autoload from. For example:

```lua
require("persisted").setup({
Expand Down Expand Up @@ -330,19 +322,6 @@ require("persisted").setup({

In this setup, `~/.config` and `~/.local/nvim` are still going to behave in their default setting (ignoring all listed directory and its children), however `/` and `/tmp` will only ignore those directories exactly.

**Ignored branches**

You may specify a table of patterns that match against branches for which the plugin will **never** autosave and autoload from:

```lua
require("persisted").setup({
ignored_branches = {
"^master",
"feature/%u"
},
})
```

**Events / Callbacks**

The plugin fires events at various points during its lifecycle:
Expand All @@ -355,21 +334,19 @@ The plugin fires events at various points during its lifecycle:
- `PersistedSavePost` - For _after_ a session is saved
- `PersistedDeletePre` - For _before_ a session is deleted
- `PersistedDeletePost` - For _after_ a session is deleted
- `PersistedStateChange` - For when a session is _started_ or _stopped_
- `PersistedToggled` - For when a session is toggled
- `PersistedStart` - For when a session has _started_
- `PersistedStop` - For when a session has _stopped_
- `PersistedToggle` - For when a session is toggled

These events can be consumed anywhere within your configuration by utilising the `vim.api.nvim_create_autocmd` function.

A commonly requested example is to use the Telescope extension to load a session, saving the current session before clearing all of the open buffers:

```lua
local group = vim.api.nvim_create_augroup("PersistedHooks", {})

vim.api.nvim_create_autocmd({ "User" }, {
vim.api.nvim_create_autocmd("User", {
pattern = "PersistedTelescopeLoadPre",
group = group,
callback = function(session)
-- Save the currently loaded session using a global variable
-- Save the currently loaded session using the global variable
require("persisted").save({ session = vim.g.persisted_loaded_session })

-- Delete all of the open buffers
Expand All @@ -378,33 +355,59 @@ vim.api.nvim_create_autocmd({ "User" }, {
})
```

**Using callback data**
**Highlights**

When certain events are fired, session data is made available for the user to consume, for example:
The plugin also comes with pre-defined highlight groups for the Telescope implementation:

```lua
{
branch = "main",
dir_path = "Code/Neovim/persisted.nvim",
file_path = "/Users/Oli/.local/share/nvim/sessions/%Users%Oli%Code%Neovim%persisted.nvim@@main.vim",
name = "Code/Neovim/persisted.nvim@@main",
}
```
- `PersistedTelescopeSelected`
- `PersistedTelescopeDir`
- `PersistedTelescopeBranch`

To consume this data, use the `session.data` table in your autocmd:
## :building_construction: Extending the Plugin

The plugin has been designed to be fully extensible. All of the functions in the [init.lua](https://github.com/olimorris/persisted.nvim/blob/main/lua/persisted/init.lua) and [utils.lua](https://github.com/olimorris/persisted.nvim/blob/main/lua/persisted/utils.lua) file are public.

Consider a user who wishes to autoload a session if arguments are passed to Neovim. A custom autocmd can be created which forces the autoload:

```lua
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "PersistedLoadPost",
group = group,
callback = function(session)
print(session.data.branch)
local persisted = require("persisted")

persisted.setup({
autoload = true
})

vim.api.nvim_create_autocmd("VimEnter", {
nested = true,
callback = function()
-- Add more complex logic here
if vim.fn.argc() > 0 then
-- Leverage the plugin's ability to resolve allowed_dirs and ignored_dirs
require("persisted").autoload({ force = true })
end
end,
})
```

> [!NOTE]
> This data is available for the `PersistedLoad`, `PersistedDelete` and `PersistedTelescope` events
Or, a user who wishes to check whether the current branch is in a table of branches to be ignored:

```lua
local persisted = require("persisted")
local utils = require("persisted.utils")

persisted.setup({
autostart = false,
use_git_branch = true,
})

local ignored_branches = {
"feature_branch"
}

if utils.in_table(persisted.branch(), ignored_branches) ~= nil then
persisted.load()
persisted.start()
end
```

## :page_with_curl: License

Expand Down
Loading