keymapper
keymapper copied to clipboard
mapping shift to be shift or parenthesis
Inpired from the space cadet keyboard I I decided to try out remapping my Shift keys to work like so:
- When held while pressing other keys, act like Shift.
- When pressed and released on their own, type an opening or closing parenthesis (left and right shift respectively).
I have tried
ShiftLeft{!200ms} >> '('
ShiftRight{!200ms} >> ')'
alas u i face some weird timing issues. Shift-t require me to hold down shift for a "long time" before pressing T. otherwise i get a t
rather than a T
. Other characters do not have the same issue.
Also when holding down shift and pressing abc
I get Abc
where I would have expected ABC
.
I then tried combining it with a ShiftRight{Any}
but I think it only made matters worse.
What am I doing wrong?
I'm pretty confident you'll be hitting some unexpected behavior if remapping shift-keys. With that said, try if this would work closer to what you want:
ShiftLeft{Any} >> ShiftLeft{Any}
ShiftRight{Any} >> ShiftRight{Any}
ShiftLeft{100ms} >> ShiftLeft
ShiftRight{100ms} >> ShiftRight
ShiftLeft >> '('
ShiftRight >> ')'
Personally I've done this instead (assuming US/UK layout):
AltRight{BracketLeft} >> !AltRight Shift{9} # '('
AltRight{BracketRight} >> !AltRight Shift{0} # ')'
It makes sense when using US/UK key layout. I can then get [{(
and )}]
all from the samt two keys.
Slightly improved version that also supports ()
.
ShiftLeft !150ms ShiftRight >> '()'
ShiftLeft{ShiftRight} >> '()'
ShiftLeft{Any} >> ShiftLeft{Any}
ShiftRight{Any} >> ShiftRight{Any}
ShiftLeft{100ms} >> ShiftLeft
ShiftRight{100ms} >> ShiftRight
ShiftLeft >> '('
ShiftRight >> ')'
Many thanks for your input. It has really bin a rollercoaster ride not only with this remapper tool, but also with so many other tools. They give off the impression you can do anything but remapping alt, shift - keys that screams for remapping you run into a ton of problems! There should be specific guides somewhere instructing you on how you go about remapping those keys. I see many mod CAPS key but I don't think it is an easy reach for me.
I'm very interested in remapping all my special keys for programming, so ill look into your definitions. Im on a nordic keyboard. I guess it is also very editor dependent. My editor autocompletes ), }, ] for me, so thef are less critical. I like the feel when I remodded J-K as you read in an earlier post, but perhaps it will cause more grief over time.
Any thoughts on this approach that places all layers on ALT's https://github.com/Roman-/redblue/blob/main/img/main.png
It has really bin a rollercoaster ride not only with this remapper tool, but also with so many other tools
Tell me about it! Once you let the genie out of the bottle... I jumped ~5 months ago after receiving my first QMK enabled Keychron K3 Pro (ISO Nordic as well btw). It was quite a battle after using a ThinkPad Compact keyboard for the past 10 years. ThinkPad layout by itself was a lot more ergonomic, mainly because of it's shorter spacebar and reversed Fn/Control keys. It effectively had the thumb keys one letter closer which allowed reaching both Win and Alt key with my thumb. It took a month of fiddling with QMK to reach the same level of ergonomics.
At that point, I was pretty pleased with my setup. So pleased, that after I saw the release of Keychron K15 Pro (low profile, alice layout), I decided to take the plunge and order my first US ANSI keyboard (ISO Nordic not yet available)... Then it was time to start from the beginning to find the most practical way of using ÄÖ
without changing the input language. :sweat_smile:
Around that time I ran across this article comparing Linux keymapping tools and found Keymapper. After receiving my K15 Pro, I thought I'll try if I could get away with Keymapper instead of QMK. Now ~4 months later, I've ended up using both (but mostly Keymapper). Recently I've also added Espanso to the mix after a friend tipped about it. It neatly complements the setup with the hotstring feature I loved AutoHotkey for back when I used Windows (~12y ago).
It's been a period full of relaxing tweaking, pleasing outcomes, frustration and headaches. So many hours of work time lost during this quest, I for sure aren't going to get it "paid back" increased productivity :joy:. Now it's only about ergonomics, reducing friction (...and an obsession).
Any thoughts on this approach that places all layers on ALT's
I don't think about layers as much now with Keymapper as I do app specific remapping. With that said, I use Alt-keys in my remaps the most of the traditional mod-keys. I've got so small hands, using Control on it's normal place is only doable for ASDF/ZXCV keys. I've put it on Caps Lock but like you, I find it hard to reach and don't use it much.
For QMK layers, I've found Tab more comfortable. On the K3 Pro (ISO Nordic), I found these keys convenient for layers while allowing use of most shortcuts I was already using:
...I also put Esc in place of Å as it's not used in Finnish.
On my K15 Pro, I've got many layer keys. Ones in green I find ergonomic, the ones in red are for specific uses:
Layer 1 is mostly empty, just QMK macros on the F-keys. Layer 2 is the one I've primarily used to complement Keymapper to get keys that are typically not used by the OS or apps and also for navigation. I use the Esc between space bars as the layer toggle and love it! This is what it looks like currently:
I've put numpad keys for use IJKL-navigation everywhere but also because they can be remapped while keeping the arrow keys as they are (for the rare situations I do find them, preferable). The special keys are mostly for Keymapper remaps for WebStorm.
Layer 3 (accessed from Tab) has some default QMK related keys for RGB (which I rarely use). The mouse keys on the right side I occassionally use:
The Esc between the space bars is what I use the most for application shortcuts. I mostly use it as a kind of like leader key is used in Vim, e.g. press Esc T
rather than Esc-T
. I'm not sure if it's related to what QMK does or just a feature of mechanical keyboards in general, but if I type Esc T
at my typical speed, the keys behave like Esc-T
. Due to this, I use the X{Y}
syntax in keymapper.conf
, even though most of the time I press them in sequence.
You can see a lot of that on this (incomplete) config I use with WebStorm. It might be difficult to get an idea of some of the mappings as they're handled in WebStorm. I've used some features from the next
branch there as well. This is just for inspiration, I'm just adjusting to it. 🙂
# Fast key sequences
Combo = $0 !250ms $1{!250ms}
DoubleTap = $0 !250ms $0{!250ms}
Tap = $0 !250ms !$0
# Key sequences
OneShot = $0 !2000ms
TwoShot = $0 !2000ms $1 !1000ms
Hold = $0{200ms}
# ...
# JetBrains IDE // Aliases
[class=JetBrainsIDE]
TabFocus = U | O
EscTap = Tap[Escape]
Esc_G = OneShot[Escape{G}] $0
# JetBrains IDE // Pull request, commit or stash diff view
[class=JetBrainsIDE title=/Diff for Pull Request |Commit: |Shelved: |History: /i]
ContextActive >> context["JetBrainsIDE pull request commit or shelve diff"]
NavLeft >> next_difference
NavDown >> prev_difference
Forward >> compare_next_file
Back >> compare_prev_file
Control{J} >> next_difference
Control{K} >> prev_difference
Control{N} >> compare_next_file
Control{P} >> compare_prev_file
DoubleTap[Escape] >> Escape
Escape >>
# JetBrains IDE // VCS changes
[class=JetBrainsIDE modifier="!AltGr" title=/Settings|Commit Changes|Commit: /i]
ContextActive >> context["JetBrainsIDE VCS changes"]
Control{J} >> next_difference
Control{K} >> prev_difference
Control{N} >> compare_next_file
Control{Shift{N}} >> compare_prev_file
# JetBrains IDE // Keychron K15 Pro mappings
[class=JetBrainsIDE device=KeyboardKeychron]
Shift{Find} >> replace_in_files
Find >> find_in_files
Help >> show_hover_info
Exec >> prefix_git_action
Erase >> rollback_change
AltGr{Shift{Delete}} >> cut_to_line_end
AltGr{Delete} >> delete_to_line_end
# JetBrains IDE // Default mappings
[class=JetBrainsIDE]
ContextActive >> context["JetBrainsIDE mappings"]
Jump = Combo[Escape, Space]
# Use numpad as arrow keys
NavUp >> ArrowUp
NavLeft >> ArrowLeft
NavDown >> ArrowDown
NavRight >> ArrowRight
# Tool window shortcuts
Hold[Digit] >> AltLeft{Digit} ^
# Function key shortcuts
Hold[FunctionKey] >> Control{FunctionKey} ^
(Control AltLeft){Any} >> (Control AltLeft){Any}
Tap[Escape] Direction >> (Control AltGr){Direction}
Tap[Escape] TabFocus >> (Control AltGr){TabFocus}
AltLeft{Direction} >> (AltLeft AltGr){Direction}
ControlRight{Direction} >> (Control AltGr){Direction}
EscTap Shift{7} >> toggle_block_comment
EscTap 7 >> toggle_comment
EscTap Shift{Slash} >> toggle_block_comment
EscTap Slash >> toggle_comment
_Shift{Escape} >> close_tool_window
BrowserBack >> navigate_back
BrowserForward >> navigate_forward
Control{BracketLeft} >> Control{BracketLeft} # move caret to previous paragraph
Control{BracketRight} >> Control{BracketRight} # move caret to next paragraph
AceJump = Combo[Escape, Space]
JTarget = I | M | L | W | J | A | B | T | D | Space | Comma | Enter
AceJump Shift{JTarget} >> Control{Comma} Shift{JTarget}
AceJump JTarget >> Control{Comma} JTarget
Esc_G[T] >> jump_to_top
Esc_G[B] >> jump_to_bottom
Esc_G[I] >> jump_to_text_start
Esc_G[K] >> jump_to_text_end
Esc_G[L] >> jump_to_line
Esc_G[W] >> jump_to_word
Esc_G[C] >> jump_to_character
Esc_G[P] >> toggle_problems
Escape{F} >> find
Escape{R} >> replace
Escape{W} >> close_tab
Escape{T} >> toggle_terminal
Escape{A} >> show_actions
Escape{Q} >> show_quick_documentation
F1 >> show_hover_info
Escape{D} >> goto_declaration
Escape{Y} >> goto_type_declaration
Escape{B} >> goto_implementation
Escape{P} >> goto_file
Escape{S} >> goto_symbol
Escape{Semicolon} >> jump_to_line
Escape{5} >> jump_to_matching_brace
Escape{Quote} >> jump_to_last_edit_loc
Escape{N} >> next_difference
Escape{E} >> next_error
Escape{J} >> join_lines
Escape{Z} >> rollback_change
Escape >> Escape
BracketLeft{BracketRight} >> BracketLeft BracketRight
BracketLeft{100ms} >>
BracketLeft{E} >> prev_error
BracketLeft{C} >> prev_change
BracketLeft{F} >> prev_function
BracketLeft{Any} >>
BracketRight{100ms} >>
BracketRight{E} >> next_error
BracketRight{C} >> next_change
BracketRight{F} >> next_function
BracketRight{Any} >>
AltGr{Enter} >> extend_selection
(Shift AltGr){Enter} >> shrink_selection
# JetBrainsIDE // IDE actions
[class=JetBrainsIDE]
ContextActive >> context["JetBrainsIDE actions"]
prefix_git_action >> _Alt{G}
close_tab >> AltLeft{W}
close_tool_window >> Shift{Escape}
find >> Control{F}
find_in_files >> (Control Shift){F}
replace >> Control{R}
replace_in_files >> (Control Shift){R}
show_actions >> _Alt{A}
show_context_actions >> _Alt{Enter}
show_hover_info >> Control{F1}
show_quick_documentation >> Control{Q}
toggle_terminal >> AltLeft{T}
toggle_problems >> AltLeft{8}
goto_file >> AltLeft{P}
goto_symbol >> AltLeft{S}
goto_declaration >> Control{B}
goto_type_declaration >> (Control Shift){B}
goto_implementation >> Control{AltLeft{B}}
jump_to_text_start >> Control{Home}
jump_to_text_end >> Control{End}
jump_to_top >> Control{PageUp}
jump_to_bottom >> Control{PageDown}
jump_to_line >> Control{G}
jump_to_character >> AltLeft{Comma}
jump_to_word >> Control{Comma}
jump_to_matching_brace >> Control{Shift{M}}
jump_to_last_edit_loc >> AltLeft{Shift{E}}
next_error >> _Alt{Escape}
prev_error >> _Alt{Shift{Escape}}
next_function >> _Alt{ArrowDown}
prev_function >> _Alt{ArrowUp}
rollback_change >> (Control AltLeft){Z}
next_change >> (Control AltLeft){ArrowDown}
prev_change >> (Control AltLeft){ArrowUp}
next_difference >> (Control AltLeft){ArrowDown}
prev_difference >> (Control AltLeft){ArrowUp}
compare_next_file >> (AltLeft Shift){N}
compare_prev_file >> (AltLeft Shift){J}
extend_selection >> _Alt{W}
shrink_selection >> _Alt{Shift{W}}
cut_to_line_end >> !AltGr (Shift Control AltLeft){Delete}
delete_to_line_end >> !AltGr (Control AltLeft){Delete}
join_lines >> _Control{J}
toggle_comment >> !Escape _Control{7}
toggle_block_comment >> !Escape _Control{Shift{7}}
@kbilsted It should work with your initial configuration. I think I know what's going wrong and how to fix it.
@kbilsted It should work with your initial configuration. I think I know what's going wrong and how to fix it.
@houmain Let me know if you want me to test something.
Hi, with the latest commits this should work as expected:
ShiftLeft{!200ms} >> '('
ShiftRight{!200ms} >> ')'
will test on latest version 4.0.1
Testing done on windows 10. Timing works very well when pressing 1 key at a time. All behaved as expected.
Unfortunately I found a weird issue.. when combining shift + cursor down
to select text in an editor then you easily get in a situation where it doesn't select, but only moves down..
Then I tried clicking shift + many keys which should produce all uppercase letters, but often I can trigger it to do lower case... eg IEieie
and TIEATIEEAIIETNAIEAIeanieieaieaieaieaieaieaieaieaaieieaaieieaIAEiea
the upper case at the end of the last sequence was me pressing again
@kbilsted Try with:
ShiftLeft{!120ms} >> '('
ShiftRight{!120ms} >> ')'
ShiftLeft{Any} >> ShiftLeft{Any}
ShiftRight{Any} >> ShiftRight{Any}
It will likely still mess up with any other mapping involving the shift keys if you have any. I'd confine this to apps where you need it regardless.
(try fiddling with the timing to be the smallest number you can reliably trigger it)
Sorry, I thought you were building from source. With latest commits I meant the ones after 4.0.1. But I think they are worth creating a 4.0.2.
You probably replied to @kbilsted but I usually am. This time I figured you were talking about the earlier changes.
P.S. What is the proper way of signaling CMake to disable Wayland support? I've hard coded it on the build file, committed that change and always rebase the new changes. It's beginning to feel silly. (With Wayland support, the build fails under my crusty Ubuntu 20.04 based system.
I've even created a mise workspace config to simplify building, starting/stopping the installed version and running a freshly built version for testing. :joy:
With 4.0.2 the workaround I suggested is not anymore necessary. Initially I was seeing a regression with some of the mouse mappings that you fixed with 4.0.1, but it seems like restarting keymapper
fixed it. I'll run with it for some time to see if I run into some other issues.
If nothing breaks, this has a lot of potential to allow other use cases as well :crossed_fingers:! I've reverted my changes back several times due to modifiers misbehaving futher down the config.
with v4.0.2 The result is much better! but i can still easily make it print lower case when it should print upper!
with one hand steadily press the same key again and again. Then with the other press shift. hold it a while, release it and hold again fast
AAAAAAAAAAaaaaaaaaaa AAAAAAAAAAAAAAAAAaaaaaaaaaa
^ ^ ^
arrow denote release and press shift
so not all the time but frequent when you use shift and a letter fast in succession it become lowercase
I noticed the same. Also it seemed that when it occurred, I had to do SpaceLeft
, SpaceRight
multiple times to get ()
, after which they worked again. Like the bindings would've been moved out of cache or something. Then again, my config is really complex and at the time I had 4 input devices at the same time with device specific configs. I had just added this novelty to the mix https://www.aliexpress.com/item/1005006099525907.html (bought mainly for decoration, space around my keyboard is reserved to mice for both hands). :slightly_smiling_face:
Thanks for the feedback. The last commit should at least fix the phenomenon described by @kbilsted.
@ristomatti I would love to see a photo of your desktop when everything is deployed. 😂
@houmain perhaps @ristomatti has watched too many cyberpunk movies :)
@ristomatti I would love to see a photo of your desktop when everything is deployed. 😂
"Deployed" :rofl:
Here we go:
Making good use of two mice is already quite impressive!
I've had RSI more than once. It balances a little bit. For the same reason I'm also using the lightest switches I could find, Gateron NuPhy Aloe's. They've got opering force of only 37±15gf. It took "a bit" of type to not typo every other word. but after that, these have been an absolute breeze to use. I tried going with the stock red switches but after just 2-3 weeks I started getting wrist pain.
have you tried https://www.maxgaming.dk/dk/switchar/choc-low-profile-pink-pro i want a glove 80 with red pro i think i'll enjoy flat and light
AFAIK only Gateron's low profile switches are compatible with Keychron's low profile models. I've got the K3 Pro as well, so I think I'll confine myself to ones that are compatible. Besides, I really like stock keycaps as well. I did order two sets of hopefully compatible keycaps from AliExpress for my K3 Pro. My plan is to convert it to ISO UK layout now that I've gotten used to ANSI US on this split keyboard.
20g sounds insaly light thought. Prior to my jump to mech keyboards half a year ago, I had used Lenovo ThinkPad Compact TrackPoint keyboards (and to some extent ThinkPad integrated keyboards) for maybe 8 years. The 50±15 gf of Gateron Red switches felt really stiff compared to 39gf of the ThinkPad switches. I've got small and relatively dexterous fingers/hands but I was surprised how light the Aloe's were. It really felt like ice scating for the first weeks :joy:.
Personally I think I could like Gateron's optical white switches available for the non-pro Keychron K-series models though:
Unfortunately QMK firmware does not support optical switches even though they'd otherwise fit (or at least this is what I've read).
Thanks for the feedback. The last commit should at least fix the phenomenon described by @kbilsted.
Hi, this is finally easily testable in the 4.1.0 release.
I hope it works this time. Tell me when ready
I hope it works this time. Tell me when ready
Well, it is.
I found this to work pretty much perfectly a few hours of actual use while working but the mapping itself didn't work out well with my workflow. I decided to continue using my old way of
AltGr = AltRight
AltGr{BracketLeft} >> Shift{9}
AltGr{BracketRight} >> Shift{0}
Aside - @houmain, I want to say version 4.1 has so far worked stellar (besides the few "cosmetic" issues discussed at #126 and #131). It really shows you know what you're doing. Despite my non-existant C++ skills, I've read and written enough code to say the codebase looks very "clean" and well thought out. May I ask how long you've been writing C++, is it something you do for work as well and if so, what type of industry? I'm guessing game development based on your other repos. 🙂
...to continue on the previous comment, I just today noticed this inverse condition syntax has appeared and found use to it right away.
I also noticed aliases within parameterized aliases now work as well I mentioned on some other issue thread. Just this evening I added this section to streamline Tmux pane and window navigation (I've included some other related parts here):
# Key groups
Digit = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
# Directional navigation
KeyUp = I
KeyLeft = J
KeyDown = K
KeyRight = L
Direction = KeyUp | KeyLeft | KeyDown | KeyRight
# Class matchers
Terminal = /kitty|tmux/i
# Passtrough common modifiers
[default]
AltLeft >> AltLeft
AltRight >> AltRight
ControlLeft >> ControlLeft
[class != Terminal, title != "tmux"]
ControlRight >> ControlRight
# Terminal // Tmux
[class = Terminal, title = "tmux"]
TmuxMod = Tab
TmuxTap = Tap[ControlRight]
# Bindings used in tmux.conf
TmuxBinding = Direction | N | P | O | W | Comma | Period | Digit
TmuxPrefix = !TmuxMod (ControlRight A){10ms} 10ms $0
# Navigate with Tab+X
TmuxMod{TmuxBinding} >> TmuxPrefix[TmuxBinding]
# Navigate with Control followed by X
TmuxTap TmuxBinding >> TmuxPrefix[TmuxBinding]
ControlRight >> ControlRight
For the curious, I've just updated my public (slightly redacted) gist of the full config here.
Last night I noticed I had also missed the "optional comma" within context definitions. It's like you've read my thoughts on this one, or did you spot it from some screenshot I've posted. Just recently changed the ContextActive
enter/leave logs to look like this:
After I spotted the change by diffing README.md
, I immediately reformatted all the context blocks to use the new [class = /foo|bar/i, title = "baz"]
format. It's so much easier to read. :+1: