Skip to content

Commit

Permalink
feat(post): wezterm session management
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikaverpil committed Oct 20, 2024
1 parent 52dbdaa commit 64d498c
Showing 1 changed file with 125 additions and 0 deletions.
125 changes: 125 additions & 0 deletions mkdocs/blog/posts/2024-10-20-wezterm-session-management.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
date: 2024-10-20
draft: false
authors:
- fredrikaverpil
comments: true
tags:
- neovim
- terminal
- lua
---

# Session management in Wezterm (without tmux)

I've been using [Neovim](https://github.com/neovim/neovim) as my daily
IDE/editor for a couple of years now. I've also been using
[tmux](https://github.com/tmux/tmux) to manage sessions, first using
[t-smart-tmux-session-manager](https://github.com/joshmedeski/t-smart-tmux-session-manager)
and later [sesh](https://github.com/joshmedeski/sesh), which supersedes the
former project. What's great about this is that it doesn't matter which terminal
emulator you use, you can still fall back to this kind of session management.

But the latency (and complexity) of tmux is annoying and I finally took some
time to evaluate the session management capabilities of
[Wezterm](https://github.com/wez/wezterm) (my currently favorite terminal
emulator, which you configure with Lua!) called
"[workspaces](https://wezfurlong.org/wezterm/recipes/workspaces.html)", to see
if this could replace tmux altogether for me.

<!-- more -->

## Replacing tmux with Wezterm's session management

Well, spoiler alert; it works _really_ well and with the help of
[smart_workspace_switcher.wezterm](https://github.com/MLFlexer/smart_workspace_switcher.wezterm),
I can get pretty much the same behavior as I am used to with sesh. They both
leverage [zoxide](https://github.com/ajeetdsouza/zoxide) for fuzzy-searching
recently visited folders.

!!! example "wezterm.lua"

```lua
-- print the workspace name at the upper right
wezterm.on("update-right-status", function(window, pane)
window:set_right_status(window:active_workspace())
end)
-- load plugin
local workspace_switcher = wezterm.plugin.require("https://github.com/MLFlexer/smart_workspace_switcher.wezterm")
-- set path to zoxide
workspace_switcher.zoxide_path = "/opt/homebrew/bin/zoxide"
-- keymaps
table.insert(keys, { key = "s", mods = "CTRL|SHIFT", action = workspace_switcher.switch_workspace() })
table.insert(keys, { key = "t", mods = "CTRL|SHIFT", action = act.ShowLauncherArgs({ flags = "FUZZY|WORKSPACES" }) })
table.insert(keys, { key = "[", mods = "CTRL|SHIFT", action = act.SwitchWorkspaceRelative(1) })
table.insert(keys, { key = "]", mods = "CTRL|SHIFT", action = act.SwitchWorkspaceRelative(-1) })
```

Full `wezterm.lua` source [here](https://github.com/fredrikaverpil/dotfiles/blob/main/wezterm.lua).

This is such a breath of fresh air, to not have to use tmux which adds
percievable latency, especially when drawing the screen. Wezterm also comes out
of the box with ability to split the terminal horizontally or vertically and
most of the features you would miss from leaving tmux. Hit `Ctrl+Shift+P` to
bring up the command palette and explore.

The only thing I'm a little wary about is how wezterm plugins are just read on
the fly from the Internet like this. I might vendor the
`smart_workspace_switcher.wezterm` project into my own dotfiles in the long
term.

## Bonus: tabs

I primarily use workspaces with Wezterm now, but it's also convenient to have
tabs around. I've created my own workflow here which entails adding the
following config to `wezterm.lua`, which is heavily inspired by
[aaronlifton's wezterm.lua config](https://github.com/aaronlifton/.config/blob/main/.config/wezterm/wezterm.lua).

So, when hitting `Cmd+Tab`, a new tab shows and is prefixed by a number. Tabs
can then be selected by hitting `Cmd+[number]`.

!!! tip "wezterm.lua"

```lua
config.hide_tab_bar_if_only_one_tab = false
config.use_fancy_tab_bar = false

local function get_current_working_dir(tab)
local current_dir = tab.active_pane and tab.active_pane.current_working_dir or { file_path = "" }
local HOME_DIR = string.format("file://%s", os.getenv("HOME"))

return current_dir == HOME_DIR and "." or string.gsub(current_dir.file_path, "(.*[/\\])(.*)", "%2")
end

wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover, max_width)
local has_unseen_output = false
if not tab.is_active then
for _, pane in ipairs(tab.panes) do
if pane.has_unseen_output then
has_unseen_output = true
break
end
end
end

local cwd = wezterm.format({
{ Attribute = { Intensity = "Bold" } },
{ Text = get_current_working_dir(tab) },
})

local title = string.format(" [%s] %s", tab.tab_index + 1, cwd)

if has_unseen_output then
return {
{ Foreground = { Color = "#8866bb" } },
{ Text = title },
}
end

return {
{ Text = title },
}
end)
```

Full `wezterm.lua` source [here](https://github.com/fredrikaverpil/dotfiles/blob/main/wezterm.lua).

0 comments on commit 64d498c

Please sign in to comment.