yqrashawn / GokuRakuJoudo

config karabiner with ease
GNU General Public License v3.0
1.16k stars 121 forks source link

Recreate all modifiers and arrows on home row keys? #107

Closed chrismo closed 3 years ago

chrismo commented 3 years ago

As I've played around with this, I think what I had conceived of is just a bit too nuts for either Karabiner-Elements or goku. The basic idea is to have the left hand home row keys replace shift, option, and command, and the right hand home row keys be arrow keys.

I tried a couple approaches with layers and simlayers, and while just holding the f key to go into "command+arrows" worked well and was simple (j,k,i,l being the arrows), adding in the s key for shift is what got me. I tried even just doing it straight in karabiner.json, and came up with one approach that was better than what I could get with goku, but still not adequate.

Anyway - I'm still a n00b and it's totally fine if this is out of scope for what these tools can do, but I've also seen some fairly fancy stuff, so I figured it couldn't hurt to ask.

yqrashawn commented 3 years ago

I tried even just doing it straight in karabiner.json, and came up with one approach that was better than what I could get with goku, but still not adequate.

Can you share your config in json format here?

chrismo commented 3 years ago

Actually, I kept picking away at this and came up with this .edn. It's only the left arrow, and only option / shift, but so far is working. :)

{:profiles {:Default {:default true
                      ;; simultaneous_threshold_milliseconds (def: 50)
                      ;; keys need to be pressed within this threshold to be considered simultaneous
                      :sim     50
                      ;; to_delayed_action_delay_milliseconds (def: 500)
                      ;; basically it means time after which the key press is count delayed
                      :delay   500
                      ;; to_if_alone_timeout_milliseconds (def: 1000)
                      ;; hold for 995s and single tap registered; hold for 1005s and seen as modifier
                      :alone   1000
                      ;; to_if_held_down_threshold_milliseconds (def: 500)
                      ;; key is fired twice when 500 ms is elapsed (otherwise seen as a hold command)
                      ;; increase this value to allow you to hold a simlayer key longer before the next key is pressed
                      :held    1000}}
 :main     [;
             {:des   "from j to opt+shift+left if opt-shift-arrow-mode"
              :rules [[:j :!SOleft_arrow :opt-shift-arrow-mode]]};
             {:des   "from sim [f,s,j] to opt+shift+left and set opt-shift-arrow-mode until after key_up"
              :rules [[{:sim  [:f :s :j]
                        :simo {:interrupt true
                               :dorder    :insensitive
                               :uorder    :insensitive
                               :afterup   {:set ["opt-shift-arrow-mode" 0]}}}
                       [{:set ["opt-shift-arrow-mode" 1]} :!SOleft_arrow]
                       nil
                       {:params {:sim 250}}]]}
             {:des   "from sim [s,j] to opt+shift+left and set opt-shift-arrow-mode until after key_up and unset opt-arrow _all_ if opt-arrow set"
              :rules [:opt-arrow-mode
                      [{:sim  [:s :j]
                        :simo {:interrupt true
                               :dorder    :insensitive
                               :uorder    :insensitive
                               :afterup   [{:set ["opt-shift-arrow-mode" 0]}
                                           {:set ["opt-arrow-mode" 1]}]}}
                       [{:set ["opt-shift-arrow-mode" 1]}
                        {:set ["opt-arrow-mode" 0]}
                        :!SOleft_arrow]
                       nil
                       {:params {:sim 250}}]]}
             {:des   "from s to opt-shift-arrow-mode if opt-arrow-mode"
              :rules [:opt-arrow-mode
                      [:s
                       ["opt-shift-arrow-mode" 1]
                       nil
                       {:afterup [["opt-shift-arrow-mode" 0] ["opt-arrow-mode" 1]]}]]}
             {:des   "from j to opt+left if opt-arrow-mode"
              :rules [:opt-arrow-mode
                      [:j :!Oleft_arrow]]}
             {:des   "from sim [f,j] to opt+left and set opt-arrow-mode until after key_up"
              :rules [[{:sim  [:f :j]
                        :simo {:interrupt true
                               :dorder    :insensitive
                               :uorder    :insensitive
                               :afterup   {:set ["opt-arrow-mode" 0]}}}
                       [{:set ["opt-arrow-mode" 1]} :!Oleft_arrow]
                       nil
                       {:params {:sim 250}}]]}
             ;
             ]
 ;
 }
chrismo commented 3 years ago
              :rules [[{:sim  [:f :s :j]
                        :simo {:interrupt true
                               :dorder    :insensitive
                               :uorder    :insensitive
                               :afterup   {:set ["opt-shift-arrow-mode" 0]}}}
                       [{:set ["opt-shift-arrow-mode" 1]} :!SOleft_arrow]
                       nil
                       {:params {:sim 250}}]]}

this rule is used 3 times so far with very little variation. is there a way to DRY this out?

chrismo commented 3 years ago

bah, there's a use case here that doesn't work, overlapping simultaneous rules and inconsistent afterup behavior - but it's a karabiner issue, not goku. even if that wasn't a problem, there are too many accidental triggers this way during normal typing anyway.

if there are any useful goku tips to do anything that I've done simpler, I'd still like to learn better goku syntax, but ... on the primary issue I'm going to have to take a different approach.

yqrashawn commented 3 years ago

Here is an example using goku's simlayer. 2 + hjkl... to enter k2-mode and trigger corresponding keys when it's not in tab-mode or tmux-winmove-mode code1 code2

chrismo commented 3 years ago

