commit 35ec6f0de6821cf4b40b823a4f08c627a8d91e90 Author: rootiest Date: Fri Aug 16 14:50:01 2024 -0400 feat(wezterm): initial commit The initial release of the rootiest-wezterm config BREAKING CHANGE: First Commit! diff --git a/.screenshots/term.png b/.screenshots/term.png new file mode 100644 index 0000000..5586dce Binary files /dev/null and b/.screenshots/term.png differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..90de350 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +# Rootiest WezTerm Configuration + +```none + ██▀███ ▒█████ ▒█████ ▄▄▄█████▓ ██▓▓█████ ██████ ▄▄▄█████▓ +▓██ ▒ ██▒▒██▒ ██▒▒██▒ ██▒▓ ██▒ ▓▒▓██▒▓█ ▀ ▒██ ▒ ▓ ██▒ ▓▒ +▓██ ░▄█ ▒▒██░ ██▒▒██░ ██▒▒ ▓██░ ▒░▒██▒▒███ ░ ▓██▄ ▒ ▓██░ ▒░ +▒██▀▀█▄ ▒██ ██░▒██ ██░░ ▓██▓ ░ ░██░▒▓█ ▄ ▒ ██▒░ ▓██▓ ░ +░██▓ ▒██▒░ ████▓▒░░ ████▓▒░ ▒██▒ ░ ░██░░▒████▒▒██████▒▒ ▒██▒ ░ +░ ▒▓ ░▒▓░░ ▒░▒░▒░ ░ ▒░▒░▒░ ▒ ░░ ░▓ ░░ ▒░ ░▒ ▒▓▒ ▒ ░ ▒ ░░ + ░▒ ░ ▒░ ░ ▒ ▒░ ░ ▒ ▒░ ░ ▒ ░ ░ ░ ░░ ░▒ ░ ░ ░ + ░░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ▒ ░ ░ ░ ░ ░ ░ + ░ ░ ░ ░ ░ ░ ░ ░ ░ + +██ ██ ███████ ███████ ████████ ███████ ██████ ███ ███ +██ ██ ██ ███ ██ ██ ██ ██ ████ ████ +██ █ ██ █████ ███ ██ █████ ██████ ██ ████ ██ +██ ███ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██ + ███ ███ ███████ ███████ ██ ███████ ██ ██ ██ ██ + + ▄████▄ ▒█████ ███▄ █ █████▒ + ▒██▀ ▀█ ▒██▒ ██▒ ██ ▀█ █ ▓██ ▒ + ▒▓█ ▄ ▒██░ ██▒▓██ ▀█ ██▒▒████ ░ + ▒▓▓▄ ▄██▒▒██ ██░▓██▒ ▐▌██▒░▓█▒ ░ + ▒ ▓███▀ ░░ ████▓▒░▒██░ ▓██░░▒█░ + ░ ░▒ ▒ ░░ ▒░▒░▒░ ░ ▒░ ▒ ▒ ▒ ░ + ░ ▒ ░ ▒ ▒░ ░ ░░ ░ ▒░ ░ + ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ + ░ ░ ░ ░ ░ + ░ + ╭─────────────╮ + ╭─────────────╮ + │ $W │ + │ │ + │ │ + ╰─────────────╯ +``` + +The rootiest WezTerm configuration you will ever see! + +## Installation + +1. Install [WezTerm](https://wezfurlong.org/wezterm/installation.html) (nightly) + +2. Install pre-requisites + + - Required + - [Nerd Fonts](https://github.com/ryanoasis/nerd-fonts/) - + Nerd Fonts glyphs are required. + - Optional + - [fish](https://fishshell.com/) + - [neovim](https://neovim.io/) + +3. Backup your current WezTerm configuration (if you have one) + + ```bash + mv ~/.config/wezterm ~/.config/wezterm.bak + mv ~/.wezterm.lua ~/.wezterm.lua.bak + ``` + +4. Clone the repository + + ```bash + git clone https://github.com/rootiest/rootiest-wezterm.git ~/.config/wezterm + ``` + +5. **Enjoy!** 🎉 + +## Features + +- Smart key bindings +- Leader key and modal mode +- Session mux/management/resurrection +- Advanced tab management +- Splits and panes integrate seamlessly with NeoVim +- Seamless integration with fish shell +- Catppuccin theme by default +- Integrates cleanly with other Rootiest projects + +## Screenshots + +![Rootiest WezTerm](.screenshots/term.png) + +## Companion Tools + +[Rootiest Fish Conf](https://github.com/rootiest/rootiest-fish) - +Fish shell configuration that pairs well with this WezTerm configuration +and the NeoVim configuration. + +[Rootiest Neovim](https://github.com/rootiest/rootiest-nvim) - +A NeoVim config built to work alongside this and the fish config. + +[Nerd Fonts](https://github.com/ryanoasis/nerd-fonts/) - +A collection of fonts that include many icons and glyphs that are used in this configuration. + +## Dotfiles + +[Rootiest Dotfiles](https://github.com/rootiest/dotfiles) + +## Credits + +- [wezterm](https://github.com/wez/wezterm) +- [resurrect.wezterm](https://github.com/MLFlexer/resurrect.wezterm) +- [smart-splits.nvim](https://github.com/mrjones2014/smart-splits.nvim) +- [wezterm-bar](https://github.com/nekowinston/wezterm-bar) diff --git a/config/colors.lua b/config/colors.lua new file mode 100644 index 0000000..dff80e4 --- /dev/null +++ b/config/colors.lua @@ -0,0 +1,53 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ COLORS │ +-- ╰─────────────────────────────────────────────────────────╯ + +return { + -- Color Scheme + color_scheme = "Catppuccin Frappe", + -- Tab Bar Colors + colors = { + tab_bar = { + inactive_tab_edge = "#484D69", + active_tab = { + bg_color = "#CA9EE6", + fg_color = "#232634", + intensity = "Normal", + underline = "None", + italic = false, + strikethrough = false, + }, + inactive_tab = { + bg_color = "#484D69", + fg_color = "#C6D0F5", + }, + inactive_tab_hover = { + bg_color = "#3b3052", + fg_color = "#C6D0F5", + italic = true, + intensity = "Bold", + }, + new_tab = { + bg_color = "#737994", + fg_color = "#C6D0F5", + intensity = "Bold", + underline = "None", + italic = false, + strikethrough = false, + }, + new_tab_hover = { + bg_color = "#3b3052", + fg_color = "#C6D0F5", + italic = true, + intensity = "Bold", + }, + }, + }, + -- Titlebar Colors + window_frame = { + active_titlebar_bg = "#232634", + inactive_titlebar_bg = "#303446", + }, + -- Terminal Variable + term = "wezterm", +} diff --git a/config/font.lua b/config/font.lua new file mode 100644 index 0000000..b7a6613 --- /dev/null +++ b/config/font.lua @@ -0,0 +1,46 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ FONTS │ +-- ╰─────────────────────────────────────────────────────────╯ + +return { + -- Terminal Font + font = WEZTERM.font({ + family = "Iosevka", + weight = "Regular", + harfbuzz_features = { + "VSAH=7", + "VSAF=3", + "VSAI=3", + "VSAJ=8", + "VSAM=4", + "VLAB=5", + "cv10=7", + "cv41=3", + "cv44=6", + "cv07=4", + }, + }), + font_size = 12.0, + -- Fancy Tab Bar Font + window_frame = { + font = WEZTERM.font({ + family = "Iosevka", + weight = "Medium", + harfbuzz_features = { + "VSAH=7", + "VSAF=3", + "VSAI=3", + "VSAJ=8", + "VSAM=4", + "VLAB=5", + "cv10=7", + "cv41=3", + "cv44=6", + "cv07=4", + }, + }), + font_size = 11, + }, + -- Cursor Shape + default_cursor_style = "BlinkingBar", +} diff --git a/config/keys.lua b/config/keys.lua new file mode 100644 index 0000000..de047ae --- /dev/null +++ b/config/keys.lua @@ -0,0 +1,50 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ KEYS │ +-- ╰─────────────────────────────────────────────────────────╯ + +-- Define action table +local act = WEZTERM.action + +return { + leader = { key = " ", mods = "CTRL", timeout_milliseconds = 1500 }, + keys = { + { key = "a", mods = "LEADER|CTRL", action = WEZTERM.action.SendKey({ key = "a", mods = "CTRL" }) }, + { key = "|", mods = "LEADER|SHIFT", action = WEZTERM.action.SplitHorizontal({ domain = "CurrentPaneDomain" }) }, + { key = "_", mods = "LEADER|SHIFT", action = WEZTERM.action.SplitVertical({ domain = "CurrentPaneDomain" }) }, + { key = "h", mods = "SHIFT|CTRL", action = act.ActivatePaneDirection("Left") }, + { key = "l", mods = "SHIFT|CTRL", action = act.ActivatePaneDirection("Right") }, + { key = "k", mods = "SHIFT|CTRL", action = act.ActivatePaneDirection("Up") }, + { key = "j", mods = "SHIFT|CTRL", action = act.ActivatePaneDirection("Down") }, + { key = "h", mods = "ALT", action = act.AdjustPaneSize({ "Left", 1 }) }, + { key = "l", mods = "ALT", action = act.AdjustPaneSize({ "Right", 1 }) }, + { key = "k", mods = "ALT", action = act.AdjustPaneSize({ "Up", 1 }) }, + { key = "j", mods = "ALT", action = act.AdjustPaneSize({ "Down", 1 }) }, + { + key = "s", + mods = "ALT", + action = WEZTERM.action.Multiple({ + WEZTERM.action_callback(function(_, _) + RESURRECT.save_state(RESURRECT.workspace_state.get_workspace_state()) + end), + }), + }, + { + key = "r", + mods = "ALT", + action = WEZTERM.action.Multiple({ + WEZTERM.action_callback(function(win, pane) + RESURRECT.fuzzy_load(win, pane, function(id, _) + id = string.match(id, "([^/]+)$") + id = string.match(id, "(.+)%..+$") + local state = RESURRECT.load_state(id, "workspace") + RESURRECT.workspace_state.restore_workspace(state, { + relative = true, + restore_text = true, + on_pane_restore = RESURRECT.tab_state.default_on_pane_restore, + }) + end) + end), + }), + }, + }, +} diff --git a/config/window.lua b/config/window.lua new file mode 100644 index 0000000..fdd649e --- /dev/null +++ b/config/window.lua @@ -0,0 +1,20 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ WINDOW │ +-- ╰─────────────────────────────────────────────────────────╯ + +return { + -- Set the initial size + initial_cols = 180, + initial_rows = 38, + + -- Set the window padding + window_padding = { + left = 0, + right = 0, + top = 10, + bottom = 0, + }, + + -- Set the animation framerate + animation_fps = 120, +} diff --git a/options.lua b/options.lua new file mode 100644 index 0000000..55d43b7 --- /dev/null +++ b/options.lua @@ -0,0 +1,56 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ OPTIONS │ +-- ╰─────────────────────────────────────────────────────────╯ +-- Load and merge configurations from the 'config' directory + +local M = {} + +-- Function to require all Lua files in a directory and merge them +local function require_configs(dir) + -- Check if the path exists + local path = dir or os.getenv("HOME") .. "/.config/wezterm/config/" + if not path then + print("Directory path is nil. Unable to load configurations.") + return + end + + -- Open the directory + local pfile, open_err = io.popen('ls "' .. path .. '"') + if not pfile then + print("Error opening directory:", open_err) + return + end + + local configs = {} + + -- Iterate over the files in the directory + for file in pfile:lines() do + if file:match("%.lua$") then + local module_name = file:gsub("%.lua$", "") + local status, config = pcall(require, "config." .. module_name) + if status and type(config) == "table" then + configs[module_name] = config + elseif not status then + print("Error requiring config:", module_name, config) + else + print("Warning: Config not a table:", module_name) + end + end + end + + pfile:close() + + -- Merge configurations into CONFIG + for _, config in pairs(configs) do + for k, v in pairs(config) do + CONFIG[k] = v + end + end +end + +function M.setup() + -- Load all configurations from the 'config' directory + require_configs() +end + +return M diff --git a/plugins.lua b/plugins.lua new file mode 100644 index 0000000..365d7ea --- /dev/null +++ b/plugins.lua @@ -0,0 +1,48 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ PLUGINS │ +-- ╰─────────────────────────────────────────────────────────╯ +-- Load plugins from the 'plugins' directory + +local M = {} + +-- Function to require all Lua files in a directory +function M.require_plugins(dir) + -- Check if the path exists + local path = dir or os.getenv("HOME") .. "/.config/wezterm/plugins/" + if not path then + print("Directory path is nil. Unable to load plugins.") + return + end + + -- Open the directory + local pfile, open_err = io.popen('ls "' .. path .. '"') + if not pfile then + print("Error opening directory:", open_err) + return + end + + -- Iterate over the files in the directory + for file in pfile:lines() do + if file:match("%.lua$") then + local module_name = file:gsub("%.lua$", "") + local status, require_err = pcall(require, "plugins." .. module_name) + if not status then + print("Error requiring plugin:", module_name, require_err) + end + end + end + + pfile:close() +end + +-- Function to update all plugins +function M.update_plugins() + WEZTERM.plugin.update_all() +end + +function M.setup() + -- Load all plugins from the 'plugins' directory + M.require_plugins() +end + +return M diff --git a/plugins/hyperlinks.lua b/plugins/hyperlinks.lua new file mode 100644 index 0000000..5a6f50e --- /dev/null +++ b/plugins/hyperlinks.lua @@ -0,0 +1,16 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ HYPERLINKS │ +-- ╰─────────────────────────────────────────────────────────╯ + +local M = {} + +-- Hyperlink Rules +CONFIG.hyperlink_rules = WEZTERM.default_hyperlink_rules() + +-- Add support for GitHub link style +table.insert(CONFIG.hyperlink_rules, { + regex = [[["]?([\w\d]{1}[-\w\d]+)(/){1}([-\w\d\.]+)["]?]], + format = "https://wwwezterm.github.com/$1/$3", +}) + +return M diff --git a/plugins/resurrect.lua b/plugins/resurrect.lua new file mode 100644 index 0000000..1df419f --- /dev/null +++ b/plugins/resurrect.lua @@ -0,0 +1,31 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ RESURRECT │ +-- ╰─────────────────────────────────────────────────────────╯ + +local M = {} + +-- Load Resurrect plugin +RESURRECT = WEZTERM.plugin.require("https://github.com/MLFlexer/resurrect.wezterm") + +-- Set the periodic save interval +RESURRECT.periodic_save(60) + +-- load the state whenever I create a new workspace +WEZTERM.on("smart_workspace_switcher.workspace_switcher.created", function(window, _, label) + local workspace_state = RESURRECT.workspace_state + + workspace_state.restore_workspace(RESURRECT.load_state(label, "workspace"), { + window = window, + relative = true, + restore_text = true, + on_pane_restore = RESURRECT.tab_state.default_on_pane_restore, + }) +end) + +-- Save the state whenever I select a workspace +WEZTERM.on("smart_workspace_switcher.workspace_switcher.selected", function(_, _, _) + local workspace_state = RESURRECT.workspace_state + RESURRECT.save_state(workspace_state.get_workspace_state()) +end) + +return M diff --git a/plugins/smart_splits.lua b/plugins/smart_splits.lua new file mode 100644 index 0000000..15fc432 --- /dev/null +++ b/plugins/smart_splits.lua @@ -0,0 +1,24 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ SMART-SPLITS │ +-- ╰─────────────────────────────────────────────────────────╯ + +local M = {} + +-- Load Smart-Splits plugin +SMART_SPLITS = WEZTERM.plugin.require("https://github.com/mrjones2014/smart-splits.nvim") + +-- Apply Smart-Splits configuration +SMART_SPLITS.apply_to_config(CONFIG, { + -- directional keys to use in order of: left, down, up, right + direction_keys = { + move = { "h", "j", "k", "l" }, -- Move with CTRL+H, CTRL+J, CTRL+K, CTRL+L + resize = { "h", "j", "k", "l" }, -- Resize with ALT+h, ALT+j, ALT+k, ALT+l + }, + -- modifier keys to combine with direction_keys + modifiers = { + move = "CTRL|SHIFT", -- modifier to use for pane movement + resize = "ALT", -- modifier to use for pane resize + }, +}) + +return M diff --git a/plugins/wezbar.lua b/plugins/wezbar.lua new file mode 100644 index 0000000..c003970 --- /dev/null +++ b/plugins/wezbar.lua @@ -0,0 +1,44 @@ +-- ╭─────────────────────────────────────────────────────────╮ +-- │ WEZBAR │ +-- ╰─────────────────────────────────────────────────────────╯ + +local M = {} + +-- Load Wezbar plugin +WEZBAR = WEZTERM.plugin.require("https://github.com/nekowinston/wezterm-bar") + +-- Configure wezbar +WEZBAR.apply_to_config(CONFIG, { + position = "top", + max_width = 32, + dividers = "arrows", -- or "slant_left", "arrows", "rounded", false + indicator = { + leader = { + enabled = true, + off = " ", + on = " ", + }, + mode = { + enabled = true, + names = { + resize_mode = "RESIZE", + copy_mode = "VISUAL", + search_mode = "SEARCH", + }, + }, + }, + tabs = { + numerals = "arabic", -- or "roman" + pane_count = "superscript", -- or "subscript", false + brackets = { + active = { "", ":" }, + inactive = { "", ":" }, + }, + }, + clock = { -- note that this overrides the whole set_right_status + enabled = true, + format = "%a %R ", -- use https://wezfurlong.org/wezterm/config/lua/wezterm.time/Time/format.html + }, +}) + +return M diff --git a/wezterm.lua b/wezterm.lua new file mode 100644 index 0000000..0022977 --- /dev/null +++ b/wezterm.lua @@ -0,0 +1,25 @@ +-- __ __ ________ +-- / | _ / | / | +-- $$ | / \ $$ | ______ ________$$$$$$$$/______ ______ _____ ____ +-- $$ |/$ \$$ | / \ / | $$ | / \ / \ / \/ \ +-- $$ /$$$ $$ |/$$$$$$ |$$$$$$$$/ $$ |/$$$$$$ |/$$$$$$ |$$$$$$ $$$$ | +-- $$ $$/$$ $$ |$$ $$ | / $$/ $$ |$$ $$ |$$ | $$/ $$ | $$ | $$ | +-- $$$$/ $$$$ |$$$$$$$$/ /$$$$/__ $$ |$$$$$$$$/ $$ | $$ | $$ | $$ | +-- $$$/ $$$ |$$ |/$$ | $$ |$$ |$$ | $$ | $$ | $$ | +-- $$/ $$/ $$$$$$$/ $$$$$$$$/ $$/ $$$$$$$/ $$/ $$/ $$/ $$/ +-------------------------------------------------------------------------------- +-- https://github.com/wez/wezterm/ + +-- Load WezTerm module +WEZTERM = require("wezterm") +-- Load Config Builder +CONFIG = WEZTERM.config_builder() + +-- Load Options +require("options").setup() + +-- Load Plugins +require("plugins").setup() + +-- Return configuration +return CONFIG