Giter Club home page Giter Club logo

gokurakujoudo's Introduction

GokuRakuJoudo

img img

ExamplesTutorialTelegramGoku in the wild

  1. Intro
    1. Why use Goku?
    2. Install
    3. Usage
    4. Tutorial
    5. Note
    6. Changelog
    7. Dependencies
    8. Contributing

Intro

Goku is a tool that lets you manage your Karabiner configuration with ease.

Karabiner Elements uses JSON as its config file format. This leads to thousands of lines of JSON (sometimes over 20,000 lines), which makes it really hard to edit the config file and iterate on your keymap.

But fear not! Goku brings the edn format to the rescue.

Why use Goku?

Below are two Karabiner configuration snippets that map caps lock to an escape key.

karabiner.json

karabiner.edn

In practice this means that you can see multiple Karabiner rules on you screen as you edit your config with Goku. Which speeds up the iteration speed significantly as you can create new rules as little as few characters.

Install

brew install yqrashawn/goku/goku

Usage

Make sure you have a profile named "Default" in Karabiner's GUI tool. You can specify your own profile name using :profiles keyword.

img

Goku reads the karabiner.edn file which holds your Karabiner config. This file should be placed inside ~/.config/ directory on your Mac (you can start with example.edn). Starting from version 0.2.2, you can specify your config file path using the environment variable GOKU_EDN_CONFIG_FILE.

Goku provides two commands:

goku: Will update karabiner.json once. gokuw: Will keep watching your karabiner.edn and when it changes, it will update your karabiner.json configuration.

Run command brew services start goku to use it as a service (runs gokuw in background). When Goku is running as service, the logs are kept inside ~/Library/Logs/goku.log.

Use goku -h to learn more.

Tutorial

Read through the Tutorial about how you can write the configuration in Goku.

If there's any question or advice, just open an issue or join Karabiner Telegram group and ask your questions there.

Note

  • Using #_ to comment out rules like this will leave a null rule (see below) in karabiner.json, it won't cause any error.
    {
      "description" : null,
      "manipulators" : [ ]
    }

Changelog

Check CHANGELOG file.

Dependencies

watchexec for watching the edn config file.
joker for linting the edn config file.

Contributing

Use lein repl for developing.

Change Makefile.local.example's name to Makefile.local, change GRAALVM variable in the makefile to right path, run make local to test then generate goku binary file.

gokurakujoudo's People

Contributors

alvaro-prieto avatar einverne avatar etiennejcharles avatar gdinh avatar halafi avatar holybasil avatar imgbot[bot] avatar isaacplmann avatar jfhector avatar joshuawagner avatar kchen0x avatar kdubovikov avatar kiinoda avatar konfido avatar marcusmoore avatar muhammedzakir avatar narze avatar nikitavoloboev avatar nikolai-cc avatar prurph avatar recollir avatar reegnz avatar rgomezcasas avatar seeekr avatar shc avatar soenkehahn avatar tweoss avatar webappzero avatar yomotherboard avatar yqrashawn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gokurakujoudo's Issues

No :pipe key?

I've got a rule that types out "foo bar" but I want it to type "foo | bar"
I cannot find a key definition like :pipe
Is there one?
I have found :spacebar :hyphen etc

Support simultaneous keys of 3 or more

When setting <from> to simultaneous keys as combination of more than two keys (in simple syntax, e.g. [:a :b :c]), goku 0.2.9 yield error messages:

ERROR: invalid <from> in main section's XXX(rule description)
Failed!

I know that most Apple keyboards have only "2-key rollovers", but a number of three-key-combo or 4-key-combo, etc. can still be recognized by certain keyboards. And karabiner.json supports that syntax, so I think it's reasonable to adjust this behavior.

[Bug] rule specific simlayer threshold/conditions setting placed at the wrong place

