Steps to try my layout:
- If you have a normal keyboard, proceed to step (2). If you have a special keyboard like the Moonlandeer or the Kinesis Advantage, use their configuration software to map the thumb keys as follows:
- left-hand thumb keys:
- left key:
left control
- middle key:
left option
- right key:
left command
- left key:
- right-hand thumb keys:
- left key:
spacebar
- middle key:
right command
- right key:
right option
- left key:
- left-hand thumb keys:
- Install Karabiner-Elements.
- Install goku.
- Clone this repo and load the config in
dotfiles/karabiner/karabiner.edn
.
Note: the karabiner.edn
file is generated by “tangling” the code blocks in the modifications.org
file, which is the file you are currently reading. If you use Emacs and would like to play around with my config, you may want to edit this file and tangle it, instead of editing karabiner.edn
directly.
- Introduction
- Profiles
- Tos
- Modifiers
- Applications
- Devices
- Layers
- Simlayers
- Templates
- Main
- Appendices
- Local variables
It seems that there is no way to set the relevant delay for a simlayer, so the only alternative is to recreate the spacebar
simlayer functionality as a series of individual modifications. Then the delay would, I believe, be controlled by the sim
variable (since spacebar
+ each of the keys it currently modifies in the simlayer would be considered simultaneous key presses).
{
:profiles {
:Default {:default true
alone (to_if_alone_timeout_miliseconds
): if a key is held for at least this long, releasing it will not trigger its alone mapping.
Example:
{:des "caps -> escape (alone) left_option (held)"
:rules [
[:##caps_lock :left_option nil {:alone :escape}]
]}
If caps_lock
is held for at least 100 miliseconds, it will not trigger escape
.
:alone 200
held (to_if_held_down_threshold_miliseconds
): if a key is held for at least this long, it will trigger its held mapping.
:held 350
delay (to_delayed_action_delay_miliseconds
): for rules defining some behavior when a succession of two keys is pressed, the second key will trigger the behavior if pressed within this many miliseconds after the first key. I haven’t defined any such rules, so the value below has no effect on my configuration.
:delay 300
sim (simultaneous_threshold_miliseconds
): keys need to be pressed within these many miliseconds to be considered simultaneous. This doesn’t apply to modifier keys, but to “normal” keys (e.g. q
+ k
to launch Karabiner).
:sim 150
:simlayer-threshold 250}} ; default
:tos {
;; macOS
:⇧ {:key :left_shift}
:⌘ {:key :left_command}
:⌥ {:key :left_option}
:⌃ {:key :left_control}
:🌐 {:key :fn}
:⌘⌃ {:key :Cleft_control}
;; Emacs
:S- {:key :left_shift} ; S
:A- {:key :right_command} ; Q
:C- {:key :left_control} ; T
:H- {:key :left_command} ; C
:M- {:key :left_option} ; O
:s- {:key :right_control} ; W
:A-C- {:key :!Qleft_control}
:A-H- {:key :!Qleft_command}
:A-M- {:key :!Qleft_option}
:A-s- {:key :!Qright_control}
;; symbols
:exclamation_mark {:key :!S1}
:at_sign {:key :!S2}
:number_sign {:key :!S3}
:dollar_sign {:key :!S4}
:percent_sign {:key :!S5}
:caret {:key :!S6}
:ampersand {:key :!S7}
:asterisk {:key :!S8}
:open_parenthesis {:key :!S9}
:close_parenthesis {:key :!S0}
:underscore {:key :!Shyphen}
:plus_sign {:key :!Sequal_sign}
:open_brace {:key :!Sopen_bracket}
:close_brace {:key :!Sclose_bracket}
:vertical_bar {:key :!Sbackslash}
:double_quote {:key :!Squote}
:open_double_quote {:key :!Eopen_bracket}
:close_double_quote {:key :!SEopen_bracket}
:open_single_quote {:key :!Eclose_bracket}
:close_single_quote {:key :!SEclose_bracket}
:tilde {:key :!Sgrave_accent_and_tilde}
:en_dash {:key :!Ehyphen}
:em_dash {:key :!SEhyphen}
;; diacritics
;; note that many of the mappings below require ABC - Extended as the macOS input source
:overdot {:key :!Ew}
:underdot {:key :!Ex}
:accute_accent {:key :!Ee}
:double_acute_accent {:key :!Ej}
:grave_accent {:key :!Egrave_accent_and_tilde}
:umlaut {:key :!Eu}
:undercomma {:key :!Ep}
:underbar {:key :!Eh}
:macron {:key :!Ea}
:breve {:key :!Eb}
:hook {:key :!Ez}
:horn {:key :!Ei}
:circumflex {:key :!E6}
:cedilla {:key :!Ec}
:overring {:key :!Ek}
:stroke {:key :!El}
:caron {:key :!Ev}
:ogonek {:key :!Em}
:tilde_accent {:key :!En}
;; “special” chars
:ø {:key :!Eo}
:œ {:key :!Eq}
:ß {:key :!Es}
:ð {:key :!Ed}
:þ {:key :!Et}
:¡ {:key :!E1}
:¿ {:key :!ESslash}
:« {:key :!Ebackslash}
:» {:key :!SEbackslash}
:• {:key :!O8}
:£ {:key :!E3}
:€ {:key :!ES2}
:… {:key :!Esemicolon}
;; math
:= {:key :equal_sign}
:+ {:key :!Sequal_sign}
:≠ {:key :!Eequal_sign}
:÷ {:key :!Eslash}
:± {:key :!ESequal_sign}
:≤ {:key :!Ecomma}
:≥ {:key :!Eperiod}
}
:modifiers {
;; macOS
:⇧ [:left_shift]
:⌘ [:left_command]
:⌥ [:left_option]
:⌃ [:left_control]
:⇧⌘ [:left_shift :left_command]
:⇧⌥ [:left_shift :left_option]
:⇧⌃ [:left_shift :left_control]
:⌘⌥ [:left_command :left_option]
:⌘⌃ [:left_command :left_control]
:⌥⌃ [:left_option :left_control]
:⇧⌘⌥ [:left_shift :left_command :left_option]
:⇧⌘⌃ [:left_shift :left_command :left_control]
:⇧⌥⌃ [:left_shift :left_option :left_control]
:⌘⌥⌃ [:left_command :left_option :left_control]
:⇧⌘⌥⌃ [:left_shift :left_command :left_option :left_control]
;; Emacs
:S- [:left_shift]
:A- [:right_command]
:C- [:left_control]
:H- [:left_command]
:M- [:left_option]
:s- [:right_control]
:A-C- [:right_command :left_control]
:A-H- [:right_command :left_command]
:A-M- [:right_command :left_option]
:A-s- [:right_command :right_control]
:C-H- [:left_control :left_command]
:C-M- [:left_control :left_option]
:C-s- [:left_control :right_control]
:H-M- [:left_command :left_option]
:H-s- [:left_command :right_control]
:M-s- [:left_option :right_control]
:A-C-H- [:right_command :left_control :left_command]
:A-C-M- [:right_command :left_control :left_option]
:A-C-s- [:right_command :left_control :right_control]
:A-H-M- [:right_command :left_command :left_option]
:A-H-s- [:right_command :left_command :right_control]
:A-M-s- [:right_command :left_option :right_control]
:C-H-M- [:left_control :left_command :left_option]
:C-H-s- [:left_control :left_command :right_control]
:C-M-s- [:left_control :left_option :right_control]
:H-M-s- [:left_command :left_option :right_control]
:A-C-H-M- [:right_command :left_control :left_command :left_option]
:A-C-H-s- [:right_command :left_control :left_command :right_control]
:A-C-M-s- [:right_control :left_control :right_command :left_option]
:A-H-M-s- [:right_command :left_command :left_option :right_control]
:C-H-M-s- [:left_control :left_command :left_option :right_control]
:A-C-H-M-s- [:left_control :left_command :left_option :right_control :right_command]
}
:applications {
:anki ["net.ankiweb.dtop"]
:chrome ["com.google.Chrome"]
:emacs ["org.gnu.Emacs"]
:firefox ["org.mozilla.firefox"]
:safari ["com.apple.Safari"]
:steam [:paths ".*/Application Support/Steam.*"]
}
:devices {
:corne [{:vendor_id 7504}]
:moonlander [{:vendor_id 12951}]
}
:layers {
:k-mode {:key :quote :condi :chrome}
}
:simlayers {
:b-mode {:key :b}
:f-mode {:key :f}
:j-mode {:key :j}
:k-mode {:key :k}
:m-mode {:key :m}
:p-mode {:key :p}
:q-mode {:key :q}
:v-mode {:key :v}
:x-mode {:key :x :condi :emacs}
:y-mode {:key :y}
:z-mode {:key :z}
:comma-mode {:key :comma :condi :emacs}
:period-mode {:key :period}
:semicolon-mode {:key :semicolon}
:slash-mode {:key :slash}
}
:templates {:alfred "osascript -e 'tell application \"Alfred 4\" to run trigger \"%s\" in workflow \"%s\" with argument \"%s\"'"
:km "osascript -e 'tell application \"Keyboard Maestro Engine\" to do script \"%s\"'"
:open "open \"%s\""
:insert "~/Library/CloudStorage/Dropbox/dotfiles/bin/char_input \"%s\""
}
Note that the :insert
template inserts an arbitrary character by calling a bash script that in turn calls an AppleScript. There may be a simpler way of doing this, but that’s how I managed to do it. Here are the scripts I’m using:
#!/bin/bash
osascript $HOME/Library/Scripts/inputCharacter.scpt "$1"
on run argv
set the clipboard to (item 1 of argv)
tell application "System Events"
keystroke "v" using {command down}
end tell
end run
:main [
{:des "Disable caps_lock"
:rules [
[:caps_lock :vk_none]
]}
{:des "Emacs: left_control → C-g (alone) M- (held)"
:rules [
[:!Ch {:modi :A-H-M-s- :key :h} :emacs] ; circumvent macOS ⌘h
[:!CQh {:modi :A-C-H-s- :key :h} :emacs] ; circumvent macOS ⌘⌥h
[:##left_control :M- [:!steam :emacs] {:alone {:modi :C- :key :g}}]
]}
{:des "Outside Emacs: left_control → escape (alone) | ⌥ (held)"
:rules [
[:##left_control :⌥ [:!steam :!emacs] {:alone :escape}]
]}
{:des "Emacs: left_option → toggle tabs/windows (alone) | S- (held)"
:rules [
[:##left_option :S- :emacs {:alone :return_or_enter}]
]}
{:des "Outside Emacs: left_option → toggle tabs/windows (alone) | ⇧ (held)"
:rules [
[:##left_option :⇧ :!emacs {:alone :return_or_enter}]
]}
Since the same key now triggers shift
and return
, we can no longer trigger shift
+ return
. So we define a special binding to trigger this key event via shift
+ spacebar
(the latter is triggered by right_command
, as defined in a section below).
{:des "left_option + right_command → ⇧ + enter"
:rules [
[:!Sright_command {:modi :⇧ :key :return_or_enter}]
]}
Since the same key now triggers shift
and return
, we can no longer trigger shift
+ return
. So we define a special binding to trigger this key event via shift
+ spacebar
(the latter is triggered by right_command
, as defined in a section below).
{:des "left_option + right_command → ⇧ + enter"
:rules [
[:!Sright_command {:modi :⇧ :key :return_or_enter}]
]}
When tapped, the left_command
key toggles between the two most recent windows (in Emacs) or tabs (in a browser). In Emacs, I do this by binding C-H-0
to my custom command window-extras-switch-to-last-window
. In Chrome, I do this by installing the extensions CLUT (Chrome) and Last Tab (Firefox) and configuring ⌘⌃0
as the keyboard shortcut for each.
{:des "Emacs: left_command → other window (alone) | H- (held)"
:rules [
[:##left_command :H- :emacs {:alone {:modi :C-H- :key :0}}]
]}
{:des "Outsie Emacs: left_command → other tab (alone) | ⌘ (held)"
:rules [
[:##left_command :⌘ :!emacs {:alone {:modi :⌘⌃ :key :0}}]
]}
The spacebar triggers control
when held and toggles between apps when tapped. In addition, if the spacebar is tapped while the command key is held, it will toggle instead between buffers (in Emacs) or windows (outside Emacs).
{:des "Emacs: spacebar → C- (held) | ⌘tab (alone)"
:rules [
[:!Cspacebar {:modi :A-H-M-s- :key :spacebar} :emacs] ; files-extras-switch-to-alternate-buffer
[:##spacebar :C- :emacs {:alone {:modi :⌘ :key :tab}}]
]}
{:des "Outside Emacs: spacebar → ⌃ (held) | ⌘tab (alone)"
:rules [
[:!Cspacebar {:modi :⌘ :key :grave_accent_and_tilde} :!emacs] ; move focus to next window
[:##spacebar :⌃ :!emacs {:alone {:modi :⌘ :key :tab}}]
]}
{:des "Emacs: right_command + left_command → A-H- (held) "
:rules [
[[:right_command :left_command] :A-H- :emacs {:alone {:modi :A- :key :spacebar}}]
]}
{:des "Emacs: right_command + left_shift → A-"
:rules [
[[:right_command :left_option] :A- :emacs]
]}
{:des "Emacs: right_command + spacebar → A-C-"
:rules [
[[:right_command :spacebar] :A-C- :emacs]
]}
{:des "Emacs: right_command + left_control → A-M-"
:rules [
[[:right_command :left_control] :A-M- :emacs]
]}
{:des "Emacs: right_command + right_option → A-s-"
:rules [
[[:right_command :right_option] :A-s- :emacs]
]}
{:des "Emacs: right_command → spacebar"
:rules [
[:##right_command :spacebar :emacs]
]}
{:des "Outside Emacs: right_command → spacebar"
:rules [
[:##right_command :spacebar :!emacs]
]}
{:des "Emacs: right_option → other window (alone) | s- (held)"
:rules [
[:##right_option :s- :emacs {:alone :tab}]
]}
{:des "outside Emacs: right_option → other window (alone) | ⌥ (held)"
:rules [
[:##right_option :⌥ :!emacs {:alone :tab}]
]}
My Logitech MX Anywhere 3S mouse does not have a tilting wheel, so I remap the side buttons to trigger the relevant tab navigation shortcuts when pressed while the shift key is held. Note that for these “extra” mouse buttons to be detected by Karabiner, you may need to enable the relevant device in the “Devices” section.
{:des "left_shift + side mouse buttons → navigate open tabs"
:rules [
[{:pkey :button4 :modi :left_shift} :!COleft_arrow]
[{:pkey :button5 :modi :left_shift} :!COright_arrow]
]}
- The right-hand top row keys control window placement, via Emacs Lisp commands in Emacs, or via Rectangle otherwise.
- The right-hand home row keys control playback.
l
triggers a Keyboard Maestro script that runs the AppleScript included below.
- The right-hand bottom row keys control volume.
h
andn
control dictation and narration, respectively.- The keyboard shortcuts need to be set under Settings > Keyboard > Dictation > Shortcut (for dictation) and Settings > Accessibility > Spoken content > Speak selection (for narration).
{:des "b-mode (media controls, window sizing)"
:rules [:b-mode
[:u {:modi :C-H- :key :u} :emacs] ; frame-extras-left-half
[:u {:modi :⇧⌘⌥⌃ :key :u}] ; Rectangle, left half
[:p {:modi :C-H- :key :p} :emacs] ; frame-extras-right-half
[:p {:modi :⇧⌘⌥⌃ :key :p}] ; Rectangle, right half
[:i {:modi :C-H- :key :i} :emacs] ; frame-extras-maximize-frame
[:i {:modi :⇧⌘⌥⌃ :key :i}] ; Rectangle, maximize
[:o {:modi :⇧⌘⌥⌃ :key :o}] ; Rectangle, center
[:j :rewind]
[:x {:modi :⇧⌘⌃ :key :3}] ; Copy picture of screen to the clipboard
[:k :play_or_pause]
[:semicolon :fast_forward]
[:comma :volume_increment]
[:period :volume_decrement]
[:m :mute]
[:c {:modi :C-M-s- :key :c} :emacs] ; connect to bluetooth device
[:g {:modi :C-M-s- :key :g} :emacs] ; toggle langs
[:h {:modi :⇧⌘⌥⌃ :key :0}] ; dictation
[:n {:modi :⇧⌘⌥⌃ :key :1}] ; narration (Settings > Accessibility > Spoken content > Speak selection)
]}
using terms from application "Spotify"
if player state of application "Spotify" is paused then
tell application "Spotify" to play
else
tell application "Spotify" to pause
end if
end using terms from
{:des "f-mode (special chars)"
:rules [:f-mode
[:d :ð]
[:e :…]
[:i :¡]
[:o :ø]
[:p :£]
[:q :œ]
[:r :€]
[:s :ß]
[:t :þ]
[:u :•]
[:slash :¿]
[:comma :«]
[:period :»]
]
}
{:des "j-mode (deletion)"
:rules [:j-mode
[:a {:modi :C-H-M- :key :a} :emacs]
[:!Wa {:modi :C-H-M-s- :key :a} :emacs]
[:!WQa {:modi :A-C-H-M-s- :key :a} :emacs]
[:s {:modi :C-H-M- :key :s} :emacs]
[:s :delete_or_backspace :!emacs]
[:d {:modi :C-H-M- :key :d} :emacs]
[:d :delete_forward :!emacs]
[:f {:modi :C-H-M- :key :f} :emacs]
[:!Wf {:modi :C-H-M-s- :key :f} :emacs]
[:!WQf {:modi :A-C-H-M-s- :key :f} :emacs]
[:q {:modi :C-H-M- :key :q} :emacs]
[:!Wq {:modi :C-H-M-s- :key :q} :emacs]
[:!WQq {:modi :A-C-H-M-s- :key :q} :emacs]
[:q {:modi :⌥ :key :delete_or_backspace} :!emacs]
[:w {:modi :C-H-M- :key :w} :emacs]
[:!Ww {:modi :C-H-M-s- :key :w} :emacs]
[:!WQw {:modi :A-C-H-M-s- :key :w} :emacs]
[:w {:modi :⌘ :key :delete_or_backspace} :!emacs]
[:e {:modi :C-H-M- :key :e} :emacs]
[:!We {:modi :C-H-M-s- :key :e} :emacs]
[:!WQe {:modi :A-C-H-M-s- :key :e} :emacs]
[:e {:modi :⌃ :key :k} :!emacs]
[:r {:modi :C-H-M- :key :r} :emacs]
[:!Wr {:modi :C-H-M-s- :key :r} :emacs]
[:!WQr {:modi :A-C-H-M-s- :key :r} :emacs]
[:r {:modi :⌥ :key :delete_forward} :!emacs]
[:z {:modi :C-H-M- :key :z} :emacs]
[:!Wz {:modi :C-H-M-s- :key :z} :emacs]
[:!WQz {:modi :A-C-H-M-s- :key :z} :emacs]
[:z {:modi :⌘ :key :delete_or_backspace} :!emacs]
[:x {:modi :C-H-M- :key :x} :emacs]
[:!Wx {:modi :C-H-M-s- :key :x} :emacs]
[:!WQx {:modi :A-C-H-M-s- :key :x} :emacs]
[:x {:modi :⌘⌥ :key :left_arrow} :!emacs]
[:c {:modi :C-H-M- :key :c} :emacs]
[:!Wc {:modi :C-H-M-s- :key :c} :emacs]
[:!WQc {:modi :A-C-H-M-s- :key :c} :emacs]
[:c {:modi :⌘⌥ :key :right_arrow} :!emacs]
[:v {:modi :C-H-M- :key :v} :emacs]
[:!Wv {:modi :C-H-M-s- :key :v} :emacs]
[:!WQv {:modi :A-C-H-M-s- :key :v} :emacs]
[:v {:modi :⌘ :key :delete_forward} :!emacs]
[:b {:modi :C-H-M- :key :b} :emacs]
[:t {:modi :C-H-M- :key :t} :emacs]
[:t :home :!emacs]
[:g {:modi :C-H-M- :key :g} :emacs]
[:g :end :!emacs]
[:!Wd {:modi :C-H-M-s- :key :d} :emacs]
[:!Ws {:modi :C-H-M-s- :key :s} :emacs]
]}
{:des "k-mode (website-specific)"
:rules [:k-mode
[:a [:km "Local website a"]]
[:b [:km "Local website b"]]
[:c [:km "Local website c"]]
[:d [:km "Local website d"]]
[:e [:km "Local website e"]]
[:f [:km "Local website f"]]
[:g [:km "Local website g"]]
[:h [:km "Local website h"]]
[:i [:km "Local website i"]]
[:j [:km "Local website j"]]
[:l [:km "Local website l"]]
[:!Sl [:km "Local website Sl"]]
[:!Cl [:km "Local website Cl"]]
[:!CSl [:km "Local website CSl"]]
[:m [:km "Local website m"]]
[:n [:km "Local website n"]]
[:o [:km "Local website o"]]
[:p [:km "Local website p"]]
[:r [:km "Local website r"]]
[:s [:km "Local website s"]]
[:t [:km "Local website t"]]
[:u [:km "Local website u"]]
[:y [:km "Local website y"]]
[:z [:km "Local website z"]]
[:x [:km "Local website x"]]
[:v [:km "Local website v"]]
[:w [:km "Local website w"]]
[:semicolon [:km "Local website semicolon"]]
[:comma [:km "Local website comma"]]
[:period [:km "Local website period"]]
[:slash [:km "Local website slash"]]
[:return_or_enter [:km "Local website return_or_enter"]]
;; [:spacebar [:km "Local website spacebar"]]
]}
{:des "m-mode (math symbols)"
:rules [:m-mode
[:e :=]
[:p :+]
[:q :≠]
[:d :÷]
[:o :±]
[:x [:insert "×"]]
[:comma :≤]
[:period :≥]
]}
E.g. “me” sometimes inserts =
{:des "p-mode (diacritics)"
:rules [:p-mode
[:a :macron]
[:b :breve]
[:c :cedilla]
[:e :accute_accent]
[:g :undercomma]
[:h :underbar]
[:i :horn]
[:j :double_acute_accent]
[:k :overring]
[:l :stroke]
[:m :ogonek]
[:n :tilde_accent]
[:r :grave_accent]
[:u :umlaut]
[:v :caron]
[:w :underdot]
[:x :overdot]
[:y :circumflex]
[:z :hook]
]
}
{:des "q-mode (apps)"
:rules [:q-mode
[:b [:open "/Applications/qBitTorrent.app"]]
[:d [:open "/System/Library/CoreServices/Finder.app"]]
[:e [:open "/Applications/Emacs.app"]]
[:f [:open "/Applications/Firefox.app"]]
[:g [:open "/Applications/Goldendict.app"]]
[:h [:open "/Applications/Google Chrome.app"]]
[:i [:open "/Applications/Anki.app"]]
[:j [:km "open: System Preferences"]]
[:k [:open "/Applications/Keyboard Maestro.app"]]
[:l [:open "/Applications/DeepL.app"]]
[:m [:open "/Applications/Media Center 29.app"]]
[:o [:open "/Applications/zoom.us.app"]]
[:p [:open "/Applications/Beeper.app"]]
[:r [:open "/Applications/Karabiner-Elements.app"]]
[:s [:open "/Applications/Slack.app"]]
[:t [:open "/System/Applications/Utilities/Terminal.app"]]
[:v [:open "/Applications/mpv.app"]]
[:w [:open "/Applications/HoudahSpot.app"]]
[:x [:open "/Applications/Plex Media Server.app/"]]
[:y [:open "/Applications/Spotify.app"]]
[:comma [:open "/Applications/Home Assistant.app"]]
[:period [:open "/Applications/Tor Browser.app"]]
]}
{:des "v-mode (numbers)"
:rules [:v-mode
[:i :8]
[:##i :##8]
[:j :4]
[:##j :4]
[:k :5]
[:##k :5]
[:l :6]
[:##l :6]
[:m :1]
[:##m :1]
[:o :9]
[:##o :9]
[:u :7]
[:##u :7]
[:comma :2]
[:##comma :2]
[:period :3]
[:##period :3]
[:p :0]
[:##p :0]
[:semicolon :period]
[:##semicolon :period]
]
}
{:des "x-mode (avy)"
:rules [:x-mode
[:a [{:modi :C-H-s- :key :a}]]
[:b [{:modi :C-H-s- :key :b}]]
[:c [{:modi :C-H-s- :key :c}]]
[:d [{:modi :C-H-s- :key :d}]]
[:e [{:modi :C-H-s- :key :e}]]
[:f [{:modi :C-H-s- :key :f}]]
[:g [{:modi :C-H-s- :key :g}]]
[:h [{:modi :C-H-s- :key :h}]]
[:i [{:modi :C-H-s- :key :i}]]
[:j [{:modi :C-H-s- :key :j}]]
[:k [{:modi :C-H-s- :key :k}]]
[:l [{:modi :C-H-s- :key :l}]]
[:m [{:modi :C-H-s- :key :m}]]
[:n [{:modi :C-H-s- :key :n}]]
[:o [{:modi :C-H-s- :key :o}]]
[:p [{:modi :C-H-s- :key :p}]]
[:q [{:modi :C-H-s- :key :q}]]
[:r [{:modi :C-H-s- :key :r}]]
[:s [{:modi :C-H-s- :key :s}]]
[:t [{:modi :C-H-s- :key :t}]]
[:u [{:modi :C-H-s- :key :u}]]
[:v [{:modi :C-H-s- :key :v}]]
[:w [{:modi :C-H-s- :key :w}]]
[:y [{:modi :C-H-s- :key :y}]]
[:z [{:modi :C-H-s- :key :z}]]
[:semicolon [{:modi :C-H-s- :key :semicolon}]]
[:comma [{:modi :C-H-s- :key :comma}]]
[:period [{:modi :C-H-s- :key :period}]]
[:slash [{:modi :C-H-s- :key :slash}]]
[:spacebar [{:modi :C-H-s- :key :spacebar}]]
[:return_or_enter [{:modi :C-H-s- :key :return_or_enter}]]
[:tab [{:modi :C-H-s- :key :tab}]]
]}
{:des "y-mode (mouse, screenshots)"
:rules [:y-mode
[:b {:modi :⇧⌘ :key :5}] ; Screenshot and recording options
[:c {:modi :⇧⌘ :key :4}] ; Save picture of selected area to a file
[:d {:mkey {:y 1500}}]
[:e {:mkey {:y 4500}}]
[:a {:mkey {:x -1500}}]
[:f {:mkey {:x 1500}}]
[:q {:mkey {:x -4500}}]
[:r {:mkey {:x 4500}}]
[:s {:mkey {:y -1500}}]
[:v {:modi :⇧⌘⌃ :key :4}] ; Copy picture of selected area to the clipboard
[:w {:mkey {:y -4500}}]
[:z {:modi :⇧⌘ :key :3}] ; Save picture of screen as a file
[:right_command :button2]
[:return_or_enter :button1]
]}
[2021-03-23 Tue 09:18] I’ve added ##
to u
and p
. This allows for the use of shift. Not sure if this addition will have any unexpected side effects, so testing it on these two words only. If everything looks fine in a few days, you can extend this modification to all other relevant letters.
[2021-03-25 Thu 08:30] Next task is to create corresponding versions of many of the motion key mappings that move the screen rather than the cursor.
{:des "z-mode (navigation)"
:rules [:z-mode
[:b {:modi :A-C-s- :key :b} :emacs]
[:c {:modi :A-C-s- :key :c}]
[:d {:modi :A-H-M-s- :key :d} :emacs] ; WTQ intercepted by OSX
[:e {:modi :A-C-s- :key :e} :emacs]
[:f [{:modi :⌘⌃ :key :n} {:modi :⌘⌃ :key :h}] :chrome] ; Google Docs next heading
[:f {:modi :A-C-s- :key :f}]
[:g {:modi :A-C-s- :key :g} :emacs]
[:h {:modi :A-C-s- :key :h} :emacs]
[:##h :page_down]
[:i {:modi :A-C-s- :key :i} :emacs]
[:##i {:modi :⌥ :key :up_arrow}]
[:j :left_arrow]
[:##j :left_arrow]
[:k :up_arrow]
[:##k :up_arrow]
[:l :down_arrow]
[:##l :down_arrow]
[:m {:modi :A-C-s- :key :m} :emacs]
[:##m {:modi :⌘ :key :left_arrow}]
[:n {:modi :A-C-s- :key :n} :emacs]
[:o {:modi :A-C-s- :key :o} :emacs]
[:##o {:modi :⌥ :key :down_arrow}]
[:p {:modi :A-C-s- :key :p} :emacs]
[:##p {:modi :⌥ :key :right_arrow}]
[:r [{:modi :⌘⌃ :key :p} {:modi :⌘⌃ :key :h}] :chrome] ; Google Docs previous heading
[:r {:modi :A-C-s- :key :r} :emacs]
[:s {:modi :A-C-s- :key :s} :emacs]
[:t {:modi :A-C-s- :key :t} :emacs]
[:u {:modi :A-C-s- :key :u} :emacs]
[:##u {:modi :⌥ :key :left_arrow}]
[:v {:modi :A-C-s- :key :v} :emacs]
[:w {:modi :A-C-s- :key :w} :emacs]
[:x {:modi :A-C-s- :key :x}]
[:y {:modi :A-C-s- :key :y} :emacs]
[:##y :page_up]
[:spacebar {:modi :A-C-s- :key :spacebar} :emacs]
[:spacebar {:modi :⌘ :key :up_arrow} :chrome] ; in Chrome, move to top
[:spacebar :home]
[:comma {:modi :A-C-s- :key :comma} :emacs]
[:##comma {:modi :⌘ :key :up_arrow}]
[:period {:modi :A-C-s- :key :period} :emacs]
[:##period {:modi :⌘ :key :down_arrow}]
[:right_command {:modi :A-C-s- :key :tab} :emacs]
[:right_command {:modi :⌘ :key :down_arrow} :chrome] ; in Chrome, move to bottom
[:right_command :end]
[:semicolon :right_arrow]
[:##semicolon :right_arrow]
[:slash {:modi :A-C-s- :key :slash} :emacs]
[:##slash {:modi :⌘ :key :right_arrow}]
[:tab {:modi :A-C-s- :key :tab} :emacs]
;; [:##tab :home]
]}
{:des "comma-mode (transposition)"
:rules [:comma-mode
[:a {:modi :A-H-M- :key :a}]
[:b {:modi :A-H-M- :key :b}]
[:c {:modi :A-H-M- :key :c}]
[:d {:modi :A-H-M- :key :d}]
[:e {:modi :A-H-M- :key :e}]
[:f {:modi :A-H-M- :key :f}]
[:g {:modi :A-H-M- :key :g}]
[:h {:modi :A-H-M- :key :h}]
[:i {:modi :A-H-M- :key :i}]
[:j {:modi :A-H-M- :key :j}]
[:l {:modi :A-H-M- :key :l}]
[:n {:modi :A-H-M- :key :n}]
[:o {:modi :A-H-M- :key :o}]
[:p {:modi :A-H-M- :key :p}]
[:q {:modi :A-H-M- :key :q}]
[:r {:modi :A-H-M- :key :r}]
[:s {:modi :A-H-M- :key :s}]
[:t {:modi :A-H-M- :key :t}]
[:u {:modi :A-H-M- :key :u}]
[:v {:modi :A-H-M- :key :v}]
[:w {:modi :A-H-M- :key :w}]
[:x {:modi :A-H-M- :key :x}]
[:y {:modi :A-H-M- :key :y}]
[:z {:modi :A-H-M- :key :z}]
[:semicolon {:modi :A-H-M- :key :semicolon}]
[:period {:modi :A-H-M- :key :period}]
[:slash {:modi :A-H-M- :key :slash}]
[:spacebar {:modi :A-H-M- :key :spacebar}]
[:return_or_enter {:modi :A-H-M- :key :return_or_enter}]
[:tab {:modi :A-H-M- :key :tab}]
]}
{:des "period-mode (manipulation)"
:rules [:period-mode
[:a {:modi :A-C-H- :key :a}]
[:b {:modi :A-C-H- :key :b}]
[:c {:modi :A-C-H- :key :c}]
[:d {:modi :A-C-H- :key :d}]
[:e {:modi :A-C-H- :key :e}]
[:f {:modi :A-C-H- :key :f}]
[:g {:modi :A-C-H- :key :g}]
[:h {:modi :A-C-H- :key :h}]
[:i {:modi :A-C-H- :key :i}]
[:j {:modi :A-C-H- :key :j}]
[:k {:modi :A-C-H- :key :k}]
[:l {:modi :A-C-H- :key :l}]
[:m {:modi :A-C-H- :key :m}]
[:n {:modi :A-C-H- :key :n}]
[:o {:modi :A-C-H- :key :o}]
[:p {:modi :A-C-H- :key :p}]
[:q {:modi :A-H-M-s- :key :9}] ; QCOq triggers ⌘⌃Q (lock screen)
[:r {:modi :A-C-H- :key :r}]
[:s {:modi :A-C-H- :key :s}]
[:t {:modi :A-C-H- :key :t}]
[:u {:modi :A-C-H- :key :u}]
[:v {:modi :A-C-H- :key :v}]
[:w {:modi :A-C-H- :key :w}]
[:x {:modi :A-C-H- :key :x}]
[:y {:modi :A-C-H- :key :y}]
[:z {:modi :A-C-H- :key :z}]
[:semicolon {:modi :A-C-H- :key :semicolon}]
[:comma {:modi :A-C-H- :key :comma}]
[:slash {:modi :A-C-H- :key :slash}]
[:spacebar {:modi :A-C-H- :key :spacebar}]
[:return_or_enter {:modi :A-C-H- :key :return_or_enter}]
]}
- Insert image of key layout
- Explain “logic” behind layout (e.g. single quotes, double quotes, and dashes as triplets in successive lines)
{:des "semicolon (symbols)"
:rules [:semicolon-mode
[:##a :percent_sign]
[:##b :grave_accent_and_tilde]
[:##c :open_bracket]
[:##d :close_parenthesis]
[:##e :number_sign]
[:##f :asterisk]
[:##g :caret]
[:##h :ampersand]
[:##i :open_single_quote]
[:##j :double_quote]
[:##k :open_double_quote]
[:##l :close_double_quote]
[:##m :hyphen]
[:##n :tilde]
[:##o :close_single_quote]
[:##q :exclamation_mark]
[:##r :dollar_sign]
[:##s :open_parenthesis]
[:##t :backslash]
[:##u :quote]
[:##v :close_bracket]
[:##w :at_sign]
[:##x :close_brace]
[:##y :vertical_bar]
[:##z :open_brace]
[:##comma :en_dash]
[:##period :em_dash]
[:##right_command :underscore]
]}
{:des "slash simlyaer → org-mode (Emacs) | app-specific macros (outside Emacs)"
:rules [:slash-mode
[:a {:modi :C-H-M-s- :key :a} :emacs]
[:b {:modi :C-H-M-s- :key :b} :emacs]
[:c {:modi :C-H-M-s- :key :c} :emacs]
[:d {:modi :C-H-M-s- :key :d} :emacs]
[:e {:modi :C-H-M-s- :key :e} :emacs]
[:f {:modi :C-H-M-s- :key :f} :emacs]
[:g {:modi :C-H-M-s- :key :g} :emacs]
[:h {:modi :C-H-M-s- :key :h} :emacs]
[:i {:modi :C-H-M-s- :key :i} :emacs]
[:j {:modi :C-H-M-s- :key :j} :emacs]
[:m {:modi :C-H-M-s- :key :m} :emacs]
[:n {:modi :C-H-M-s- :key :n} :emacs]
[:o {:modi :C-H-M-s- :key :o} :emacs]
[:p {:modi :C-H-M-s- :key :p} :emacs]
[:q {:modi :C-H-M-s- :key :q} :emacs]
[:r {:modi :C-H-M-s- :key :r} :emacs]
[:s {:modi :C-H-M-s- :key :s} :emacs]
[:t {:modi :C-H-M-s- :key :t} :emacs]
[:u {:modi :C-H-M-s- :key :u} :emacs]
[:v {:modi :C-H-M-s- :key :v} :emacs]
[:w {:modi :C-H-M-s- :key :w} :emacs]
[:z {:modi :C-H-M-s- :key :z} :emacs]
[:x {:modi :C-H-M-s- :key :x} :emacs]
[:y {:modi :C-H-M-s- :key :y} :emacs]
[:period {:modi :C-H-M-s- :key :period} :emacs]
[:a [:km "Local app a"] :!emacs]
[:b [:km "Local app b"] :!emacs]
[:c [:km "Local app c"] :!emacs]
[:d [:km "Local app d"] :!emacs]
[:e [:km "Local app e"] :!emacs]
[:f [:km "Local app f"] :!emacs]
[:g [:km "Local app g"] :!emacs]
[:h [:km "Local app h"] :!emacs]
[:i [:km "Local app i"] :!emacs]
[:j [:km "Local app j"] :!emacs]
[:k [:km "Local app k"] :!emacs]
[:l [:km "Local app l"] :!emacs]
[:m [:km "Local app m"] :!emacs]
[:n [:km "Local app n"] :!emacs]
[:o [:km "Local app o"] :!emacs]
[:p [:km "Local app p"] :!emacs]
[:q [:km "Local app q"] :!emacs]
[:r [:km "Local app r"] :!emacs]
[:s [:km "Local app s"] :!emacs]
[:t [:km "Local app t"] :!emacs]
[:u [:km "Local app u"] :!emacs]
[:v [:km "Local app v"] :!emacs]
[:w [:km "Local app w"] :!emacs]
[:x [:km "Local app x"] :!emacs]
[:y [:km "Local app y"] :!emacs]
[:z [:km "Local app z"] :!emacs]
[:0 [:km "Local app 0"] :!emacs]
[:1 [:km "Local app 1"] :!emacs]
[:2 [:km "Local app 2"] :!emacs]
[:3 [:km "Local app 3"] :!emacs]
[:4 [:km "Local app 4"] :!emacs]
[:5 [:km "Local app 5"] :!emacs]
[:6 [:km "Local app 6"] :!emacs]
[:7 [:km "Local app 7"] :!emacs]
[:8 [:km "Local app 8"] :!emacs]
[:9 [:km "Local app 9"] :!emacs]
[:semicolon [:km "Local app semicolon"] :!emacs]
[:comma [:km "Local app comma"] :!emacs]
[:period [:km "Local app period"] :!emacs]
[:return_or_enter [:km "Local app return_or_enter"] :!emacs]
[:spacebar [:km "Local app spacebar"] :!emacs]
]}
]}
- Hacking your keyboard with Karabiner
- Remap Keyboard Shortcuts Karabiner Elements. Video tutorial by John Lindquist.
- Karabiner God Mode
- Karabiner configuration reference manual
- Putting your Keyboard on Steroids with Karabiner Elements
- Hacking your keyboard with karabiner | Kaushik Gopal’s blog
letter | modifier |
---|---|
C | left_command |
T | left_control |
O | left_option |
S | left_shift |
F | fn |
Q | right_command |
W | right_control |
E | right_option |
R | right_shift |
- category: Modifier keys
- name: caps_lock
- name: left_control
- name: left_shift
- name: left_option
- name: left_command
- name: right_control
- name: right_shift
- name: right_option
- name: right_command
- name: fn
- category: Controls and symbols
- name: return_or_enter
- name: escape
- name: delete_or_backspace
- name: delete_forward
- name: tab
- name: spacebar
- name: hyphen label: hyphen (-)
- name: equal_sign label: equal_sign (=)
- name: open_bracket label: open_bracket [
- name: close_bracket label: close_bracket ]
- name: backslash label: backslash (\)
- name: non_us_pound
- name: semicolon label: semicolon (;)
- name: quote label: quote (‘)
- name: grave_accent_and_tilde label: grave_accent_and_tilde ()
- name: comma label: comma (,)
- name: period label: period (.)
- name: slash label: slash (/)
- name: non_us_backslash
- category: Arrow keys
- name: up_arrow
- name: down_arrow
- name: left_arrow
- name: right_arrow
- name: page_up
- name: page_down
- name: home
- name: end
- category: Letter keys
- name: a
- name: b
- name: c
- name: d
- name: e
- name: f
- name: g
- name: h
- name: i
- name: j
- name: k
- name: l
- name: m
- name: n
- name: o
- name: p
- name: q
- name: r
- name: s
- name: t
- name: u
- name: v
- name: w
- name: x
- name: y
- name: z
- category: Number keys
- name: ‘1’
- name: ‘2’
- name: ‘3’
- name: ‘4’
- name: ‘5’
- name: ‘6’
- name: ‘7’
- name: ‘8’
- name: ‘9’
- name: ‘0’
- category: Function keys
- name: f1
- name: f2
- name: f3
- name: f4
- name: f5
- name: f6
- name: f7
- name: f8
- name: f9
- name: f10
- name: f11
- name: f12
- name: f13
- name: f14
- name: f15
- name: f16
- name: f17
- name: f18
- name: f19
- name: f20
- name: f21 not_to: true
- name: f22 not_to: true
- name: f23 not_to: true
- name: f24 not_to: true
- category: Media controls
- name: display_brightness_decrement not_from: true
- name: display_brightness_increment not_from: true
- name: mission_control not_from: true
- name: launchpad not_from: true
- name: dashboard not_from: true
- name: illumination_decrement not_from: true
- name: illumination_increment not_from: true
- name: rewind not_from: true
- name: play_or_pause not_from: true
- name: fastforward not_from: true
- name: mute
- name: volume_decrement
- name: volume_increment
- name: eject not_from: true
- name: apple_display_brightness_decrement not_from: true
- name: apple_display_brightness_increment not_from: true
- name: apple_top_case_display_brightness_decrement not_from: true
- name: apple_top_case_display_brightness_increment not_from: true
- category: Keypad keys
- name: keypad_num_lock
- name: keypad_slash
- name: keypad_asterisk
- name: keypad_hyphen
- name: keypad_plus
- name: keypad_enter
- name: keypad_1
- name: keypad_2
- name: keypad_3
- name: keypad_4
- name: keypad_5
- name: keypad_6
- name: keypad_7
- name: keypad_8
- name: keypad_9
- name: keypad_0
- name: keypad_period
- name: keypad_equal_sign
- name: keypad_comma
- category: Virtual Keys
- name: vk_none label: vk_none (disable this key) not_from: true
- category: Keys in pc keyboards
- name: print_screen
- name: scroll_lock
- name: pause
- name: insert
- name: application
- name: help
- name: power
- name: execute not_to: true
- name: menu not_to: true
- name: select not_to: true
- name: stop not_to: true
- name: again not_to: true
- name: undo not_to: true
- name: cut not_to: true
- name: copy not_to: true
- name: paste not_to: true
- name: find not_to: true
- category: International keys
- name: international1
- name: international2 not_to: true
- name: international3
- name: international4 not_to: true
- name: international5 not_to: true
- name: international6 not_to: true
- name: international7 not_to: true
- name: international8 not_to: true
- name: international9 not_to: true
- name: lang1
- name: lang2
- name: lang3 not_to: true
- name: lang4 not_to: true
- name: lang5 not_to: true
- name: lang6 not_to: true
- name: lang7 not_to: true
- name: lang8 not_to: true
- name: lang9 not_to: true
- category: Japanese
- name: japanese_eisuu label: 英数キー
- name: japanese_kana label: かなキー
- name: japanese_pc_nfer label: PCキーボードの無変換キー not_to: true
- name: japanese_pc_xfer label: PCキーボードの変換キー not_to: true
- name: japanese_pc_katakana label: PCキーボードのかなキー not_to: true
- category: Others
- name: keypad_equal_sign_as400 not_to: true
- name: locking_caps_lock not_to: true
- name: locking_num_lock not_to: true
- name: locking_scroll_lock not_to: true
- name: alternate_erase not_to: true
- name: sys_req_or_attention not_to: true
- name: cancel not_to: true
- name: clear not_to: true
- name: prior not_to: true
- name: return label: rarely used return (HID usage 0x9e) not_to: true
- name: separator not_to: true
- name: out not_to: true
- name: oper not_to: true
- name: clear_or_again not_to: true
- name: cr_sel_or_props not_to: true
- name: ex_sel not_to: true
- name: left_alt label: left_alt (equal toleft_option)
- name: left_gui label: left_gui (equal toleft_command)
- name: right_alt label: right_alt (equal toright_option)
- name: right_gui label: right_gui (equal toright_command)
- name: vk_consumer_brightness_down label: vk_consumer_brightness_down (equal todisplay_brightness_decrement) not_from: true
- name: vk_consumer_brightness_up label: vk_consumer_brightness_up (equal todisplay_brightness_increment) not_from: true
- name: vk_mission_control label: vk_mission_control (equal tomission_control) not_from: true
- name: vk_launchpad label: vk_launchpad (equal tolaunchpad) not_from: true
- name: vk_dashboard label: vk_dashboard (equal todashboard) not_from: true
- name: vk_consumer_illumination_down label: vk_consumer_illumination_down (equal toillumination_decrement) not_from: true
- name: vk_consumer_illumination_up label: vk_consumer_illumination_up (equal toillumination_increment) not_from: true
- name: vk_consumer_previous label: vk_consumer_previous (equal torewind) not_from: true
- name: vk_consumer_play label: vk_consumer_play (equal toplay) not_from: true
- name: vk_consumer_next label: vk_consumer_next (equal tofastforward) not_from: true
- name: volume_down label: volume_down (equal tovolume_decrement)
- name: volume_up label: volume_up (equal tovolume_increment`)
Source: Wikipedia
letter | freq | normalized | used |
---|---|---|---|
E | 0.13000 | 1. | |
T | 0.09100 | 1.4285714 | |
A | 0.08200 | 1.5853659 | |
O | 0.07500 | 1.7333333 | |
I | 0.07000 | 1.8571429 | |
N | 0.06700 | 1.9402985 | |
S | 0.06300 | 2.0634921 | |
H | 0.06100 | 2.1311475 | |
R | 0.06000 | 2.1666667 | |
D | 0.04300 | 3.0232558 | |
L | 0.04000 | 3.25 | |
C | 0.02800 | 4.6428571 | |
U | 0.02800 | 4.6428571 | |
M | 0.02400 | 5.4166667 | |
W | 0.02400 | 5.4166667 | |
F | 0.02200 | 5.9090909 | t |
G | 0.02000 | 6.5 | |
Y | 0.02000 | 6.5 | |
P | 0.01900 | 6.8421053 | t |
B | 0.01500 | 8.6666667 | t |
V | 0.00980 | 13.265306 | t |
K | 0.00770 | 16.883117 | t |
J | 0.00150 | 86.666667 | t |
X | 0.00150 | 86.666667 | t |
Q | 0.00095 | 136.84211 | t |
Z | 0.00074 | 175.67568 | t |