wezterm
wezterm copied to clipboard
add ability to remap modifier and caps lock keys
Is your feature request related to a problem? Please describe. No
Describe the solution you'd like Because I use CAPS key as Command key on macOS, It can save many times when I use Command key. And in Terminal I also want to remap my command key to control key, because many hot key will use control key.
Describe alternatives you've considered No
Additional context No
Remapping modifiers cross platform is potentially a bit gnarly, so I'm not eager to work on this.
I would suggest looking at https://karabiner-elements.pqrs.org/ to remap globally; that's what I use on macOS to remap caps lock to a dual role (tap = ESC, hold = control) key.
Got it and thanks for your quick reply.
Also want to check if remap Command to Alt and Option to Super is possible. I usually use Emacs inside terminal but want consistent Meta/Alt key across Mac and Linux.
I find a way in Karabiner Elements to swap Option <-> Command only for WezTerm, for others: Here is the example and my configs:
{
"conditions": [
{
"bundle_identifiers": [
"^com\\.github\\.wez\\.wezterm$"
],
"type": "frontmost_application_if"
}
],
"description": "WezTerm Left Option to Cmd",
"from": {
"key_code": "left_option",
"modifiers": {
"optional": [
"any"
]
}
},
"to": [
{
"key_code": "left_command",
"lazy": true
}
],
"type": "basic"
},
{
"conditions": [
{
"bundle_identifiers": [
"^com\\.github\\.wez\\.wezterm$"
],
"type": "frontmost_application_if"
}
],
"description": "WezTerm Left Cmd to Option",
"from": {
"key_code": "left_command",
"modifiers": {
"optional": [
"any"
]
}
},
"to": [
{
"key_code": "left_option",
"lazy": true
}
],
"type": "basic"
}
Thx @qqldd, this is exactly what I want~ I made some changes to the karabiner config~
{
"title": "WezTerm switch option with cmd",
"rules": [
{
"description": "WezTerm Left Option to Cmd",
"manipulators": [
{
"conditions": [
{
"bundle_identifiers": ["^com\\.github\\.wez\\.wezterm$"],
"type": "frontmost_application_if"
}
],
"from": {
"key_code": "left_option",
"modifiers": {
"optional": ["any"]
}
},
"to": [
{
"key_code": "left_command",
"lazy": true
}
],
"type": "basic"
}
]
},
{
"description": "WezTerm Left Cmd to Option",
"manipulators": [
{
"conditions": [
{
"bundle_identifiers": ["^com\\.github\\.wez\\.wezterm$"],
"type": "frontmost_application_if"
}
],
"from": {
"key_code": "left_command",
"modifiers": {
"optional": ["any"]
}
},
"to": [
{
"key_code": "left_option",
"lazy": true
}
],
"type": "basic"
}
]
}
]
}
Remapping modifiers cross platform is potentially a bit gnarly, so I'm not eager to work on this.
I would suggest looking at https://karabiner-elements.pqrs.org/ to remap globally; that's what I use on macOS to remap caps lock to a dual role (tap = ESC, hold = control) key.
To switch Opt
and CMD
when using wezterm
is a good solution, but I tried this for one day, found that it not that good because some system wide keybindings is not consistent since cmd
is in opt
position.
@wez
So maybe there's a way to deem CMD
as META
when using mac?
If you look at the flow chart at https://wezfurlong.org/wezterm/config/keyboard-concepts.html#keyboard-processing-flow, where do you envision the modifier remapping happening?
Thx for your hint, I actually can just map the send key
. And I finally come up with something that seems working well.
local wezterm = require("wezterm")
local act = wezterm.action
function macCMDtoMeta()
local keys = "abdefghijklmnopqrstuwxyz" -- no c,v
local keymappings = {}
for i = 1, #keys do
local c = keys:sub(i, i)
table.insert(keymappings, {
key = c,
mods = "CMD",
action = act.SendKey({
key = c,
mods = "META",
}),
})
table.insert(keymappings, {
key = c,
mods = "CMD|CTRL",
action = act.SendKey({
key = c,
mods = "META|CTRL",
}),
})
end
return keymappings
end
return {
font = wezterm.font_with_fallback({
"Hack Nerd Font Mono",
}),
color_scheme = "Gruvbox dark, medium (base16)",
keys = macCMDtoMeta(),
font_size = 18.0,
hide_tab_bar_if_only_one_tab = true,
}
Remapping modifiers cross platform is potentially a bit gnarly, so I'm not eager to work on this.
@wez I'd love to have an interceptor kind of function that listens to and potentially modify keyboard events right before the "Send key to terminal" step
The workaround from @LintaoAmons is fine for a subset of chars but it's not optimal if I want to literally remap every occurrence of a specific modifier for all chars, symbols, ..etc.
My use case: I use Linux, Mac, and Windows almost daily, so I have the CMD and Ctrl swapped in Mac which solves most of my problems except for the terminal.
While I can change Wezterm own keybinds to use the appropriate modifier based on the OS I need a way to still use ctrl for terminal-based apps like Vim (as in, I press ctrl -> OS swaps it with CMD -> Wezterm's SendKey sends Ctrl). So having the ability to override what gets sent to these apps would fix the final piece of the puzzle for me. Currently, I use Karabiner but it's messy, and with every shortcut, I add I have to make two: one for all apps and one for Terminals.
I don't know if that would make it any better in terms of implementation/maintenance but just throwing ideas here and am open to feedback.
I imagine a something like public Lua interface of windowmods_to_termwiz_mods would suffice for my need.
@LintaoAmons, sorry to revive - have you tried that script with CMD|SHIFT
-> META|SHIFT
, by any chance? This latter remap doesn't appear to work, for some reason.
Edit: in fact, even CMD|CTRL
remap doesn't appear to be working for me - a key combination like Ctrl-Cmd-h still registers as Ctrl-Win-h inside the terminal. Not sure what I'm doing wrong..
@dinvlad
Here's my up-to-date config, it working fine for me, and should be fine for you. If not maybe you should debug some other possible reason outside wezterm?
@LintaoAmons thanks, and sorry for spam - does this work for you inside a terminal, or even more specifically inside Tmux? I'm probably missing something obvious - I'll create a discussion if it's more appropriate to discuss there. For now, I just created a different mapping that doesn't involve CMD, and the new binding seems to be working fine, as a workaround.
@dinvlad Yes, it's working both in tmux and vim(within or without tmux)~
@LintaoAmons thanks for your help - I got it working. Not sure what the ultimate culprit was, but I did all of the following:
-
set
config.term = "wezterm"
in.wezterm.lua
, as well asprograms.tmux.terminal = "wezterm";
andhome.sessionVariables.TERMINFO_DIRS = "${config.home.profileDirectory}/share/terminfo:$TERMINFO_DIRS";
in Nix's home-manager (which is what I'm using for config management). Obviously, these settings should only affect things like undercurls, but I figured they might be relevant -
double-checked I'm using your config without any other logic that may affect it. I think at one point I had a condition whether we're on macOS or not - and it turned out there was a syntactic mistake in that condition when I tried it again. For posterity, here's an expanded config that I'm using now to do an even more comprehensive remap of all ASCII characters (with the exception of CMD-c and CMD-v):
config.keys = {
-- regular mappings --
}
-- Swap Cmd <-> Option on macOS
if wezterm.target_triple:match("darwin$") then
for i = 0, 127 do
local key = string.char(i)
for _, mods in ipairs({ "", "|CTRL", "|SHIFT" }) do
if mods == "" and (key == "c" or key == "v") then
goto continue
end
for from, to in pairs({ CMD = "OPT", OPT = "CMD" }) do
table.insert(config.keys, {
key = key,
mods = from .. mods,
action = act.SendKey({
key = key,
mods = to .. mods,
}),
})
end
::continue::
end
end
end
- did a full restart of Tmux and WezTerm plus
killall tmux wezterm-mux-server
- since I've noticed that at least some settings didn't apply until I exited all Tmux sessions and stopped WezTerm Unix domain.