{:des   "Vi Mode [D as Trigger Key]"
                       :rules [:vi-mode
                               [:##j :down_arrow nil {:params {:sim 432}}]
                               ....
                               ]}

should generates

{
  "description": "Vi Mode [D as Trigger Key]",
  "manipulators": [
    {
      "conditions": [
        {
          "name": "vi-mode",
          "type": "variable_if",
          "value": 1
        }
      ],
      "from": {
        "key_code": "j",
        "modifiers": {
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
          "key_code": "down_arrow"
        }
      ],
      "type": "basic"
    },
    {
      "from": {
        "simultaneous": [
          {
            "key_code": "d"
          },
          {
            "key_code": "j"
          }
        ],
        "simultaneous_options": {
          "detect_key_down_uninterruptedly": true,
          "key_down_order": "strict",
          "key_up_order": "strict_inverse",
          "key_up_when": "any",
          "to_after_key_up": [
            {
              "set_variable": {
                "name": "vi-mode",
                "value": 0
              }
            }
          ]
        }
      },
      "parameters": {
        "basic.simultaneous_threshold_milliseconds": 432
      },
      "to": [
        {
          "set_variable": {
            "name": "vi-mode",
            "value": 1
          }
        },
        {
          "key_code": "down_arrow"
        }
      ],
      "type": "basic"
    },
    ......
  ]
}

but generates

{
  "description": "Vi Mode [D as Trigger Key]",
  "manipulators": [
    {
      "conditions": [
        {
          "name": "vi-mode",
          "type": "variable_if",
          "value": 1
        }
      ],
      "from": {
        "key_code": "j",
        "modifiers": {
          "optional": [
            "any"
          ]
        }
      },
      "parameters": {
        "basic.simultaneous_threshold_milliseconds": 432
      },
      "to": [
        {
          "key_code": "down_arrow"
        }
      ],
      "type": "basic"
    },
    {
      "from": {
        "simultaneous": [
          {
            "key_code": "d"
          },
          {
            "key_code": "j"
          }
        ],
        "simultaneous_options": {
          "detect_key_down_uninterruptedly": true,
          "key_down_order": "strict",
          "key_up_order": "strict_inverse",
          "key_up_when": "any",
          "to_after_key_up": [
            {
              "set_variable": {
                "name": "vi-mode",
                "value": 0
              }
            }
          ]
        }
      },
      "parameters": {
        "basic.simultaneous_threshold_milliseconds": 250
      },
      "to": [
        {
          "set_variable": {
            "name": "vi-mode",
            "value": 1
          }
        },
        {
          "key_code": "down_arrow"
        }
      ],
      "type": "basic"
    },
    ......
  ]
}

should put

"parameters": {
        "basic.simultaneous_threshold_milliseconds": 432
},

in the both sim rules.

Using an optional parameter in a template?

I'm not familiar with clojure, is there a way to make the third parameter optional?

:templates {
  :alfred "osascript -e 'tell application \"Alfred 3\" to run trigger \"%s\" in workflow \"%s\" with argument \"%s\"'"
}

I added the third %s and now I'm getting errors because I have many callers without the 3rd argument, is there a way to mark it as optional?

Thanks

Simultaneous keys with hyper to shell command

I'd like to trigger a shell script by pressing hyper + space + left_arrow.

I've been trying to define the rule in different ways, but all of them trigger a ERROR: invalid <from> in main section.

How can I define such a rule?

I always get Key must be integer

Hey there,

Just trying to use this library but still its not working for me.

I used the example in the tutorial.

When i run

goku

I get the following

Exception in thread "main" java.lang.IllegalArgumentException: Key must be integer
	at java.lang.Throwable.<init>(Throwable.java:265)
	at java.lang.Exception.<init>(Exception.java:66)
	at java.lang.RuntimeException.<init>(RuntimeException.java:62)
	at java.lang.IllegalArgumentException.<init>(IllegalArgumentException.java:52)
	at clojure.lang.APersistentVector.assoc(APersistentVector.java:345)
	at clojure.lang.APersistentVector.assoc(APersistentVector.java:18)
	at clojure.lang.RT.assoc(RT.java:792)
	at clojure.core$assoc__4371.invokeStatic(core.clj:191)
	at clojure.core$assoc__4371.invoke(core.clj:190)
	at karabiner_configurator.core$update_to_karabiner_json.invokeStatic(core.clj:76)
	at karabiner_configurator.core$update_to_karabiner_json.invoke(core.clj:66)
	at karabiner_configurator.core$parse_edn.invokeStatic(core.clj:82)
	at karabiner_configurator.core$parse_edn.invoke(core.clj:81)
	at karabiner_configurator.core$_main.invokeStatic(core.clj:150)
	at karabiner_configurator.core$_main.doInvoke(core.clj:145)
	at clojure.lang.RestFn.invoke(RestFn.java:397)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at karabiner_configurator.core.main(Unknown Source)
	at [com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:163)](url)