The second links are using just layer, not simlayer, which I'd read wasn't a good option if I type quickly?

chrismo commented 3 years ago

This is much simpler - toggle caps-key into the mode, then I can just do everything straightforward.

{:profiles {:Default {:default true
                      ;; simultaneous_threshold_milliseconds (def: 50)
                      ;; keys need to be pressed within this threshold to be considered simultaneous
                      :sim     50
                      ;; to_delayed_action_delay_milliseconds (def: 500)
                      ;; basically it means time after which the key press is count delayed
                      :delay   500
                      ;; to_if_alone_timeout_milliseconds (def: 1000)
                      ;; hold for 995s and single tap registered; hold for 1005s and seen as modifier
                      :alone   1000
                      ;; to_if_held_down_threshold_milliseconds (def: 500)
                      ;; key is fired twice when 500 ms is elapsed (otherwise seen as a hold command)
                      ;; increase this value to allow you to hold a simlayer key longer before the next key is pressed
                      :held    1000}}

 :main     [;
             {:des   "escape kills all home row modifier arrow modes"
              :rules [[:escape
                       [:escape
                        {:set ["arrows-mode" 0]}
                        {:set ["shift-mode" 0]}
                        {:set ["command-mode" 0]}
                        {:set ["option-mode" 0]}]]]}

             {:des   "toggle arrows with caps"
              :rules [[:caps_lock ["arrows-mode" 0] :arrows-mode]
                      [:caps_lock ["arrows-mode" 1]]]}

             {:des   "modifiers"
              :rules [:arrows-mode
                      [:s ["shift-mode" 1] nil {:afterup ["shift-mode" 0]}]
                      [:d ["command-mode" 1] nil {:afterup ["command-mode" 0]}]
                      [:f ["option-mode" 1] nil {:afterup ["option-mode" 0]}]]}

             {:des   "arrows plain"
              :rules [[:condi :arrows-mode :!shift-mode :!command-mode :!option-mode]
                      [:j :left_arrow]
                      [:k :down_arrow]
                      [:l :right_arrow]
                      [:i :up_arrow]]}

             {:des   "arrows shift"
              :rules [[:condi :arrows-mode :shift-mode :!command-mode :!option-mode]
                      [:j :!Sleft_arrow]
                      [:k :!Sdown_arrow]
                      [:l :!Sright_arrow]
                      [:i :!Sup_arrow]]}

             {:des   "arrows command"
              :rules [[:condi :arrows-mode :!shift-mode :command-mode :!option-mode]
                      [:j :!Cleft_arrow]
                      [:k :!Cdown_arrow]
                      [:l :!Cright_arrow]
                      [:i :!Cup_arrow]]}

             {:des   "arrows option"
              :rules [[:condi :arrows-mode :!shift-mode :!command-mode :option-mode]
                      [:j :!Oleft_arrow]
                      [:k :!Odown_arrow]
                      [:l :!Oright_arrow]
                      [:i :!Oup_arrow]]}

             {:des   "arrows shift-command"
              :rules [[:condi :arrows-mode :shift-mode :command-mode :!option-mode]
                      [:j :!SCleft_arrow]
                      [:k :!SCdown_arrow]
                      [:l :!SCright_arrow]
                      [:i :!SCup_arrow]]}

             {:des   "arrows shift-option"
              :rules [[:condi :arrows-mode :shift-mode :!command-mode :option-mode]
                      [:j :!SOleft_arrow]
                      [:k :!SOdown_arrow]
                      [:l :!SOright_arrow]
                      [:i :!SOup_arrow]]}
             ;
             ]
 ;
 }
kiinoda commented 3 years ago

@chrismo i wonder if this does what you actually want? it's a snippet from my config.

        {
            :des "Extend Layer - CapsLock (quick release for ESC)"
            :rules [
                [:##caps_lock ["extend" 1] [:!symbols :!mouse :!shifted :!system] {:afterup ["extend" 0] :alone :escape}]
                :extend
                    ; functions
                    [:##1 :f1][:##2 :f2][:##3 :f3][:##4 :f4][:##5 :f5][:##6 :f6]
                    [:##7 :f7][:##8 :f8][:##9 :f9][:##0 :f10][:##hyphen :f11][:##equal_sign :f12]
                    ; modifiers
                    [:##a :left_control][:##s :left_shift][:##d :left_option][:##f :left_command]
                    ; arrows
                    [:##j :left_arrow]
                    [:##k :down_arrow]
                    [:##i :up_arrow]
                    [:##l :right_arrow]
                    ; shortcuts
                    [:##u :!Cleft_arrow :!terminals]
                    [:##o :!Cright_arrow :!terminals]
                    [:##z :!Cz][:##x :!Cx][:##c :!Cc][:##v :!Cv]
            ]
        }
chrismo commented 3 years ago

Wow! I totally didn't understand what ## actually did. I thought I knew, but ... that's perfect :) I have a long-hand version of this tracking my own variables to send things like :!SCleft_arrow that's so much simpler now. I'd be facepalming if I wasn't so happy. Thx again!

Vermoot commented 3 years ago

I'm not sure I understand everything I see here, but it might be in the right area for what I want to do:

Is there any way I can have home row mods in karabiner using the simultaneous feature? It's my understanding that just remapping a key with if_alone won't work because if I type too fast I'll get many false positives (because karabiner doesn't have something like IGNORE_MOD_TAP_INTERRUPT in QMK), but that something like that is achievable with simultaneous.

Another headscratcher is that I'd want to have home row mods (at least shift on A and ;), while keeping some of my combos, for example the one I have on AS.