created wezterm config

This commit is contained in:
Jeremie Fraeys 2024-05-27 18:02:03 -04:00
parent 1972aef9bb
commit c64e26e33b
7 changed files with 647 additions and 0 deletions

View file

@ -0,0 +1,134 @@
local wezterm = require("wezterm")
local alert_popup_before_seconds = 15
local alert_if_in_next_minutes = 30
local theme_bg = "#2c323c"
local theme_red = "#f92572"
local nerd_font_free = ""
local nerd_font_meeting = "󰤙"
-- local meeting_delimiter = ""
local nerd_font_separator = ""
local ical_buddy = "/usr/local/bin/icalBuddy"
local ignored_cal = "Birthdays, Family, Contacts, School, Home, Canadian Holidays, Canadiens, Jours fériés au Canada"
local function execute_command(command)
local f = io.popen(command)
if f == nil then
return ""
end
local result = f:read("*all")
f:close()
return result
end
local function check_ical_buddy()
local result = execute_command("test -f " .. ical_buddy)
if result == "" then
wezterm.log_error("Error: iCalBuddy is not installed")
return false
end
return true
end
local function get_meeting_command(event_filter)
return string.format(
'%s --includeEventProps "title,datetime,attendees" --propertyOrder "title,datetime" --noCalendarNames --dateFormat "%%A" --includeOnlyEventsFromNowOn --limitItems 1 --excludeAllDayEvents --separateByDate --excludeCals "%s" %s',
ical_buddy,
ignored_cal,
event_filter
)
end
local function get_next_meeting()
local command = get_meeting_command("eventsToday")
local next_meeting = execute_command(command)
if next_meeting == "" then
return nil
end
return next_meeting
end
local function parse_result(ical_output)
local title, start_time, end_time, attendees
for line in ical_output:gmatch("[^\r\n]+") do
if line:match("%d%d:%d%d - %d%d:%d%d") then
start_time = line:match("(%d%d:%d%d) -")
end_time = line:match(" - (%d%d:%d%d)")
end
if line:match("attendees:") then
attendees = line:gsub("attendees: ", ""):gsub("^%s*(.-)%s*$", "%1")
end
end
title = ical_output:match("[^\r\n]+")
return { title = title, start_time = start_time, end_time = end_time, attendees = attendees }
end
local function calculate_times(start_time)
if not start_time then
return nil
end
local epoc_meeting = os.time({
hour = start_time:sub(1, 2),
min = start_time:sub(4, 5),
sec = 0,
})
local epoc_now = os.time()
local epoc_diff = epoc_meeting - epoc_now
local minutes_till_meeting = math.floor(epoc_diff / 60)
return { minutes_till_meeting = minutes_till_meeting, epoc_diff = epoc_diff }
end
local function display_popup(meeting)
local meeting_info = string.format(
"Title: %s\nStart Time: %s\nEnd Time: %s\nAttendees: %s",
meeting.title,
meeting.start_time,
meeting.end_time,
meeting.attendees
)
wezterm.gui.show_popup(meeting_info)
end
local function print_tmux_status(times, meeting)
local print_alert = string.format(
"#[fg=%s,bold,bg=%s] %s %s %s (%d minutes)",
theme_red,
theme_bg,
nerd_font_separator,
nerd_font_meeting,
meeting.start_time,
meeting.title,
times.minutes_till_meeting
)
if times.epoc_diff <= alert_popup_before_seconds then
display_popup(meeting)
elseif times.minutes_till_meeting < alert_if_in_next_minutes then
wezterm.log_info(print_alert)
else
wezterm.log_info(string.format("#[bold,bg=%s] %s %s", theme_bg, nerd_font_separator, nerd_font_free))
end
end
local function main()
if not check_ical_buddy() then
return
end
local next_meeting = get_next_meeting()
if not next_meeting then
return
end
local meeting = parse_result(next_meeting)
local times = calculate_times(meeting.start_time)
if not times then
return
end
print_tmux_status(times, meeting)
end
TIMER = wezterm.time.call_after(alert_popup_before_seconds, main)

View file

View file

@ -0,0 +1,22 @@
local wezterm = require('wezterm')
local function is_found(str, pattern)
return string.find(str, pattern) ~= nil
end
local function platform()
local is_win = is_found(wezterm.target_triple, 'windows')
local is_linux = is_found(wezterm.target_triple, 'linux')
local is_mac = is_found(wezterm.target_triple, 'darwin')
local os = is_win and 'windows' or is_linux and 'linux' or is_mac and 'mac' or 'unknown'
return {
os = os,
is_win = is_win,
is_linux = is_linux,
is_mac = is_mac,
}
end
print(Platform.os)
return platform