Can there be better example added?

Use modifier only in layer

Hi, is it possible to use a combination of modifier key only in layers without key code?

{:layers {foobar {:modi [:left_shift : left_control]}}}

Strange behavior of sim layer

I'm not sure if this is the problem with my Goku configuration, but maybe someone can give advice.

I utilize sim layer with s-key to navigate a cursor; adding a spacebar as a right_shift works great in all directions, only with the left_arrow/h doesn't work.

I quit Keyboard Maestro/Engine and Hammerspoon, disabled all shortcuts in Preferences: nothing helps.

I would really appreciate any suggestions since the shift is the only missing puzzle in this kind-of-vim navigation.

:simlayers {:s-mode {:key :s}}

{:des "s-key"
        :rules[:s-mode

        [:e :delete_forward]
        [:##d :delete_or_backspace]
        [:c :!Cdelete_or_backspace] ;; delete line

        ;; navigation
        [:##h :left_arrow]
        [:##k :up_arrow]
        [:##j :down_arrow]
        [:##l :right_arrow]

        [:spacebar :right_shift] ;; works with j/k/l, not with h/left_arrow
        
        [:##f :right_command]
        [:##a :right_option]
        
        [:##semicolon :return_or_enter]

        [:close_bracket :!CSslash] ; search/help
        [:open_bracket :!CTspacebar] ; emojis in Alfred
                
        [:r [:km "Cut Line"]]
        [:g [:km "Cut Word"]]]}

Thank you and stay safe!

Map literal must contain an even number of forms Syntax Error

karabiner.edn:10:1: Read error: Map literal must contain an even number of forms Syntax Error

file content:

{:profiles
 {:Goku {:sim 100
         :delay 500
         :alone 1000
         :held 500}}
 {:test {:sim     50
         :delay   500
         :alone   1000
         :held    500}}
}

Syntax error, but I can not find the Syntax error.

Support variables other than "1"

I'd really like to check when

:multitouch_extension_finger_count

is set to "2", but I've spent hours reading the docs and examples and can't find a way.

My goal is to use 2 fingers on the trackpad as a shift key.

adding rules for held + alone + selective mapping

I'm trying to "supercharge" my caps lock key with the following behavior:

  1. if tapped alone - send escape key
  2. if held - emulate left_control
  3. if held in combination with some specific letters (for e.g. caps_lock + j -> send down_arrow)

Any 2 of the above conditions is possible, but if i want to write a goku rule to encompass all 3, i can't seem to find a way to do it, without tediously jotting down all the possible combinations? seems like i'm missing something basic in the way i have my rules listed out. Currently what i have:

:layers {
    :homerow-mode {:key :caps_lock :alone {:key :escape}}
} ;; layers

:main [
 
    {:des "CapsLock: vim navigation"
     :rules [:homerow-mode
                [:h :left_arrow]
                [:j :down_arrow]
                [:k :up_arrow]
                [:l :right_arrow]
                [:!Sh :!Sleft_arrow]
                [:!Sj :!Sdown_arrow]
                [:!Sk :!Sup_arrow]
                [:!Sl :!Sright_arrow]
                [:!Ch :!Cleft_arrow]
                [:!Cj :!Cdown_arrow]
                [:!Ck :!Cup_arrow]
                [:!Cl :!Cright_arrow]
                [:!CSh :!CSleft_arrow]
                [:!CSj :!CSdown_arrow]
                [:!CSk :!CSup_arrow]
                [:!CSl :!CSright_arrow]
                [:!Oh :!Oleft_arrow]
                [:!Oj :!Odown_arrow]
                [:!Ok :!Oup_arrow]
                [:!Ol :!Oright_arrow]
                [:!OSh :!OSleft_arrow]
                [:!OSj :!OSdown_arrow]
                [:!OSk :!OSup_arrow]
                [:!OSl :!OSright_arrow]
     ]}

]

I feel there's got to be a better way to say, default to left_control when held, but under special cirucmstances do a different action

Converting from json?

I found (and made) a bunch of json configurations. Then I found Goku.
If Goku uses its own profile, can I somehow combine its json output with existing json modifications?
Or maybe there's a way to convert json rules into goku rules?

I tried searching for all this but I couldn't find people having this problem.
Any advice? I want to use for example the Mouse Keys modification from the website, but the json is over 900 lines, how should I go about converting it or using it in conjunction with new rules that I'd write in Goku?

Thanks

Multiple simlayers

Is it possible to add multiple simlayers in the same file?

If yes, can someone add example syntax?

Things i tried:

:simlayers {:h-mod {:key :h}}
:simlayers {:g-mod {:key :g}}

==> Read error: Duplicate key :simlayers

:simlayers {
    :h-mod {:key :h}
    :g-mod {:key :g}
  }

==> creates false positive parsing
(shows Done! but g-mod does not show up and changes to h-mod also don't show up)

:simlayers [
    :h-mod {:key :h}
    :g-mod {:key :g}
  ]

==> Exception: nth not supported on this type: Keyword

:simlayers {[
    {:h-mod {:key :h}}
    {:g-mod {:key :g}}
  ]}

==> Read error: Map literal must contain an even number of forms

Adjust basic.simultaneous_threshold_milliseconds

First, thank you for creating this fantastic tool for configuring Karabiner, it's immensely helpful!

I have some problems with sometimes accidentally triggering some events while writing text, e.g. for the below rule I sometimes get an asterisk when writing words containing “sv”.

{:des “s-key (special characters)"
 :rules [:s-mode
            [:v :!Rbackslash] ; asterisk *
            ]}

I've tried to adjust the default timing parameters but it does not seem to help, currently using:

 {:Default {:default true
         :sim     50
         :delay   500
         :alone   1000
         :held    500}}

I'm not sure exactly how these delay parameters work and in what way to adjust them to avoid accidental triggering, since it seems somewhat poorly documented. I wonder if I would also need to adjust the 'basic.simultaneous_threshold_milliseconds' parameter. This seems to be static at 250 ms regardless of the default settings above. Can it be changed using Goku?

I'm grateful for any advice how to solve the problem of accidentally triggering rules when typing ordinary text.

Friendly error message

Error messages are generated with assert right now for debugger. Maybe we should format it a bit and make it show less stack trace.

Using Goku without Homebrew

I noticed that there is a nix package for Goku, but I can't figure out how to actually use it without using a brew service. Would be nice to have some manual or Nixpkgs documentation.

Seems goku can't find joker bin file when running with brew service

Exception in thread "main" java.io.IOException: Cannot run program "joker": error=2, null
	at java.lang.Throwable.<init>(Throwable.java:287)
	at java.lang.Exception.<init>(Exception.java:84)
	at java.io.IOException.<init>(IOException.java:81)
	at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
	at java.lang.Runtime.exec(Runtime.java:620)
	at clojure.java.shell$sh.invokeStatic(shell.clj:113)
	at clojure.java.shell$sh.doInvoke(shell.clj:79)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at karabiner_configurator.core$check_edn_syntax.invokeStatic(core.clj:86)
	at karabiner_configurator.core$check_edn_syntax.invoke(core.clj:85)
	at karabiner_configurator.core$parse_edn.invokeStatic(core.clj:89)
	at karabiner_configurator.core$parse_edn.invoke(core.clj:88)
	at karabiner_configurator.core$_main.invokeStatic(core.clj:157)
	at karabiner_configurator.core$_main.doInvoke(core.clj:152)
	at clojure.lang.RestFn.invoke(RestFn.java:397)
	at clojure.lang.AFn.applyToHelper(AFn.java:152)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at karabiner_configurator.core.main(Unknown Source)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:163)
Caused by: java.io.IOException: error=2, null
	at java.lang.Throwable.<init>(Throwable.java:265)
	at java.lang.Exception.<init>(Exception.java:66)
	at java.io.IOException.<init>(IOException.java:58)
	at com.oracle.svm.core.posix.Target_java_lang_UNIXProcess.forkAndExec(PosixJavaLangSubstitutions.java:319)
	at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
	at java.lang.ProcessImpl.start(ProcessImpl.java:134)
	at java.lang.ProcessBui

Create Karabiner JSON -> Goku converter

Would be useful for people trying to switch over from painstakingly writing Karabiner JSON to Goku.

Not a huge issue but can be helpful and there was a person in Telegram Karabiner group asking for something like it.

[Question] Karabiner 12.4.0

Hello!

Is it safe to update to the latest version of Karabiner (12.4.0)?

I've seen a few things changing in the two previous minor releases, and I don't want to risk a sloppy update :D

Thanks!

Running goku / gokuw command gives errors

Hey there,

This is my first time trying to run goku. I added an example to by karabiner.edn as described in the tutorial.

Now when I run goku command i get:

Exception in thread "main" java.lang.IllegalArgumentException: Key must be integer
        at java.lang.Throwable.<init>(Throwable.java:265)
        at java.lang.Exception.<init>(Exception.java:66)
        at java.lang.RuntimeException.<init>(RuntimeException.java:62)
        at java.lang.IllegalArgumentException.<init>(IllegalArgumentException.java:52)
        at clojure.lang.APersistentVector.assoc(APersistentVector.java:345)
        at clojure.lang.APersistentVector.assoc(APersistentVector.java:18)
        at clojure.lang.RT.assoc(RT.java:792)
        at clojure.core$assoc__4371.invokeStatic(core.clj:191)
        at clojure.core$assoc__4371.invoke(core.clj:190)
        at karabiner_configurator.core$update_to_karabiner_json.invokeStatic(core.clj:76)
        at karabiner_configurator.core$update_to_karabiner_json.invoke(core.clj:66)
        at karabiner_configurator.core$parse_edn.invokeStatic(core.clj:82)
        at karabiner_configurator.core$parse_edn.invoke(core.clj:81)
        at karabiner_configurator.core$_main.invokeStatic(core.clj:150)
        at karabiner_configurator.core$_main.doInvoke(core.clj:145)
        at clojure.lang.RestFn.invoke(RestFn.java:397)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.RestFn.applyTo(RestFn.java:132)
        at karabiner_configurator.core.main(Unknown Source)
        at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:163)

How to batch keystrokes together

It's not clear how I can batch multiple keystrokes together in the action.

I want to make a binding on b key to insert TODO: . With a space after.

I would think I'd have to do something like this [:b [:T][:O]] to achieve this but not sure. The tutorial is not clear about it either.

type unicode characters

Does Goku provide a way to configure a key sequence rule for typing unicode characters ? I couldn't find one in the examples. I want to a rule like [[:right_shift :up_arrow] :↑] to type ↑ when I do right-shift+up-arrow

simlayers key output order

I've been toying with the following:

     :simlayers 
      {  :numpad-mode {:key :s}}
....
       {:des "numpad mode"
                 :rules [[:u :7      :numpad-mode {:key_up_order :strict}]
                         [:i :8      :numpad-mode {:key_up_order :strict}]
                         [:o :9      :numpad-mode {:key_up_order :strict}]

                         [:j :4      :numpad-mode {:key_up_order :strict}]
                         [:k :5      :numpad-mode {:key_up_order :strict}]
                         [:l :6      :numpad-mode {:key_up_order :strict}]

                         [:m :1      :numpad-mode {:key_up_order :strict}]
                         [:comma :2  :numpad-mode {:key_up_order :strict}]
                         [:period :3 :numpad-mode {:key_up_order :strict}]

                         [:n :0 :numpad-mode]
                         ]}

This lets me type numbers using s + uiojkl. However, it doesn't quite work. If I type m,k while holding s, I get 51 as output instead of the expected 15.

This might be a just me not finding the necessary documentation, but I'm stumped? What should I change?

gokuw does not obey $GOKU_EDN_CONFIG_FILE

$ echo $GOKU_EDN_CONFIG_FILE
/Users/nonono/.config/karabiner/karabiner.edn

$ cat $(which gokuw)
#!/bin/sh
watchexec -r -w ~/.config/karabiner.edn /usr/local/opt/goku/bin/goku

Can't define layer that maps a key to a modified key if sublayer uses that key

Description might sound a little weird, but I have a defined tab-mode, yabai-move-mode yabai-scale-mode that all make use of the same keybindings h,j,k,l,o,n but map those keys to shell-commands. These modes work fine.

But then, I have a spec-mode which maps h,j,k,l to a mod-key entry, but karabiner refuses to see this as input after running goku. If I change the keys to something like y,u,i,o then it works.

My guess has something to do with tab-mode already using h,j,k,l but it works fine for other modes. So I'm not sure why it would prevent me from mapping to a mod-key entry. Here is my karabiner.edn for reference (heavily inspired by your .edn file):

{:profiles
 {:Default     {:default true
                :sim     50
                :delay   500
                :alone   500
                :held    500}}
 :applications {:vmware   ["^com\\.vmware\\.fusion$"]
                :emacs    ["^org\\.gnu\\.Emacs$"]
                :firefox  ["^org\\.mozilla\\.firefox$"]}
 :layers       {:tab-mode           {:key :tab
                                     :afterup [{:set ["yabai-move-mode" 0]}
                                               {:set ["yabai-scale-mode" 0]}
                                               {:set ["spec-mode" 0]}]}
                :spec-mode          {:key :s :condi :tab-mode}
                :yabai-insert-mode  {:key :i :condi :tab-mode}
                :yabai-move-mode    {:key :f :condi :tab-mode}
                :yabai-scale-mode   {:key :c :condi :tab-mode}}
 :main         [
                {:des "caps to ctrl modifier"
                 :rules [[:##caps_lock :left_control]]}

                {:des "left ctrl to right ctrl"
                 :rules [[:##left_control :right_control]]}

                {:des "yabai insert mode"
                 :rules [:yabai-insert-mode
                         [:h "/usr/local/bin/yabai -m window --insert west"]
                         [:j "/usr/local/bin/yabai -m window --insert south"]
                         [:k "/usr/local/bin/yabai -m window --insert north"]
                         [:l "/usr/local/bin/yabai -m window --insert east"]]}

                {:des "yabai move mode"
                 :rules [:yabai-move-mode
                         [:h "/usr/local/bin/yabai -m window --warp west"]
                         [:j "/usr/local/bin/yabai -m window --warp south"]
                         [:k "/usr/local/bin/yabai -m window --warp north"]
                         [:l "/usr/local/bin/yabai -m window --warp east"]
                         [:o "/usr/local/bin/yabai -m window --warp prev"]
                         [:n "/usr/local/bin/yabai -m window --warp next"]
                         [:period "/usr/local/bin/yabai -m window --display next"]
                         [:comma "/usr/local/bin/yabai -m window --display previous"]
                         [:open_bracket "/usr/local/bin/yabai -m window --space prev"]
                         [:close_bracket "/usr/local/bin/yabai -m window --space next"]]}

                {:des "yabai scale mode"
                 :rules [:yabai-scale-mode
                         [:h "~/.local/bin/yabai-resize left"]
                         [:j "~/.local/bin/yabai-resize down"]
                         [:k "~/.local/bin/yabai-resize up"]
                         [:l "~/.local/bin/yabai-resize right"]]}

                {:des "tab mode"
                 :rules [:tab-mode
                         [:grave_accent_and_tilde "launchctl kickstart -k \"gui/${UID}/homebrew.mxcl.yabai\""]
                         [:o "~/.local/bin/yabai-prev"]
                         [:n "~/.local/bin/yabai-next"]
                         [:h "/usr/local/bin/yabai -m window --focus west"]
                         [:j "/usr/local/bin/yabai -m window --focus south"]
                         [:k "/usr/local/bin/yabai -m window --focus north"]
                         [:l "/usr/local/bin/yabai -m window --focus east"]
                         [:a "/usr/local/bin/yabai -m window --toggle float"]
                         [:b "/usr/local/bin/yabai -m window --layout bsp"]
                         [:m "/usr/local/bin/yabai -m window --toggle zoom-parent"]
                         [:p "/usr/local/bin/yabai -m window --toggle pip"]
                         [:spacebar "yabai -m window --toggle zoom-fullscreen"]
                         [:delete_or_backspace "/usr/local/bin/yabai -m window --close"]]}

                {:des "spec mode"
                 :rules [:spec-mode
                         [:y :!COleft_arrow]
                         [:u :!COdown_arrow]
                         [:i :!COup_arrow]
                         [:o :!COright_arrow]]}
                ]}

Example doesn't work

Looks like example.edn doesn't work:

❯ goku
Syntax error in config:
/Users/devall/.config/karabiner.edn:69:45: Read error: Map literal must contain an even number of forms

Will Goku consider add specify file path feature?

I use mackup to backup my settings of almost all my applications, which means the karabienr.edn file path is /allmyfiles/macOS-HOME/Mackup/.config/karabiner/karabienr.edn.

Goku couldn't read from '/Users/$(whoami)/.config/karabiner.edn(symbolic link)'.

Here is the log:

Error: Path error: couldn't canonicalize '/Users/$(whoami)/.config/karabiner.edn':
Too many levels of symbolic links (os error 62)

So I move karabiner.edn back to /Users/$(whoami)/.config/karabiner.edn.

Support more than 5 buttons in ":pkey"

I have a mouse with 7 buttons. According to the Karabiner Event Viewer, the seventh button sends a combination of (tab, left_control, left_alt). I wanted to use Goko to translate this into 'button7' instead.

I tried a rule like this:

{:des "enable extra mouse btn" :rules [[:!TOtab {:pkey :button7}]]}

When I run goku I get this result:

ERROR: invalid pointing key code :button7
Failed!

I'm not a clojure guy, but keys-info.clj makes it look like the pkey keyword will only support up to :button5. I think (from playing with the 'Simple modifications' tab) Karabiner-Elements supports up to button32. Can goku be extended with support for more buttons?

Thanks.

parse :held :delayed in simlayer

:simlayers {:test-mode {:key :9}}
;; and
{:des "example"
         :rules [[:k "say 'k double press'" [["test-mode" 1] ["test-mode-k-dbpress-mode" 1]]]
                 :test-mode
                 [:j "say 'j press down'" nil {:held "say 'j held down'"}]
                 [:k ["say 'k press down'"  ["test-mode-k-dbpress-mode" 1]] nil {:delayed {:canceled ["test-mode-k-dbpress-mode" 0]
                                                                                           :invoked ["test-mode-k-dbpress-mode" 0]}}]]}

to json config

{
  "description": "example",
  "manipulators": [
    {
      "from": {
        "key_code": "k"
      },
      "to": [
        {
          "shell_command": "say 'k double press'"
        }
      ],
      "conditions": [
        {
          "name": "test-mode",
          "value": 1,
          "type": "variable_if"
        },
        {
          "name": "test-mode-k-dbpress-mode",
          "value": 1,
          "type": "variable_if"
        }
      ],
      "type": "basic"
    },
    {
      "to_if_held_down": [
        {
          "shell_command": "say 'j held down'"
        }
      ],
      "from": {
        "key_code": "j"
      },
      "to": [
        {
          "shell_command": "say 'j press down'"
        }
      ],
      "conditions": [
        {
          "name": "test-mode",
          "value": 1,
          "type": "variable_if"
        }
      ],
      "type": "basic"
    },
    {
      "type": "basic",
      "parameters": {
        "basic.simultaneous_threshold_milliseconds": 250
      },
      "to_if_held_down": [
        {
          "shell_command": "say 'j held down'"
        }
      ],
      "to": [
        {
          "set_variable": {
            "name": "test-mode",
            "value": 1
          }
        },
        {
          "shell_command": "say 'j press down'"
        }
      ],
      "from": {
        "simultaneous": [
          {
            "key_code": "9"
          },
          {
            "key_code": "j"
          }
        ],
        "simultaneous_options": {
          "detect_key_down_uninterruptedly": true,
          "key_down_order": "strict",
          "key_up_order": "strict_inverse",
          "key_up_when": "any",
          "to_after_key_up": [
            {
              "set_variable": {
                "name": "test-mode",
                "value": 0
              }
            }
          ]
        }
      }
    },
    {
      "to_delayed_action": {
        "to_if_invoked": [
          {
            "set_variable": {
              "name": "test-mode-k-dbpress-mode",
              "value": 0
            }
          }
        ],
        "to_if_canceled": [
          {
            "set_variable": {
              "name": "test-mode-k-dbpress-mode",
              "value": 0
            }
          }
        ]
      },
      "from": {
        "key_code": "k"
      },
      "to": [
        {
          "shell_command": "say 'k press down'"
        },
        {
          "set_variable": {
            "name": "test-mode-k-dbpress-mode",
            "value": 1
          }
        }
      ],
      "conditions": [
        {
          "name": "test-mode",
          "value": 1,
          "type": "variable_if"
        }
      ],
      "type": "basic"
    },
    {
      "type": "basic",
      "parameters": {
        "basic.simultaneous_threshold_milliseconds": 250
      },
      "to_delayed_action": {
        "to_if_invoked": [
          {
            "set_variable": {
              "name": "test-mode-k-dbpress-mode",
              "value": 0
            }
          }
        ],
        "to_if_canceled": [
          {
            "set_variable": {
              "name": "test-mode-k-dbpress-mode",
              "value": 0
            }
          }
        ]
      },
      "to": [
        {
          "set_variable": {
            "name": "test-mode",
            "value": 1
          }
        },
        {
          "shell_command": "say 'k press down'"
        },
        {
          "set_variable": {
            "name": "test-mode-k-dbpress-mode",
            "value": 1
          }
        }
      ],
      "from": {
        "simultaneous": [
          {
            "key_code": "9"
          },
          {
            "key_code": "k"
          }
        ],
        "simultaneous_options": {
          "detect_key_down_uninterruptedly": true,
          "key_down_order": "strict",
          "key_up_order": "strict_inverse",
          "key_up_when": "any",
          "to_after_key_up": [
            {
              "set_variable": {
                "name": "test-mode",
                "value": 0
              }
            }
          ]
        }
      }
    }
  ]
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.