servery-nvim-demo.mp4
The workflow
- Configure the directories you want to appear in the UI
- Use
:Sv(or configure a keymap) to jump between them - Profit
Features
-
Sessions outlive the terminal emulator unless you close them, e.g. with
:qa -
Supports session management via a bunch of ui providers:
- Built-in ui
- Snacks/picker
- fzf-lua
- mini.pick
- telescope
-
:Svdoes all the stuff
Install/configure
Note
servery.nvim requires nvim 0.12+. Display of server elapsed times requires 0.13+.
vim.pack (nvim 0.12+):
vim.pack.add({ "https://github.com/wurli/servery.nvim" }) -- The following are the defaults - you don't need to change them -- but you probably should at least set `dirs` and `ui.provider`. require("servery").setup({ -- Either supply the directories as an array of strings, or a function -- which returns an array. Shorthands like `~` are expanded. The default -- lists the non-hidden dirs in your home directory. ---@type string[] | fun(): string[] dirs = function() return vim.fn.glob("~/*", true, true) end, ---Function which discovers running servers which servery can attach to. ---@type fun(): string[] servers = function() return vim.tbl_filter( -- By default, servers are only shown if the "name" part of the -- server name is `nvim`. See `:h serverstart()` for more info. function(s) return vim.startswith(vim.fs.basename(s), "nvim.") end, vim.fn.serverlist({ peer = true }) ) end, session_dir = vim.fs.normalize(vim.fs.joinpath(vim.fn.stdpath("run"), "..", "servery")), -- Command and additional argument(s) used to start a new session. servery appends -- `--headless --listen {socket}`. -- default uses `vim.v.progpath` / current running nvim, user can add -- arguments here when neovim must be started through a wrapper, resolved -- from PATH, and / or needs extra startup setup, etc... ---@type string[] spawn_cmd = { vim.v.progpath }, ui = { -- Options: "builtin" | "snacks" | "fzf" | "telescope" | "mini_pick" provider = "builtin", ---@type servery.ui_provider prompt = "Switch Nvim Session", icons = { current = "", active = "", inactive = "", }, actions = { ["<enter>"] = "switch", ["<c-g>"] = "switch_and_detach", ["<c-x>"] = "detach", ["<c-s>"] = "spawn", }, -- fzf-lua uses fzf's keymap notation, so it gets its own actions table fzf_actions = { ["enter"] = "switch", ["ctrl-g"] = "switch_and_detach", ["ctrl-x"] = "detach", ["ctrl-s"] = "spawn", }, }, })
Or using lazy.nvim:
{
"wurli/servery",
opts = {
dirs = { "~" },
-- ... See above for more
},
lazy = false
},Keybinds/commands
:Sv: Open the servery ui.:[N]Sv[!]: Go to the nth last visited session. Also stops the current session if!is used.:Sv[!] [dir]: Go to the session in[dir], creating it if it's not already open. Also stops the current session if!is used.:[N]SvStop: Close the nth last visited session.:SvStop [dir]: Close the session in[dir].
Keymaps should be set up manually:
vim.keymap.set("n", "<c-f>", "<cmd>Sv<cr>", { desc = "Switch nvim sessions" }) vim.keymap.set("n", "ZV", "<cmd>1Sv<cr>", { desc = "Go to previous session" })
Why servery.nvim?
I previously managed sessions with Prime's
tmux-sessionizer. Tmux
served me well but has some rough edges which I'd prefer to avoid, so once
Neovim added :connect and :detach I decided to just move my whole life into
Neovim.