My Wezterm Setup
This is my Wezterm setup. My goal was to allow Wezterm to replace tmux, as I wanted a way to essentially have the features I use most from tmux always available — pane splitting, tab creation, and session management. My keybindings mimic those I used in tmux for creating new panes and tabs.
I'd previously used tmux-resurrect to manage my tmux sessions, and relied on its ability to save state periodically. For wezterm, I'm using resurrect.wezterm, with a number of configurations based on my own usage, and I use the same keybindings for naming sessions, saving sessions, and loading sessions, as I did in tmux.
In my own setup, the smart-splits and resurrect configurations are in separate subdirectories; I've adapted the gist to a flat file structure.
| 1 | -- From https://alexplescan.com/posts/2024/08/10/wezterm/ |
| 2 | local wezterm = require 'wezterm' |
| 3 | |
| 4 | local module = {} |
| 5 | |
| 6 | -- Returns a bool based on whether the host operating system's |
| 7 | -- appearance is light or dark. |
| 8 | function module.is_dark() |
| 9 | -- wezterm.gui is not always available, depending on what |
| 10 | -- environment wezterm is operating in. Just return true |
| 11 | -- if it's not defined. |
| 12 | if wezterm.gui then |
| 13 | -- Some systems report appearance like "Dark High Contrast" |
| 14 | -- so let's just look for the string "Dark" and if we find |
| 15 | -- it assume appearance is dark. |
| 16 | return wezterm.gui.get_appearance():find("Dark") |
| 17 | end |
| 18 | return true |
| 19 | end |
| 20 | |
| 21 | return module |
| 1 | -- Provide generalized functionality for merging tables |
| 2 | |
| 3 | local merge = {} |
| 4 | |
| 5 | function merge.all(base, overrides) |
| 6 | local ret = base or {} |
| 7 | local second = overrides or {} |
| 8 | for _, v in pairs(second) do table.insert(ret, v) end |
| 9 | return ret |
| 10 | end |
| 11 | |
| 12 | return merge |
| 1 | local wezterm = require 'wezterm' |
| 2 | local module = {} |
| 3 | |
| 4 | local function has_value (tab, val) |
| 5 | for index, value in ipairs(tab) do -- luacheck: ignore 213 |
| 6 | if value == val then |
| 7 | return true |
| 8 | end |
| 9 | end |
| 10 | |
| 11 | return false |
| 12 | end |
| 13 | |
| 14 | local function notify (subject, msg, urgency) |
| 15 | local allowed_urgency = { 'low', 'normal', 'critical' } |
| 16 | urgency = urgency or 'normal' |
| 17 | if not has_value(allowed_urgency, urgency) then |
| 18 | urgency = 'normal' |
| 19 | end |
| 20 | |
| 21 | wezterm.run_child_process { |
| 22 | 'notify-send', |
| 23 | '-i', |
| 24 | 'org.wezfurlong.wezterm', |
| 25 | '-a', |
| 26 | 'wezterm', |
| 27 | '-u', |
| 28 | urgency, |
| 29 | subject, |
| 30 | msg |
| 31 | } |
| 32 | end |
| 33 | |
| 34 | module.send = notify |
| 35 | |
| 36 | return module |
| 1 | -- From https://alexplescan.com/posts/2024/08/10/wezterm/ |
| 2 | local wezterm = require 'wezterm' |
| 3 | local appearance = require 'appearance' |
| 4 | |
| 5 | local function segments_for_right_status(window) |
| 6 | return { |
| 7 | window:active_workspace() .. ' ', |
| 8 | wezterm.strftime('%a %Y-%m-%d %H:%M '), |
| 9 | wezterm.hostname(), |
| 10 | } |
| 11 | end |
| 12 | |
| 13 | wezterm.on('update-status', function(window, _) |
| 14 | local SOLID_LEFT_ARROW = utf8.char(0xe0b2) |
| 15 | local segments = segments_for_right_status(window) |
| 16 | |
| 17 | local color_scheme = window:effective_config().resolved_palette |
| 18 | -- Note the use of wezterm.color.parse here, this returns |
| 19 | -- a Color object, which comes with functionality for lightening |
| 20 | -- or darkening the colour (amongst other things). |
| 21 | local bg = wezterm.color.parse(color_scheme.background) |
| 22 | local fg = color_scheme.foreground |
| 23 | |
| 24 | -- Each powerline segment is going to be coloured progressively |
| 25 | -- darker/lighter depending on whether we're on a dark/light colour |
| 26 | -- scheme. Let's establish the "from" and "to" bounds of our gradient. |
| 27 | local gradient_to, gradient_from = bg |
| 28 | |
| 29 | if appearance.is_dark() then |
| 30 | gradient_from = gradient_to:lighten(0.2) |
| 31 | else |
| 32 | gradient_from = gradient_to:darken(0.2) |
| 33 | end |
| 34 | |
| 35 | -- Yes, WezTerm supports creating gradients, because why not?! Although |
| 36 | -- they'd usually be used for setting high fidelity gradients on your terminal's |
| 37 | -- background, we'll use them here to give us a sample of the powerline segment |
| 38 | -- colours we need. |
| 39 | local gradient = wezterm.color.gradient( |
| 40 | { |
| 41 | orientation = 'Horizontal', |
| 42 | colors = { gradient_from, gradient_to }, |
| 43 | }, |
| 44 | #segments -- only gives us as many colours as we have segments. |
| 45 | ) |
| 46 | |
| 47 | -- We'll build up the elements to send to wezterm.format in this table. |
| 48 | local elements = {} |
| 49 | |
| 50 | for i, seg in ipairs(segments) do |
| 51 | local is_first = i == 1 |
| 52 | |
| 53 | if is_first then |
| 54 | table.insert(elements, { Background = { Color = 'none' } }) |
| 55 | end |
| 56 | table.insert(elements, { Foreground = { Color = gradient[i] } }) |
| 57 | table.insert(elements, { Text = SOLID_LEFT_ARROW }) |
| 58 | |
| 59 | table.insert(elements, { Foreground = { Color = fg } }) |
| 60 | table.insert(elements, { Background = { Color = gradient[i] } }) |
| 61 | table.insert(elements, { Text = ' ' .. seg .. ' ' }) |
| 62 | end |
| 63 | |
| 64 | window:set_right_status(wezterm.format(elements)) |
| 65 | end) |
| 1 | -- resurrect.wezterm configuration and settings |
| 2 | -- |
| 3 | -- This module: |
| 4 | -- * Configures the resurrect.wezterm plugin |
| 5 | -- * Configures event listener configuration (via an additional required file) |
| 6 | -- * Returns wezterm keybinding configuration for resurrect-related actions. |
| 7 | -- |
| 8 | -- The main wezterm configuration is then responsible for merging the |
| 9 | -- keybindings with other keybindings, or setting up its own. |
| 10 | |
| 11 | local config = {} |
| 12 | local wezterm = require 'wezterm' |
| 13 | local resurrect = wezterm.plugin.require("https://github.com/MLFlexer/resurrect.wezterm") |
| 14 | |
| 15 | -- resurrect.wezterm encryption |
| 16 | -- Uncomment the following to use encryption. |
| 17 | -- If you do, ensure you have the age tool installed, you have created an |
| 18 | -- encryption key at ~/.config/age/wezterm-resurrect.txt, and that you supply |
| 19 | -- the associated public_key below |
| 20 | resurrect.set_encryption({ |
| 21 | enable = true, |
| 22 | method = "age", |
| 23 | private_key = wezterm.home_dir .. "/.config/age/wezterm-resurrect.txt", |
| 24 | public_key = "PUBLIC-KEY-GOES-HERE", |
| 25 | }) |
| 26 | |
| 27 | -- resurrect.wezterm periodic save every 5 minutes |
| 28 | resurrect.periodic_save({ |
| 29 | interval_seconds = 300, |
| 30 | save_tabs = true, |
| 31 | save_windows = true, |
| 32 | save_workspaces = true, |
| 33 | }) |
| 34 | |
| 35 | -- Save only 5000 lines per pane |
| 36 | resurrect.set_max_nlines(5000) |
| 37 | |
| 38 | -- Default keybindings |
| 39 | -- These will need to be merged with the main wezterm keys. |
| 40 | config.keys = { |
| 41 | { |
| 42 | -- Save current and window state |
| 43 | -- See https://github.com/MLFlexer/resurrect.wezterm for options around |
| 44 | -- saving workspace and window state separately |
| 45 | key = 'S', |
| 46 | mods = 'LEADER|SHIFT', |
| 47 | action = wezterm.action_callback(function(win, pane) -- luacheck: ignore 212 |
| 48 | local state = resurrect.workspace_state.get_workspace_state() |
| 49 | resurrect.save_state(state) |
| 50 | resurrect.window_state.save_window_action() |
| 51 | end), |
| 52 | }, |
| 53 | { |
| 54 | -- Load workspace or window state, using a fuzzy finder |
| 55 | key = 'L', |
| 56 | mods = 'LEADER|SHIFT', |
| 57 | action = wezterm.action_callback(function(win, pane) |
| 58 | resurrect.fuzzy_load(win, pane, function(id, label) -- luacheck: ignore 212 |
| 59 | local type = string.match(id, "^([^/]+)") -- match before '/' |
| 60 | id = string.match(id, "([^/]+)$") -- match after '/' |
| 61 | id = string.match(id, "(.+)%..+$") -- remove file extension |
| 62 | |
| 63 | local opts = { |
| 64 | window = win:mux_window(), |
| 65 | relative = true, |
| 66 | restore_text = true, |
| 67 | on_pane_restore = resurrect.tab_state.default_on_pane_restore, |
| 68 | } |
| 69 | |
| 70 | if type == "workspace" then |
| 71 | local state = resurrect.load_state(id, "workspace") |
| 72 | resurrect.workspace_state.restore_workspace(state, opts) |
| 73 | elseif type == "window" then |
| 74 | local state = resurrect.load_state(id, "window") |
| 75 | -- opts.tab = win:active_tab() |
| 76 | resurrect.window_state.restore_window(pane:window(), state, opts) |
| 77 | elseif type == "tab" then |
| 78 | local state = resurrect.load_state(id, "tab") |
| 79 | resurrect.tab_state.restore_tab(pane:tab(), state, opts) |
| 80 | end |
| 81 | end) |
| 82 | end), |
| 83 | }, |
| 84 | { |
| 85 | -- Delete a saved session using a fuzzy finder |
| 86 | key = 'd', |
| 87 | mods = 'LEADER|SHIFT', |
| 88 | action = wezterm.action_callback(function(win, pane) |
| 89 | resurrect.fuzzy_load( |
| 90 | win, |
| 91 | pane, |
| 92 | function(id) |
| 93 | resurrect.delete_state(id) |
| 94 | end, |
| 95 | { |
| 96 | title = 'Delete State', |
| 97 | description = 'Select session to delete and press Enter = accept, Esc = cancel, / = filter', |
| 98 | fuzzy_description = 'Search session to delete: ', |
| 99 | is_fuzzy = true, |
| 100 | } |
| 101 | ) |
| 102 | end), |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | require 'resurrect-events' |
| 107 | |
| 108 | return config |
| 1 | -- resurrect.wezterm event listener configuration |
| 2 | -- |
| 3 | -- This module configures event listeners for the resurrect.wezterm plugin. |
| 4 | |
| 5 | local wezterm = require 'wezterm' |
| 6 | local notify = require '../notify' |
| 7 | local suppress_notification = false |
| 8 | |
| 9 | wezterm.on('resurrect.error', function (error) |
| 10 | notify.send("Wezterm - ERROR", error, 'critical') |
| 11 | end) |
| 12 | |
| 13 | wezterm.on('resurrect.periodic_save', function () |
| 14 | suppress_notification = true |
| 15 | end) |
| 16 | |
| 17 | wezterm.on('resurrect.save_state.finished', function (session_path) |
| 18 | local is_workspace_save = session_path:find("state/workspace") |
| 19 | |
| 20 | if is_workspace_save == nil then |
| 21 | return |
| 22 | end |
| 23 | |
| 24 | if suppress_notification then |
| 25 | suppress_notification = false |
| 26 | return |
| 27 | end |
| 28 | |
| 29 | local path = session_path:match(".+/([^+]+)$") |
| 30 | local name = path:match("^(.+)%.json$") |
| 31 | notify.send("Wezterm - Save workspace", 'Saved workspace ' .. name .. "\n\n" .. session_path) |
| 32 | end) |
| 33 | |
| 34 | wezterm.on('resurrect.load_state.finished', function(name, type) |
| 35 | local msg = 'Completed loading ' .. type .. ' state: ' .. name |
| 36 | notify.send("Wezterm - Restore session", msg) |
| 37 | end) |
| 1 | local w = require('wezterm') |
| 2 | |
| 3 | -- if you are *NOT* lazy-loading smart-splits.nvim (recommended) |
| 4 | local function is_vim(pane) |
| 5 | -- this is set by the plugin, and unset on ExitPre in Neovim |
| 6 | return pane:get_user_vars().IS_NVIM == 'true' |
| 7 | end |
| 8 | |
| 9 | local direction_keys = { |
| 10 | h = 'Left', |
| 11 | j = 'Down', |
| 12 | k = 'Up', |
| 13 | l = 'Right', |
| 14 | } |
| 15 | |
| 16 | local function split_nav(resize_or_move, key) |
| 17 | return { |
| 18 | key = key, |
| 19 | mods = resize_or_move == 'resize' and 'META' or 'CTRL', |
| 20 | action = w.action_callback(function(win, pane) |
| 21 | if is_vim(pane) then |
| 22 | -- pass the keys through to vim/nvim |
| 23 | win:perform_action({ |
| 24 | SendKey = { key = key, mods = resize_or_move == 'resize' and 'META' or 'CTRL' }, |
| 25 | }, pane) |
| 26 | else |
| 27 | if resize_or_move == 'resize' then |
| 28 | win:perform_action({ AdjustPaneSize = { direction_keys[key], 3 } }, pane) |
| 29 | else |
| 30 | win:perform_action({ ActivatePaneDirection = direction_keys[key] }, pane) |
| 31 | end |
| 32 | end |
| 33 | end), |
| 34 | } |
| 35 | end |
| 36 | |
| 37 | return { |
| 38 | keys = { |
| 39 | -- move between split panes |
| 40 | split_nav('move', 'h'), |
| 41 | split_nav('move', 'j'), |
| 42 | split_nav('move', 'k'), |
| 43 | split_nav('move', 'l'), |
| 44 | |
| 45 | -- resize panes |
| 46 | split_nav('resize', 'h'), |
| 47 | split_nav('resize', 'j'), |
| 48 | split_nav('resize', 'k'), |
| 49 | split_nav('resize', 'l'), |
| 50 | }, |
| 51 | } |
| 1 | local wezterm = require 'wezterm' |
| 2 | |
| 3 | wezterm.on( |
| 4 | 'format-tab-title', |
| 5 | function(tab, tabs, panes, config, hover, max_width) |
| 6 | if tab.is_active then |
| 7 | -- Do nothing; normal active style is fine, so just return the text |
| 8 | return tab.active_pane.title |
| 9 | end |
| 10 | |
| 11 | local has_unseen_output = false |
| 12 | |
| 13 | for _, pane in ipairs(tab.panes) do |
| 14 | if pane.has_unseen_output then |
| 15 | has_unseen_output = true |
| 16 | break |
| 17 | end |
| 18 | end |
| 19 | |
| 20 | if has_unseen_output then |
| 21 | -- Set the background to Solarized's yellow, and foreground to |
| 22 | -- Solarized's base02 |
| 23 | return { |
| 24 | { Background = { Color = '#b58900' } }, |
| 25 | { Foreground = { Color = '#073642' } }, |
| 26 | { Text = ' ' .. tab.active_pane.title .. ' ' }, |
| 27 | } |
| 28 | end |
| 29 | |
| 30 | -- Do nothing different, as there's no activity; just return the text |
| 31 | return tab.active_pane.title |
| 32 | end |
| 33 | ) |
| 1 | -- Pull in the wezterm API, some of its modules, and plugins |
| 2 | local wezterm = require 'wezterm' |
| 3 | local act = wezterm.action |
| 4 | local merge = require 'merge' |
| 5 | local mux = wezterm.mux |
| 6 | local resurrect = require 'resurrect-config' |
| 7 | local smart_splits = require 'smart-splits-setup' |
| 8 | |
| 9 | -- -------------------------------------------------------------------- |
| 10 | -- CONFIGURATION |
| 11 | -- -------------------------------------------------------------------- |
| 12 | |
| 13 | -- This table will hold the configuration. |
| 14 | local config = {} |
| 15 | |
| 16 | -- In newer versions of wezterm, use the config_builder which will |
| 17 | -- help provide clearer error messages |
| 18 | if wezterm.config_builder then |
| 19 | config = wezterm.config_builder() |
| 20 | end |
| 21 | |
| 22 | config.adjust_window_size_when_changing_font_size = false |
| 23 | config.automatically_reload_config = true |
| 24 | config.color_scheme = 'Solarized (dark) (terminal.sexy)' |
| 25 | config.enable_scroll_bar = true |
| 26 | config.enable_wayland = true |
| 27 | -- config.font = wezterm.font('Hack') |
| 28 | config.font = wezterm.font('MonaspiceNe NFP') |
| 29 | config.font_size = 12.0 |
| 30 | config.hide_tab_bar_if_only_one_tab = false |
| 31 | -- The leader is similar to how tmux defines a set of keys to hit in order to |
| 32 | -- invoke tmux bindings. Binding to ctrl-a here to mimic tmux |
| 33 | config.leader = { key = 'a', mods = 'CTRL', timeout_milliseconds = 2000 } |
| 34 | config.mouse_bindings = { |
| 35 | -- Open URLs with Ctrl+Click |
| 36 | { |
| 37 | event = { Up = { streak = 1, button = 'Left' } }, |
| 38 | mods = 'CTRL', |
| 39 | action = act.OpenLinkAtMouseCursor, |
| 40 | } |
| 41 | } |
| 42 | config.pane_focus_follows_mouse = true |
| 43 | config.scrollback_lines = 5000 |
| 44 | config.tiling_desktop_environments = { |
| 45 | 'Wayland', |
| 46 | } |
| 47 | config.use_dead_keys = false |
| 48 | config.warn_about_missing_glyphs = false |
| 49 | config.window_decorations = "TITLE | RESIZE" |
| 50 | config.window_padding = { |
| 51 | left = 0, |
| 52 | right = 0, |
| 53 | top = 0, |
| 54 | bottom = 0, |
| 55 | } |
| 56 | |
| 57 | -- Tab bar |
| 58 | config.use_fancy_tab_bar = true |
| 59 | config.tab_bar_at_bottom = true |
| 60 | config.switch_to_last_active_tab_when_closing_tab = true |
| 61 | config.tab_max_width = 32 |
| 62 | config.colors = { |
| 63 | quick_select_label_bg = { Color = '#fdf6e3' }, |
| 64 | quick_select_label_fg = { Color = '#073642' }, |
| 65 | tab_bar = { |
| 66 | active_tab = { |
| 67 | fg_color = '#073642', |
| 68 | bg_color = '#2aa198', |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | -- Add items to launch menu |
| 74 | config.launch_menu = { |
| 75 | { |
| 76 | label = 'mwop', |
| 77 | cwd = wezterm.home_dir .. '/git/weierophinney/mwop.net', |
| 78 | }, |
| 79 | { |
| 80 | label = 'onedrive', |
| 81 | cwd = wezterm.home_dir .. '/OneDrive', |
| 82 | }, |
| 83 | { |
| 84 | label = 'top', |
| 85 | args = { 'top' }, |
| 86 | }, |
| 87 | } |
| 88 | |
| 89 | -- Custom key bindings |
| 90 | config.keys = { |
| 91 | -- Show the launcher |
| 92 | { |
| 93 | key = 'm', |
| 94 | mods = 'LEADER', |
| 95 | action = act.ShowLauncher, |
| 96 | }, |
| 97 | |
| 98 | -- Copy mode |
| 99 | { |
| 100 | key = '[', |
| 101 | mods = 'LEADER', |
| 102 | action = act.ActivateCopyMode, |
| 103 | }, |
| 104 | |
| 105 | -- ---------------------------------------------------------------- |
| 106 | -- TABS |
| 107 | -- |
| 108 | -- Where possible, I'm using the same combinations as I would in tmux |
| 109 | -- ---------------------------------------------------------------- |
| 110 | |
| 111 | -- Show tab navigator; similar to listing panes in tmux |
| 112 | { |
| 113 | key = 'w', |
| 114 | mods = 'LEADER', |
| 115 | action = act.ShowTabNavigator, |
| 116 | }, |
| 117 | |
| 118 | -- Create a tab (alternative to Ctrl-Shift-Tab) |
| 119 | { |
| 120 | key = 'c', |
| 121 | mods = 'LEADER', |
| 122 | action = act.SpawnTab 'CurrentPaneDomain', |
| 123 | }, |
| 124 | |
| 125 | -- Rename current tab; analagous to command in tmux |
| 126 | { |
| 127 | key = ',', |
| 128 | mods = 'LEADER', |
| 129 | action = act.PromptInputLine { |
| 130 | description = 'Enter new name for tab', |
| 131 | action = wezterm.action_callback( |
| 132 | function(window, pane, line) -- luacheck: ignore 212 |
| 133 | if line then |
| 134 | window:active_tab():set_title(line) |
| 135 | end |
| 136 | end |
| 137 | ), |
| 138 | }, |
| 139 | }, |
| 140 | |
| 141 | -- Move to next/previous TAB |
| 142 | { |
| 143 | key = 'n', |
| 144 | mods = 'LEADER', |
| 145 | action = act.ActivateTabRelative(1), |
| 146 | }, |
| 147 | { |
| 148 | key = 'p', |
| 149 | mods = 'LEADER', |
| 150 | action = act.ActivateTabRelative(-1), |
| 151 | }, |
| 152 | |
| 153 | -- Close tab |
| 154 | { |
| 155 | key = '&', |
| 156 | mods = 'LEADER|SHIFT', |
| 157 | action = act.CloseCurrentTab{ confirm = true }, |
| 158 | }, |
| 159 | |
| 160 | -- ---------------------------------------------------------------- |
| 161 | -- PANES |
| 162 | -- |
| 163 | -- These are great and get me most of the way to replacing tmux |
| 164 | -- entirely, particularly as you can use "wezterm ssh" to ssh to another |
| 165 | -- server, and still retain Wezterm as your terminal there. |
| 166 | -- |
| 167 | -- Note that these only define creating splits, relative motion |
| 168 | -- (next/previous), zooming, swapping, and killing panes; actual directional |
| 169 | -- motions between panes or resizing them are handled by smart splits. |
| 170 | -- ---------------------------------------------------------------- |
| 171 | |
| 172 | -- Vertical split |
| 173 | { |
| 174 | -- | |
| 175 | key = '|', |
| 176 | mods = 'LEADER|SHIFT', |
| 177 | action = act.SplitPane { |
| 178 | direction = 'Right', |
| 179 | size = { Percent = 50 }, |
| 180 | }, |
| 181 | }, |
| 182 | |
| 183 | -- Horizontal split |
| 184 | { |
| 185 | -- - |
| 186 | key = '-', |
| 187 | mods = 'LEADER', |
| 188 | action = act.SplitPane { |
| 189 | direction = 'Down', |
| 190 | size = { Percent = 50 }, |
| 191 | }, |
| 192 | }, |
| 193 | |
| 194 | -- Close/kill active pane |
| 195 | { |
| 196 | key = 'x', |
| 197 | mods = 'LEADER', |
| 198 | action = act.CloseCurrentPane { confirm = true }, |
| 199 | }, |
| 200 | |
| 201 | -- Swap active pane with another one |
| 202 | { |
| 203 | key = '{', |
| 204 | mods = 'LEADER|SHIFT', |
| 205 | action = act.PaneSelect { mode = "SwapWithActiveKeepFocus" }, |
| 206 | }, |
| 207 | |
| 208 | -- Zoom current pane (toggle) |
| 209 | { |
| 210 | key = 'z', |
| 211 | mods = 'LEADER', |
| 212 | action = act.TogglePaneZoomState, |
| 213 | }, |
| 214 | { |
| 215 | key = 'f', |
| 216 | mods = 'ALT', |
| 217 | action = act.TogglePaneZoomState, |
| 218 | }, |
| 219 | |
| 220 | -- Move to next/previous pane |
| 221 | { |
| 222 | key = ';', |
| 223 | mods = 'LEADER', |
| 224 | action = act.ActivatePaneDirection('Prev'), |
| 225 | }, |
| 226 | { |
| 227 | key = 'o', |
| 228 | mods = 'LEADER', |
| 229 | action = act.ActivatePaneDirection('Next'), |
| 230 | }, |
| 231 | |
| 232 | -- ---------------------------------------------------------------- |
| 233 | -- Workspaces |
| 234 | -- |
| 235 | -- These are roughly equivalent to tmux sessions. |
| 236 | -- ---------------------------------------------------------------- |
| 237 | |
| 238 | -- Attach to muxer |
| 239 | { |
| 240 | key = 'a', |
| 241 | mods = 'LEADER', |
| 242 | action = act.AttachDomain 'unix', |
| 243 | }, |
| 244 | |
| 245 | -- Detach from muxer |
| 246 | { |
| 247 | key = 'd', |
| 248 | mods = 'LEADER', |
| 249 | action = act.DetachDomain { DomainName = 'unix' }, |
| 250 | }, |
| 251 | |
| 252 | -- Show list of workspaces |
| 253 | { |
| 254 | key = 's', |
| 255 | mods = 'LEADER', |
| 256 | action = act.ShowLauncherArgs { flags = 'WORKSPACES' }, |
| 257 | }, |
| 258 | |
| 259 | -- Rename current session; analagous to command in tmux |
| 260 | { |
| 261 | key = '$', |
| 262 | mods = 'LEADER|SHIFT', |
| 263 | action = act.PromptInputLine { |
| 264 | description = 'Enter new name for session', |
| 265 | action = wezterm.action_callback( |
| 266 | function(window, pane, line) -- luacheck: ignore 212 |
| 267 | if line then |
| 268 | mux.rename_workspace( |
| 269 | window:mux_window():get_workspace(), |
| 270 | line |
| 271 | ) |
| 272 | end |
| 273 | end |
| 274 | ), |
| 275 | }, |
| 276 | }, |
| 277 | } |
| 278 | |
| 279 | -- -------------------------------------------------------------------- |
| 280 | -- Smart splits |
| 281 | -- |
| 282 | -- See https://github.com/mrjones2014/smart-splits.nvim |
| 283 | -- |
| 284 | -- Allows moving and resizing panes easily, as well as navigation between |
| 285 | -- wezterm and nvim panes |
| 286 | -- -------------------------------------------------------------------- |
| 287 | config.keys = merge.all(config.keys, smart_splits.keys) |
| 288 | |
| 289 | -- -------------------------------------------------------------------- |
| 290 | -- resurrect.wezterm |
| 291 | -- |
| 292 | -- See https://github.com/MLFlexer/resurrect.wezterm |
| 293 | -- See resurrect.lua |
| 294 | -- -------------------------------------------------------------------- |
| 295 | config.keys = merge.all(config.keys, resurrect.keys) |
| 296 | |
| 297 | -- Powerline for tab bar |
| 298 | require 'powerline' |
| 299 | |
| 300 | -- Tab status |
| 301 | require 'tab-status' |
| 302 | |
| 303 | -- Plugin management |
| 304 | -- Automatically update plugins |
| 305 | -- wezterm.plugin.update_all() |
| 306 | |
| 307 | -- and finally, return the configuration to wezterm |
| 308 | return config |