-
Notifications
You must be signed in to change notification settings - Fork 0
wezterm
WezTerm is the next-generation terminal emulator made by Wez Furlong himself, one of the core maintainers of PHP and other great software projects
- more than that it feels like the terminal emulator that is designed to go hand-in-hand with Neovim as our primary editor
This is obvious from the very start with the fact that our configuration is created using a standard lua file and we can find evidence of a Neovim-like mindset everywhere I look.
- from the fact that many vim keybindings are already set
- as well as the fact that we have a vim-like understanding of panes, windows, and tabs which roughly translate to the buffers, windows, and tabs mentality of (neo)vim
First, we need to import and define the config which we will use to set all of our settings
local wezterm = require("wezterm")
local config = {}
if wezterm.config_builder then
config = wezterm.config_builder()
end
local act = wezterm.action
- First, we just need to import the wezterm library which is available any time we are within wezterm itself
- Then we start an empty config table, and we will proceed to add to this table throughout our work in the future sections
- Next, if we have the config builder available (more just about versioning since this is a new feature) we can turn the wezterm config variable into a builder object
- These builder objects make it easier to see good error messages and make it easier to configure the terminal in general
- Finally we will sometimes use the action module of the wezterm module so we are going to make this specific module a variable so we can easily refer to it going forward
First, we set things that are always on for wezterm
config.color_scheme = "nord"
config.font = wezterm.font("JetBrains Mono")
config.default_prog = { "C:\\Program Files\\PowerShell\\7\\pwsh.exe", "-ExecutionPolicy", "RemoteSigned" }
- First, we set the colorscheme out of the literally hundered colorschemes available
- Next, we set the font to
Monoid NF
which is a mono nerd font that I usually download manually from the normal nerdfont page - finally, since we always interact through wezterm through windows for now we are going to be sure to set the shell to powershell 7
- this prevents it from doing the default of setting it to the
cmd
shell
- this prevents it from doing the default of setting it to the
We will need the ability to check what program is running in the foreground for later.
For now, here is the equivalent the unix basename()
command
this was lifted from the knowledge documentation of smart-splits.nvim
local function basename(s)
return string.gsub(s, '(.*[/\\])(.*)', '%2')
end
- here we are taking in a string and removing the leading
/
, and\\
characters, as well as the text between them so we just get to the final piece of text- This is assumed to be the process running in the current pane which will be used later
Now that we have the process name, we want to check wether or not we are in vim or neovim. This is relevant because for a few of the hotkeys we may opt to send the key combination to (neo)vim rather than just doing the wezterm hotkey itself
local function is_vim(pane)
local process_name = basename(pane:get_foreground_process_name())
return process_name == 'nvim.exe' or process_name == 'vim.exe'
end
- This is a simple function that applies the basename function defined about to the foreground process name, and will ask if we are in vim or neovim
- We are using this for a check later on as we try to define this shared behavior with
smart-splits.nvim
- We are using this for a check later on as we try to define this shared behavior with
The traditional keymap layout is already okay but we want to expand this
The mechanic that wezterm introduces is key tables. These are similar to vim modes in that we can define keymaps that are only applicable for certain contexts
- We can then set these contexts and do the hotkeys we have defined specifically for these context panes
Like Neovim, we can have a leader key(s) which will serve as a sort of gateway to the rest of the hotkeys we will be defining later on
config.leader = { key = "Space", mods = "CTRL|SHIFT" }
- while we want to implement the leader concept, we cant do the same thing as vim because it isn't actually a modal editor, space is still an input character most of the time
- therefore, we need to use some modifier keys on top to ensure we can activite it no matter what application we are using (including neovim!)
- Now we can simply say the mod is
"LEADER"
on top of our keys and it will know to put the hotkey behind our newly defined leader key for wezterm
The part is to actually set both the keymaps, and the key tables themselves within the wezterm config builder
local keymaps = {}
local direction_keys = {
Left = 'h',
Down = 'j',
Up = 'k',
Right = 'l',
-- reverse lookup
h = 'Left',
j = 'Down',
k = 'Up',
l = 'Right',
}
- First, we set the main keymaps that will either do an action or enter one of our keymap modes
- Next, we set the keymaps that are used during our various modes in wezterm
- Finally we define some direction_keys for movement with a vim-like mindset to use later on
Like (neo)vim, wezterm understands things through panes, windows, and tabs, similar to vim's buffers, windows, and tabs.
More than that, thanks to smart-splits.nvim, we can actually use the same hotkeys we define in neovim to manage the splits of wezterm, giving us a crazy good workflow for finally opening, moving, selecting, and closing panes like a normal neovim window.
We define the function to do both resizing and movement of panes below:
local function split_nav(resize_or_move, key)
return {
key = key,
mods = resize_or_move == 'resize' and 'META' or 'CTRL',
action = wezterm.action_callback(function(win, pane)
if is_vim(pane) then
-- pass the keys through to vim/nvim
win:perform_action({
SendKey = { key = key, mods = resize_or_move == 'resize' and 'META' or 'CTRL' },
}, pane)
else
if resize_or_move == 'resize' then
win:perform_action({ AdjustPaneSize = { direction_keys[key], 3 } }, pane)
else
win:perform_action({ ActivatePaneDirection = direction_keys[key] }, pane)
end
end
end),
}
end
- This returns a table that defines a keymap given 2 paramaters, the key, and the meta key used
- The real magic is that we use that
is_vim()
function to check if we are in vim at the same time and instead pass this hotkey to vim if that is what we are looking to do- this is awesome because we can seamlessly use the same hotkey between neovim and wezterm, we don't have to define and memorize a different set of hotkeys for wezterm stuff as neovim stuff
- If we arent in vim though, we actually run the relevant wezterm function
-
AdjustPaneSize
for resizing - and
ActivatePaneDirection
for changing pane focus
-
With the groundwork laid, we should just be able to insert the relevant hotkey into our larger list of keymaps using the standard insert method and falling the function for the insertion
table.insert(keymaps,split_nav('resize', 'h'))
table.insert(keymaps,split_nav('resize', 'j'))
table.insert(keymaps,split_nav('resize', 'k'))
table.insert(keymaps,split_nav('resize', 'l'))
Same as before, just inserting the appropriate keymaps for the function we are going for at this point
table.insert(keymaps,split_nav('move', 'h'))
table.insert(keymaps,split_nav('move', 'j'))
table.insert(keymaps,split_nav('move', 'k'))
table.insert(keymaps,split_nav('move', 'l'))
Everyone is in love with the command pallet idea after VSCode popularized it so it goes with the wezterm emulator so that we can bring up a quick menu to quickly do several commands including splitting, making new tabs, and other requirements of working through these pieces
We can set the command pallet hotkey with the below snippet:
table.insert(keymaps,{
key = 'p',
mods = 'CTRL|ALT',
action = act.ActivateCommandPalette,
})
Not to be confused with quick search mode, quick select mode can be thought of as a more precise version of quick search. Whereas one is mostly just a case of searching for instances of a certain string based on the users' input, quick select is specficially tailored towards quickly grabbing pre-defined text patterns and giving users the ability to do more with these selections than merely putting them in their clipboard
The following snippet will bring up the quick select mode without any arguments
table.insert(keymaps, { key = 's', mods = 'LEADER', action = act.QuickSelect })
Wezterm makes it easy to close windows by default, but gives not hotkeys for closing panes, so to remedy that we just add the following keymap for that specific use case:
table.insert(keymaps, {
key = "c",
mods = "LEADER",
action = act.CloseCurrentPane({
confirm = true,
}),
})
Wezterm has a launcher that can be used similar to windows terminal where we can search for the different kinds of shells and machines to connect to and open them as a new window within the current instance of wezterm
Here is a simple leader snippet to pull up the launcher in a new window:
table.insert(keymaps, {
key = "l",
mods = "LEADER",
action = act.ShowLauncher,
})
Next we want to unbind the default keybinding to put WezTerm into Full Screen mode because it is conflicting with the default binding in Neorg for continuing a list item
table.insert(keymaps, {
key = "Enter",
mods = "ALT",
action = act.DisableDefaultAssignment,
})
table.insert(keymaps, {key = "F11", action = act.ToggleFullScreen})
With all that done, we are ready to return our config to WezTerm so it can actually use the configuration settings we have defined
config.keys = keymaps
return config
- remember, nothing is real until this config is returned at the end!
- commenting this line will return us to a normal default config for testing purposes