matthew revised this gist . Go to revision
10 files changed, 375 insertions, 2 deletions
README.md(file created)
@@ -0,0 +1,10 @@ | |||
1 | + | # My Wezterm Setup | |
2 | + | ||
3 | + | This is my Wezterm setup. | |
4 | + | 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. | |
5 | + | My keybindings mimic those I used in tmux for creating new panes and tabs. | |
6 | + | ||
7 | + | I'd previously used tmux-resurrect to manage my tmux sessions, and relied on its ability to save state periodically. | |
8 | + | 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. | |
9 | + | ||
10 | + | In my own setup, the smart-splits and resurrect configurations are in separate subdirectories; I've adapted the gist to a flat file structure. |
appearance.lua(file created)
@@ -0,0 +1,21 @@ | |||
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 |
merge.lua(file created)
@@ -0,0 +1,12 @@ | |||
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 |
notify.lua(file created)
@@ -0,0 +1,36 @@ | |||
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 |
powerline.lua(file created)
@@ -0,0 +1,65 @@ | |||
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) |
resurrect-config.lua(file created)
@@ -0,0 +1,108 @@ | |||
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 |
resurrect-events.lua(file created)
@@ -0,0 +1,37 @@ | |||
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) |
smart-splits-setup.lua(file created)
@@ -0,0 +1,51 @@ | |||
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 | + | } |
tab-status.lua(file created)
@@ -0,0 +1,33 @@ | |||
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 | + | ) |
wezterm.lua
@@ -3,8 +3,8 @@ local wezterm = require 'wezterm' | |||
3 | 3 | local act = wezterm.action | |
4 | 4 | local merge = require 'merge' | |
5 | 5 | local mux = wezterm.mux | |
6 | - | local resurrect = require 'resurrect/config' | |
7 | - | local smart_splits = require 'smart-splits/setup' | |
6 | + | local resurrect = require 'resurrect-config' | |
7 | + | local smart_splits = require 'smart-splits-setup' | |
8 | 8 | ||
9 | 9 | -- -------------------------------------------------------------------- | |
10 | 10 | -- CONFIGURATION |
matthew revised this gist . Go to revision
1 file changed, 308 insertions
wezterm.lua(file created)
@@ -0,0 +1,308 @@ | |||
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 |