View file

@ -0,0 +1,95 @@
-- Pull in the wezterm API
local wezterm = require 'wezterm'
-- Define the terminal program to use
local term_program = "wezterm"
-- Define utility functions
local function run_command(command)
local f = io.popen(command)
if not f then
return nil, "Failed to execute command: " .. command
end
local output = f:read("*a")
f:close()
return output
end
-- Check if a directory is valid
local function is_directory_valid(directory)
local fd_output = run_command("fd --min-depth 1 --max-depth 5 --type d . " .. directory)
return fd_output ~= ""
end
-- Function to create or attach to a session
local function create_or_attach_session(selected_name, selected)
local sessions = wezterm.get_sessions()
for _, session in ipairs(sessions) do
if session.name == selected_name then
wezterm.launch(term_program, {
args = { "--to-session", selected_name },
cwd = selected,
})
return
end
end
wezterm.launch(term_program, {
args = { "--to-session", selected_name },
cwd = selected,
})
end
-- Main sessionizer function
local function run_sessionizer()
-- Use fzf to select a directory
local selected = run_command(
"fzf --preview 'tree -C {}' --preview-window=right:50%:wrap --height=100% --border --prompt='Select a directory: ' --bind='enter:accept,ctrl-c:abort' --query='' --no-mouse"
)
-- Check if no directory was selected
if not selected then
print("No directory selected. Exiting.")
return
end
-- Trim leading/trailing whitespace from the selected directory
selected = selected:gsub("^%s*(.-)%s*$", "%1")
local selected_name = selected:gsub("%.", "_")
local tmux_running = run_command("pgrep tmux")
-- Check if the directory is valid
if not is_directory_valid(selected) then
print("Invalid directory: " .. selected)
return
end
-- Check if tmux is not running and not attached to a session
if not tmux_running and not wezterm.target_cmdline() then
create_or_attach_session(selected_name, selected)
return
end
-- Check if the session already exists
local sessions = wezterm.get_sessions()
local found = false
for _, session in ipairs(sessions) do
if session.name == selected_name then
found = true
break
end
end
-- If session doesn't exist, spawn a new one
if not found then
wezterm.launch(term_program, {
args = { "--to-session", selected_name },
cwd = selected,
})
end
end
-- Export the sessionizer function
return {
run_sessionizer = run_sessionizer
}

View file

@ -0,0 +1,22 @@
local wezterm = require 'wezterm'
-- wezterm.gui is not available to the mux server, so take care to
-- do something reasonable when this config is evaluated by the mux
local function get_appearance()
if wezterm.gui then
return wezterm.gui.get_appearance()
end
return 'Dark'
end
local function scheme_for_appearance(appearance)
if appearance:find 'Dark' then
return 'Monokai (dark) (terminal.sexy)'
else
return 'Solarized (light) (terminal.sexy)'
end
end
return {
color_scheme = scheme_for_appearance(get_appearance()),
}

View file

@ -0,0 +1,39 @@
-- Import required modules
local wezterm = require "wezterm"
-- Function to create or attach to a session
local function create_or_attach_session(branch_name, command)
-- Get the current WezTerm window's session
local session = wezterm.target_window().parent
-- Clean branch name to use as window name
local clean_name = branch_name:gsub("[./]", "__")
-- Check if the window exists and select it, otherwise create a new window
local window = session:find_window_by_name(clean_name)
if not window then
window = session:new_tab(wezterm.term_muxed_pane_with_default { pane_title = clean_name })
else
window:activate()
end
-- Send command to the selected window if provided
if command then
window:send_string(command .. "\n")
end
end
-- Extract branch name from the first argument
local branch_name = arg[1]
-- Extract command to send to WezTerm from the remaining arguments
local command = table.concat(arg, " ", 2)
-- Check if branch name is provided
if not branch_name then
print("Branch name not provided. Exiting.")
return
end
-- Call function to create or attach to session
create_or_attach_session(branch_name, command)

335
wezterm/.wezterm.lua Normal file
View file

