Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
My source Karabiner file in Goku's edn format
{
;; ! | means mandatory - modifier(s) alone when pressend change behavior
;; # | means optional - modifiers are optional (but atleast one necessary)
;; :!Ca is keycode :a and prefix a with !C
;; 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
;; ## | optional any (this has no effect when used on the RHS; only LHS)
;; !! | command + control + optional + shift (hyper)
;; to understand better how modifiers work in karabiner
;; karabiner definition of mandatory and optional
;; https://karabiner-elements.pqrs.org/docs/json/complex-modifications-manipulator-definition/from/modifiers/
;; need to prefix C T O S F with ! or #
;;
;; code for all this:
;; https://github.com/yqrashawn/GokuRakuJoudo/blob/b9b334a187379f9bc8182ad59e2cca2a1789e9c0/src/karabiner_configurator/keys.clj#L68
:profiles {
:Default { :default true
:sim 100 ;; simultaneous_threshold_milliseconds (def: 50)
;; keys need to be pressed within this threshold to be considered simultaneous
:delay 500 ;; to_delayed_action_delay_milliseconds (def: 500)
;; basically it means time after which the key press is count delayed
:alone 500 ;; to_if_alone_timeout_milliseconds (def: 1000)
;; hold for 995s and single tap registered; hold for 1005s and seen as modifier
:held 1000 ;; to_if_held_down_threshold_milliseconds (def: 500)
;; key is fired twice when 500 ms is elapsed (otherwise seen as a hold command)
}
} ;; profiles
:templates {
:km "osascript -e 'tell application \"Keyboard Maestro Engine\" to do script \"%s\"'"
:open "open \"%s\""
} ;; templates
;; Define different kinds of keyboards
:devices {
:apple [
{:vendor_id 1452}
{:vendor_id 76}
]
:ap2 [{:vendor_id 1241, :product_id 41618 }] ;; Anne Pro 2 (mechanical)
:msft [{:vendor_id 1118, :product_id 1957 }] ;; Microsoft Keyboard [Ergonomic Sculpt]
:tada68 [{:vendor_id 65261, :product_id 4611 }] ;; Tada68 (mechanical)
:kinesis [{:vendor_id 10730 }] ;; Kinesis Advantage 2 keyboard
:kybs [ ;; Default for all keyboards
{:vendor_id 1452}
{:vendor_id 76}
{:vendor_id 1241, :product_id 41618 }
{:vendor_id 1118, :product_id 1957 }
{:vendor_id 65261, :product_id 4611 }
{:vendor_id 10730}
]
:kybs-kinesis [ ;; All keyboards (except Kinesis)
{:vendor_id 1452}
{:vendor_id 76}
{:vendor_id 1241, :product_id 41618 }
{:vendor_id 1118, :product_id 1957 }
{:vendor_id 65261, :product_id 4611 }
]
} ;; devices
;; layers are basically "hyper" keys
;; press this in combination with something else and depending on your rule, make things happen
:layers {
:launch-mode {:key :tab}
} ;; layers
;; simlayers are basically "hyper" keys
;; layers works too, but only recommended for non-typing keys like . or tab
;; to use more regular typing keys, use simlayers
:simlayers {
:d-mode {:key :d}
} ;; simlayers
:applications {
:terminals [ "^com\\.apple\\.Terminal$",
"^com\\.googlecode\\.iterm2$",
"^com\\.google\\.android\\.studio$"]
}
;; main contains multiple manipulators
:main [
;; each manipulator has a description and multiple rules
;;{:des "..." ;; -> description
;; :rules[
;; [<from> <to> <conditions>] ;; -> rule 1
;; [<from> <to> <conditions>] ;; -> rule 2
;; ]}
;; rule [:period ["period-mode" 1] nil {:afterup ["period-mode" 0] :alone :period}]
;; |_____| |_______________| |_| |_________________________________________|
;; <from> <to> <conditions> <other options>
;;
;; karabiner docs: ;; https://pqrs.org/osx/karabiner/json.html#complex_modifications-manipulator-definition
;; <other options> includs ~to_if_alone~, ~to_if_held_down~,~to_after_key_up~, ~to_delayed_action~ and ~parameters~.
;;
;; (custom variables) & modifiers -> Advanced
;; https://github.com/yqrashawn/GokuRakuJoudo/blob/master/examples.org#custom-variable
;; ----------------------------------
;; Hardware keyboard mappings
;; ----------------------------------
{:des "Tada68 specific mappings"
:rules [:ap2
[:left_option :left_command]
[:left_command :left_option]
]}
{:des "Tada68 specific mappings"
:rules [:tada68
[:delete_forward :end]
[:escape :grave_accent_and_tilde]
[:grave_accent_and_tilde :home]
[:left_gui :left_alt]
]}
{:des "Microsoft Ergonomic Sculpt Keyboard"
:rules [:msft
[:delete_forward :end]
[:escape :grave_accent_and_tilde]
[:grave_accent_and_tilde :home]
[:left_gui :left_alt]
]}
{:des "Kinesis Advantage2 specific mappings"
:rules [:kinesis
[:non_us_backslash :!QWspacebar] ;; § -> emoji viewer
[:open_bracket :backslash] ;; [ -> \
[:close_bracket :slash] ;; ] -> /
]}
;; ----------------------------------
;; Key mappings
;; ----------------------------------
{:des "delete sequences"
:rules [
;; delete word
[:u :!Tw [:d-mode :terminals]]
[:u :!Odelete_or_backspace [:d-mode :!terminals]]
;; backspace
[:i :delete_or_backspace :d-mode]
;; Training disable keys
[:delete_or_backspace :vk_none :!terminals]
;;[:!Odelete_or_backspace :vk_none :!terminals]
;;[:!CSdelete_or_backspace :vk_none :!terminals]
]}
{:des "home row enhancements (caps/vim/quick keys)"
:rules [
;; caps lock alone = escape ; hold = control
[:caps_lock ["caps-mode" 1] nil {:afterup ["caps-mode" 0]
:alone :escape}]
;; caps lock vim mode
[:##h :left_arrow ["caps-mode" 1]]
[:##j :down_arrow ["caps-mode" 1]]
[:##k :up_arrow ["caps-mode" 1]]
[:##l :right_arrow ["caps-mode" 1]]
;; switch tabs in most apps
;; Cmd Shift <-
[:##m :!CSopen_bracket ["caps-mode" 1]]
;; Cmd Shift ->
[:##comma :!CSclose_bracket ["caps-mode" 1]]
;; easier reach to modifier keys
[:slash :right_command nil {:alone :slash}]
[:z :left_control nil {:alone :z}]
;; easier key launches
[[:f :j] :!Ospacebar] ;; alfred
]
}
{:des "quick bracket/braces sequences"
:rules [
;; () - through caps lock
[:k :!S9 :d-mode]
[:l :!S0 :d-mode]
;; {} - through caps lock
[:j :!Sopen_bracket :d-mode]
[:semicolon :!Sclose_bracket :d-mode]
;; [] - through caps lock
[:s :open_bracket :d-mode]
[:f :close_bracket :d-mode]
;; Cmd/Ctrl -> () : primary thumb keys
[:##right_command :right_control :apple]
[:##right_option :right_control :ap2]
;; Alt -> [] or Meh(Control Shift Option): secondary thumb keys
;;[:##left_alt :left_option :apple {:alone :open_bracket}]
;;[:##right_alt :!TOleft_shift :apple {:alone :close_bracket}]
]}
{:des "launch-mode: quick open applications"
:rules [:launch-mode
[:y [:km "wm: def 1 major"] ] ;; Window move
[:u [:km "wm: def 1"] ] ;; Window move
[:i [:km "wm: def 2"] ] ;; Window move
[:o [:km "wm: def 3"] ] ;; Window move
[:p [:km "wm: def 3 major"] ] ;; Window move
[:j :!QWspacebar ] ;; e(m)oji
[:k [:km "trigger macro by name"] ] ;; keyboard maestro
[:l :!CSv ] ;; c(l)ipboard history
]}
] ;; main list
}
@njm2112

This comment has been minimized.

Copy link

@njm2112 njm2112 commented Apr 17, 2020

I'm having some difficulty implementing layer/simlayer functionality and wondered if you have any advice.

I am trying to create "o-mode" whereby pressing the letter o performs the typical behavior, but holding o and pressing another key executes a Keyboard Maestro macro. Here's an excerpt from my Karabiner.edn file:

:layers { :o-mode {:key :o} }

:simlayers {
    :caps-mode { :key :escape :alone { :key :escape :condi ["caps-mode" 0]}}
    :launch-mode { :key :caps_lock} },

    :main [
        {:des "o-mode -> Hold o + key" :rules [
            [:g [:km "Search using Google"]] [:o-mode] ]}       ;; pressing `g` while holding `o` triggers KM macro

        {:des "w-mode -> Hold w + key" :rules [
            [:left_arrow [:!CTOSleft_arrow] [:w-mode]]          ;; pressing `←` while holding `w` triggers `⌘⌃⌥⇧`  + `←`
            [:right_arrow [:!CTOSright_arrow] [:w-mode]]]} }    ;; pressing `➝` while holding `w` triggers `⌘⌃⌥⇧` +  `➝`

The trouble I'm having is that once I implement this and trigger "o-mode" once (o +g), it seems that I'm stuck in o-mode and everytime I press g (including in isolation), the Keyboard Maestro macro is triggered.

Is there something obvious about my config (that I'm missing) that is causing this behavior? Any insight you might have would be appreciated.

@kaushikgopal

This comment has been minimized.

Copy link
Owner Author

@kaushikgopal kaushikgopal commented May 30, 2020

@njm2112 so i definitely do something very similar so surprised it isn't working for you.

Can you rewrite your script like so:

:layers { :o-mode {:key :o} }
...
:main [

{:des "o-mode: quick open applications"
 :rules [:o-mode
            [:g [:km "Search using Google" ] ] ;; pressing `g` while holding `o` triggers KM macro
]}

That should do the trick. I have something like this and it works like a charm:

image

image

@einverne

This comment has been minimized.

Copy link

@einverne einverne commented Oct 13, 2020

It seems these two lines have a syntax error:

       [:!Ww :!TOSdelete_or_backspace !:terminals]
       [:!Tw :!TOSdelete_or_backspace !:terminals]

Should it be :!terminals?

@kaushikgopal

This comment has been minimized.

Copy link
Owner Author

@kaushikgopal kaushikgopal commented Oct 18, 2020

@einverne: right you are. i'll go ahead and update the script. that's a typo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.