-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwezterm.lua
More file actions
360 lines (318 loc) · 9.01 KB
/
Copy pathwezterm.lua
File metadata and controls
360 lines (318 loc) · 9.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
local wezterm = require 'wezterm'
local act = wezterm.action
local config = wezterm.config_builder()
-- Native Wayland on Hyprland (better background redraw than XWayland).
-- If the window is invisible on launch again, set back to false.
config.enable_wayland = true
-- OpenGL avoids WebGpu "frozen until focus" bugs on some setups
config.front_end = 'OpenGL'
-- Less batching delay for live output in unfocused windows
config.mux_output_parser_coalesce_delay_ms = 0
-- Persistent mux: panes/workspaces survive GUI close; dmenu `wezterm start` reconnects.
-- Closing the window (Hyprland Super+Q) detaches the GUI instead of cycling workspaces.
config.unix_domains = {
{ name = 'unix' },
}
config.default_gui_startup_args = { 'connect', 'unix' }
-- Match ~/.config/ghostty/config (Synthwave Everything + Berkeley Mono)
-- Berkeley Mono Variable: avoid berkeley_mono.ttf (underscore) — it resolves to oblique.
-- Use berkeley-mono.ttf only via ConfigDirsOnly.
config.font_locator = 'ConfigDirsOnly'
config.font_dirs = { '/home/alejandro/.config/wezterm/fonts' }
config.font = wezterm.font_with_fallback {
{ family = 'Berkeley Mono Variable', weight = 'DemiBold', style = 'Normal' },
'GeistMono Nerd Font Mono',
'Noto Sans Symbols 2',
}
config.warn_about_missing_glyphs = false
config.cell_width = 0.92
config.line_height = 1.0
config.font_size = 12.0
config.colors = {
foreground = '#f0eff1',
background = '#2a2139',
cursor_bg = '#72f1b8',
cursor_fg = '#1a1a1a',
cursor_border = '#72f1b8',
selection_bg = '#181521',
selection_fg = '#f0eff1',
split = '#6d77b3',
scrollbar_thumb = '#6d77b3',
ansi = {
'#fefefe',
'#f97e72',
'#72f1b8',
'#fede5d',
'#6d77b3',
'#c792ea',
'#f772e0',
'#fefefe',
},
brights = {
'#fefefe',
'#f88414',
'#72f1b8',
'#fff951',
'#36f9f6',
'#e1acff',
'#f92aad',
'#fefefe',
},
tab_bar = {
background = '#2a2139',
active_tab = {
bg_color = '#181521',
fg_color = '#72f1b8',
intensity = 'Bold',
},
inactive_tab = {
bg_color = '#2a2139',
fg_color = '#6d77b3',
},
inactive_tab_hover = {
bg_color = '#181521',
fg_color = '#c792ea',
},
new_tab = {
bg_color = '#2a2139',
fg_color = '#c792ea',
},
new_tab_hover = {
bg_color = '#181521',
fg_color = '#72f1b8',
},
},
}
config.default_cursor_style = 'BlinkingBar'
config.window_padding = { left = 0, right = 0, top = 0, bottom = 0 }
config.window_decorations = 'NONE'
config.pane_focus_follows_mouse = true
-- copy-on-select: not a config field on this build; select + middle-click or Ctrl+Shift+C
config.use_fancy_tab_bar = false
config.show_tab_index_in_tab_bar = false
config.tab_max_width = 36
local HOME = os.getenv('HOME') or ''
local shell_titles = {
[''] = true,
zsh = true,
bash = true,
sh = true,
fish = true,
}
local function path_from_cwd(cwd)
if cwd == nil then
return nil
end
if type(cwd) == 'userdata' or type(cwd) == 'table' then
if cwd.file_path and cwd.file_path ~= '' then
return cwd.file_path
end
if cwd.path and cwd.path ~= '' then
return cwd.path
end
end
if type(cwd) ~= 'string' then
return nil
end
local path = cwd:match('^file://[^/]+(/.+)$')
if not path then
path = cwd
end
return path:gsub('%%(%x%x)', function(hex)
return string.char(tonumber(hex, 16))
end)
end
local function shorten_path(path)
if not path or path == '' then
return nil
end
if HOME ~= '' and path:sub(1, #HOME) == HOME then
path = '~' .. path:sub(#HOME + 1)
end
return path
end
local function tab_display_title(tab)
local pane = tab.active_pane
local title = pane.title or ''
local ssh_host = pane.user_vars and pane.user_vars.ssh_host
if ssh_host and ssh_host ~= '' then
-- Prefer explicit tab title if set
local custom = tab.tab_title and tab.tab_title ~= '' and tab.tab_title
local program = not shell_titles[title] and title or nil
local label = custom or program
if label then
return ssh_host .. ' · ' .. label
end
local cwd = path_from_cwd(pane.current_working_dir)
local path = shorten_path(cwd)
if path then
return ssh_host .. ' ' .. path
end
return ssh_host
end
if tab.tab_title and tab.tab_title ~= '' then
return tab.tab_title
end
if shell_titles[title] then
local cwd = path_from_cwd(pane.current_working_dir)
local label = shorten_path(cwd)
if label then
return label
end
end
return title
end
-- Gap between tabs via format-tab-title (tab_bar_style fields removed in newer builds)
wezterm.on('format-tab-title', function(tab, _tabs, _panes, _config, hover, max_width)
local bg = '#2a2139'
local fg = '#6d77b3'
if tab.is_active then
bg = '#181521'
fg = '#72f1b8'
elseif hover then
bg = '#181521'
fg = '#c792ea'
end
local title = wezterm.truncate_right(tab_display_title(tab), max_width - 4)
local cells = {
{ Background = { Color = '#2a2139' } },
{ Text = ' ' },
{ Background = { Color = bg } },
{ Foreground = { Color = fg } },
}
if tab.is_active then
table.insert(cells, { Attribute = { Intensity = 'Bold' } })
end
table.insert(cells, { Text = ' ' .. title .. ' ' })
table.insert(cells, { Background = { Color = '#2a2139' } })
table.insert(cells, { Text = ' ' })
return cells
end)
config.default_workspace = '1'
-- Status lives in the tab bar; keep it visible even with one tab
config.enable_tab_bar = true
config.hide_tab_bar_if_only_one_tab = false
-- Named workspaces (Ctrl+1..9, Ctrl+0 = workspace "10")
local workspace_names = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' }
local workspace_keys = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' }
local workspace_slots = {}
for _, name in ipairs(workspace_names) do
workspace_slots[name] = true
end
local function kill_workspace(workspace)
local success, stdout =
wezterm.run_child_process { 'wezterm', 'cli', 'list', '--format=json' }
if not success or stdout == '' then
return
end
local ok, panes = pcall(wezterm.json_parse, stdout)
if not ok or not panes then
return
end
for _, p in ipairs(panes) do
if p.workspace == workspace then
wezterm.run_child_process {
'wezterm',
'cli',
'kill-pane',
'--pane-id=' .. tostring(p.pane_id),
}
end
end
end
-- Workspace numbers on the right (same colors as tabs; plain string + ANSI on this build)
local FG_ACTIVE = '\x1b[38;2;114;241;184m' -- #72f1b8
local FG_INACTIVE = '\x1b[38;2;109;119;179m' -- #6d77b3
local ATTR_BOLD = '\x1b[1m'
local ATTR_RESET = '\x1b[0m'
local function workspace_status(window)
local active = window:active_workspace()
local names = wezterm.mux.get_workspace_names()
local name_set = {}
for _, n in ipairs(names) do
name_set[n] = true
end
local chunks = {}
local has_slot = false
for _, slot in ipairs(workspace_names) do
if name_set[slot] then
has_slot = true
if #chunks > 0 then
table.insert(chunks, ' ')
end
if slot == active then
table.insert(chunks, FG_ACTIVE .. ATTR_BOLD .. slot)
else
table.insert(chunks, FG_INACTIVE .. slot)
end
end
end
if not has_slot then
return FG_ACTIVE .. ATTR_BOLD .. active .. ATTR_RESET
end
return table.concat(chunks, '') .. ATTR_RESET
end
wezterm.on('update-status', function(window, _pane)
local ok, status = pcall(workspace_status, window)
if ok and status and status ~= '' then
window:set_right_status(status)
else
window:set_right_status(FG_ACTIVE .. ATTR_BOLD .. window:active_workspace() .. ATTR_RESET)
end
end)
config.keys = {}
for i, key in ipairs(workspace_keys) do
table.insert(config.keys, {
key = key,
mods = 'CTRL',
action = act.SwitchToWorkspace { name = workspace_names[i] },
})
end
-- Fuzzy picker: all workspaces (create/switch)
table.insert(config.keys, {
key = 'w',
mods = 'CTRL|SHIFT',
action = act.ShowLauncherArgs { flags = 'FUZZY|WORKSPACES' },
})
-- Cycle workspaces (lexicographic order of names)
table.insert(config.keys, {
key = 'n',
mods = 'CTRL|SHIFT',
action = act.SwitchWorkspaceRelative(1),
})
table.insert(config.keys, {
key = 'p',
mods = 'CTRL|SHIFT',
action = act.SwitchWorkspaceRelative(-1),
})
-- Kill all panes in the current workspace
table.insert(config.keys, {
key = 'k',
mods = 'CTRL|SHIFT',
action = wezterm.action_callback(function(window, _pane)
kill_workspace(window:active_workspace())
end),
})
-- New workspace: prompt for name
table.insert(config.keys, {
key = 'i',
mods = 'CTRL|SHIFT',
action = act.PromptInputLine {
description = 'New workspace name',
action = wezterm.action_callback(function(window, pane, line)
if line and line ~= '' then
window:perform_action(act.SwitchToWorkspace { name = line }, pane)
end
end),
},
})
-- Alt+1..9, Alt+0 = tab index 0..9
for i = 0, 9 do
local key = i == 9 and '0' or tostring(i + 1)
table.insert(config.keys, {
key = key,
mods = 'ALT',
action = act.ActivateTab(i),
})
end
return config