@ -0,0 +1,335 @@
-- Pull in the wezterm API
local wezterm = require("wezterm")
local act = wezterm.action
-- Pull custom modules
local theme = require("theme-switcher")
-- local sessionizer = require("sessionizer")
local config = {}
local keys = {}
local key_tables = {}
-- sessionizer.apply_to_config(config)
-- ical.apply_to_config(config)
-- This will hold the configuration.
if wezterm.config_builer then
config = wezterm.config_builder()
end
if wezterm.target_triple == "x86_64-pc-windows-msvc" then
-- Windows-specific settings
config.default_prog = { "wsl.exe", "~", "-d", "Ubuntu-20.04" }
elseif wezterm.target_triple == "x86_64-apple-darwin" then
-- macOS-specific settings
config.macos_window_background_blur = 10
config.default_prog = { "/bin/zsh" }
config.font = wezterm.font_with_fallback({
{ family = "MesloLGS NF", scale = 0.9 },
{ family = "font-symbols-only-nerds-font", scale = 0.9 },
})
elseif wezterm.target_triple == "x86_64-unknown-linux-gnu" then
-- Linux-specific settings
config.default_prog = { "/usr/bin/zsh" }
config.font = wezterm.font_with_fallback({
{ family = "MesloLGS NF", scale = 0.9 },
{ family = "Ubuntu Mono", scale = 0.9 },
})
end
config.check_for_updates = true
config.use_ime = true
config.term = "xterm-256color"
config.color_scheme = theme.color_scheme
config.line_height = 1.1
config.window_padding = {
left = 3,
right = 3,
top = 3,
bottom = 3,
}
config.inactive_pane_hsb = {
saturation = 0.9,
brightness = 0.7,
}
config.initial_rows = 50
config.initial_cols = 140
config.use_dead_keys = false
config.enable_scroll_bar = true
config.scrollback_lines = 5000
config.adjust_window_size_when_changing_font_size = false
config.window_decorations = "RESIZE | MACOS_FORCE_ENABLE_SHADOW"
config.hide_tab_bar_if_only_one_tab = true
config.window_frame = {
font = wezterm.font({ family = "Noto Sans", weight = "Regular" }),
}
config.hyperlink_rules = {
-- Matches: a URL in parens: (URL)
{
regex = "\\((\\w+://\\S+)\\)",
format = "$1",
highlight = 1,
},
-- Matches: a URL in brackets: [URL]
{
regex = "\\[(\\w+://\\S+)\\]",
format = "$1",
highlight = 1,
},
-- Matches: a URL in curly braces: {URL}
{
regex = "\\{(\\w+://\\S+)\\}",
format = "$1",
highlight = 1,
},
-- Matches: a URL in angle brackets: <URL>
{
regex = "<(\\w+://\\S+)>",
format = "$1",
highlight = 1,
},
-- Then handle URLs not wrapped in brackets
{
regex = "[^(]\\b(\\w+://\\S+[)/a-zA-Z0-9-]+)",
format = "$1",
highlight = 1,
},
-- implicit mailto link
{
regex = "\\b\\w+@[\\w-]+(\\.[\\w-]+)+\\b",
format = "mailto:$0",
},
}
config.leader = { key = "a", mods = "CTRL", timeout_milliseconds = 1000 }
keys = {
{ key = "LeftArrow", mods = "OPT", action = act.SendString("\x1bb") },
{ key = "RightArrow", mods = "OPT", action = act.SendString("\x1bf") },
-- The physical CMD key on OSX is the Alt key on Win/*nix, so map the common Alt-combo commands.
{ key = ".", mods = "CMD", action = act.SendString("\x1b.") },
{ key = "p", mods = "CMD", action = act.SendString("\x1bp") },
{ key = "n", mods = "CMD", action = act.SendString("\x1bn") },
{ key = "b", mods = "CMD", action = act.SendString("\x1bb") },
{ key = "f", mods = "CMD", action = act.SendString("\x1bf") },
-- Window management
{ key = "a", mods = "LEADER", action = act({ SendString = "`" }) },
{ key = "v", mods = "LEADER", action = act({ SplitVertical = { domain = "CurrentPaneDomain" } }) },
{ key = "b", mods = "LEADER", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) },
{ key = "z", mods = "LEADER", action = "TogglePaneZoomState" },
{ key = "c", mods = "LEADER", action = act({ SpawnTab = "CurrentPaneDomain" }) },
{ key = "n", mods = "LEADER", action = act({ ActivateTabRelative = 1 }) },
{ key = "p", mods = "LEADER", action = act({ ActivateTabRelative = -1 }) },
{ key = "h", mods = "LEADER", action = act.ActivatePaneDirection("Left") },
{ key = "j", mods = "LEADER", action = act.ActivatePaneDirection("Down") },
{ key = "k", mods = "LEADER", action = act.ActivatePaneDirection("Up") },
{ key = "l", mods = "LEADER", action = act.ActivatePaneDirection("Right") },
{ key = "H", mods = "LEADER", action = act({ AdjustPaneSize = { "Left", 5 } }) },
{ key = "J", mods = "LEADER", action = act({ AdjustPaneSize = { "Down", 5 } }) },
{ key = "K", mods = "LEADER", action = act({ AdjustPaneSize = { "Up", 5 } }) },
{ key = "L", mods = "LEADER", action = act({ AdjustPaneSize = { "Right", 5 } }) },
{ key = "`", mods = "LEADER", action = act.ActivateLastTab },
{ key = " ", mods = "LEADER", action = act.ActivateTabRelative(1) },
{ key = "x", mods = "LEADER", action = act({ CloseCurrentPane = { confirm = true } }) },
-- Run sessionizer with fzf
-- { key = "s", mods = "LEADER", action = sessionizer.run_sessionizer }
{ key = "w", mods = "LEADER", action = act.ShowTabNavigator },
-- Activate Copy Mode
{ key = "[", mods = "LEADER", action = act.ActivateCopyMode },
-- Paste from Copy Mode
{ key = "y", mods = "LEADER", action = act.PasteFrom("PrimarySelection") },
--open wezterm config quickly
{
key = ",",
mods = "LEADER",
action = act.SpawnCommandInNewTab({
cwd = os.getenv("WEZTERM_CONFIG_DIR"),
set_environment_variables = {
TERM = "screen-256color",
},
args = {
"/usr/local/bin/nvim",
os.getenv("WEZTERM_CONFIG_FILE"),
},
}),
},
{ key = "r", mods = "LEADER", action = act.ReloadConfiguration },
-- Swich to default workspace
{ key = "y", mods = "CTRL | SHIFT", action = act.SwitchToWorkspace({
name = "default",
}) },
--Switch to monitoring workspace
{
key = "m",
mods = "CTRL | SHIFT",
action = act.SwitchToWorkspace({
name = "monitoring",
spawn = {
args = { "top" },
},
}),
},
-- Create a new workspace with a randomm anem and switch to it
{ key = "i", mods = "CTRL | SHIFT", action = act.SwitchToWorkspace },
--Show launcher in fuzzy selecton mode
{
key = "s",
mods = "ALT",
action = act.ShowLauncherArgs({
flags = "FUZZY|WORKSPACES",
}),
},
}
for i = 1, 9 do
table.insert(keys, { key = tostring(i), mods = "LEADER", action = act.ActivateTab(i - 1) })
end
key_tables = {
copy_mode = {
{ key = "c", mods = "CTRL", action = act.CopyMode("Close") },
{ key = "q", mods = "NONE", action = act.CopyMode("Close") },
{ key = "Escape", mods = "NONE", action = act.CopyMode("Close") },
{ key = "h", mods = "NONE", action = act.CopyMode("MoveLeft") },
{ key = "j", mods = "NONE", action = act.CopyMode("MoveDown") },
{ key = "k", mods = "NONE", action = act.CopyMode("MoveUp") },
{ key = "l", mods = "NONE", action = act.CopyMode("MoveRight") },
{ key = "LeftArrow", mods = "NONE", action = act.CopyMode("MoveLeft") },
{ key = "DownArrow", mods = "NONE", action = act.CopyMode("MoveDown") },
{ key = "UpArrow", mods = "NONE", action = act.CopyMode("MoveUp") },
{ key = "RightArrow", mods = "NONE", action = act.CopyMode("MoveRight") },
{ key = "RightArrow", mods = "ALT", action = act.CopyMode("MoveForwardWord") },
{ key = "f", mods = "ALT", action = act.CopyMode("MoveForwardWord") },
{ key = "Tab", mods = "NONE", action = act.CopyMode("MoveForwardWord") },
{ key = "LeftArrow", mods = "ALT", action = act.CopyMode("MoveBackwardWord") },
{ key = "b", mods = "ALT", action = act.CopyMode("MoveBackwardWord") },
{ key = "Tab", mods = "SHIFT", action = act.CopyMode("MoveBackwardWord") },
{ key = "0", mods = "NONE", action = act.CopyMode("MoveToStartOfLine") },
{ key = "Enter", mods = "NONE", action = act.CopyMode("MoveToStartOfNextLine") },
{ key = "$", mods = "NONE", action = act.CopyMode("MoveToEndOfLineContent") },
{ key = "$", mods = "SHIFT", action = act.CopyMode("MoveToEndOfLineContent") },
{ key = "^", mods = "NONE", action = act.CopyMode("MoveToStartOfLineContent") },
{ key = "^", mods = "SHIFT", action = act.CopyMode("MoveToStartOfLineContent") },
{ key = "v", mods = "NONE", action = act.CopyMode({ SetSelectionMode = "Cell" }) },
{ key = "V", mods = "NONE", action = act.CopyMode({ SetSelectionMode = "Line" }) },
{ key = "V", mods = "SHIFT", action = act.CopyMode({ SetSelectionMode = "Line" }) },
{ key = "v", mods = "CTRL", action = act.CopyMode({ SetSelectionMode = "Block" }) },
{ key = "G", mods = "NONE", action = act.CopyMode("MoveToScrollbackBottom") },
{ key = "G", mods = "SHIFT", action = act.CopyMode("MoveToScrollbackBottom") },
{ key = "g", mods = "NONE", action = act.CopyMode("MoveToScrollbackTop") },
{ key = "H", mods = "NONE", action = act.CopyMode("MoveToViewportTop") },
{ key = "H", mods = "SHIFT", action = act.CopyMode("MoveToViewportTop") },
{ key = "M", mods = "NONE", action = act.CopyMode("MoveToViewportMiddle") },
{ key = "M", mods = "SHIFT", action = act.CopyMode("MoveToViewportMiddle") },
{ key = "L", mods = "NONE", action = act.CopyMode("MoveToViewportBottom") },
{ key = "L", mods = "SHIFT", action = act.CopyMode("MoveToViewportBottom") },
{ key = "o", mods = "NONE", action = act.CopyMode("MoveToSelectionOtherEnd") },
{ key = "O", mods = "NONE", action = act.CopyMode("MoveToSelectionOtherEndHoriz") },
{ key = "O", mods = "SHIFT", action = act.CopyMode("MoveToSelectionOtherEndHoriz") },
{ key = "PageUp", mods = "NONE", action = act.CopyMode("PageUp") },
{ key = "PageDown", mods = "NONE", action = act.CopyMode("PageDown") },
{ key = "b", mods = "CTRL", action = act.CopyMode("PageUp") },
{ key = "f", mods = "CTRL", action = act.CopyMode("PageDown") },
-- Enter y to copy and quit the copy mode.
{
key = "y",
mods = "NONE",
action = act.Multiple({
act.CopyTo("ClipboardAndPrimarySelection"),
act.CopyMode("Close"),
}),
},
-- Enter search mode to edit the pattern.
-- When the search pattern is an empty string the existing pattern is preserved
{ key = "/", mods = "NONE", action = act({ Search = { CaseSensitiveString = "" } }) },
{ key = "?", mods = "NONE", action = act({ Search = { CaseInSensitiveString = "" } }) },
{ key = "n", mods = "CTRL", action = act({ CopyMode = "NextMatch" }) },
{ key = "p", mods = "CTRL", action = act({ CopyMode = "PriorMatch" }) },
},
search_mode = {
{ key = "Escape", mods = "NONE", action = act({ CopyMode = "Close" }) },
-- Go back to copy mode when pressing enter, so that we can use unmodified keys like "n"
-- to navigate search results without conflicting with typing into the search area.
{ key = "Enter", mods = "NONE", action = "ActivateCopyMode" },
{ key = "c", mods = "CTRL", action = "ActivateCopyMode" },
{ key = "n", mods = "CTRL", action = act({ CopyMode = "NextMatch" }) },
{ key = "p", mods = "CTRL", action = act({ CopyMode = "PriorMatch" }) },
{ key = "r", mods = "CTRL", action = act.CopyMode("CycleMatchType") },
{ key = "u", mods = "CTRL", action = act.CopyMode("ClearPattern") },
},
}
-- move prompt to the bottom
local function move_prompt_to_bottom()
os.execute("tput cup $LINES")
end
config.on_start = move_prompt_to_bottom()
config.keys = keys
config.key_tables = key_tables
wezterm.on("update-right-status", function(window)
local stat = window:active_workspace()
if window:active_key_table() then
stat = window:active_key_table()
end
if window:leader_is_active() then
stat = "L"
end
-- "Wed Mar 3 08:14"
local date = wezterm.strftime("%a %b %-d %H:%M ")
local bat = ""
for _, b in ipairs(wezterm.battery_info()) do
bat = string.format("%.0f%%", b.state_of_charge * 100)
end
window:set_right_status(wezterm.format({
{ Text = stat },
{ Text = " | " },
{ Text = date },
{ Text = " | " },
{ Text = bat },
{ Text = " " },
}))
end)
config.default_prog = { "zsh" }
-- and finally, return the configuration to wezterm
return config