Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to create launcher mode in Karabiner Elements? #926

Closed
nikitavoloboev opened this Issue Aug 18, 2017 · 23 comments

Comments

Projects
None yet
8 participants
@nikitavoloboev
Copy link

nikitavoloboev commented Aug 18, 2017

In Karabiner you could do this :

<item>
    <name>make comma a modifier</name>
    <identifier>private.launcher_mode_open_apps_v72</identifier>

    <!-- condition: turn on launcher mode only when the trigger key is pressed without other keys. -->
    <pressingphysicalkeys_lessthan>2</pressingphysicalkeys_lessthan>
    <modifier_not>
      ModifierFlag::COMMAND_L,
      ModifierFlag::COMMAND_R,
      ModifierFlag::CONTROL_L,
      ModifierFlag::CONTROL_R,
      ModifierFlag::FN,
      ModifierFlag::OPTION_L,
      ModifierFlag::OPTION_R,
      ModifierFlag::SHIFT_L,
      ModifierFlag::SHIFT_R,
    </modifier_not>

    <autogen>
      __KeyOverlaidModifier__
      KeyCode::COMMA,

      <!--
          Use notsave.launcher_mode_v2 in order to be higher priority.
          Use ModifierFlag::MY_LAUNCHER_MODE for __DropAllKeys__.
      -->
      @begin
      KeyCode::VK_CONFIG_SYNC_KEYDOWNUP_notsave_private_launcher_mode_v72, ModifierFlag::MY_LAUNCHER_MODE,
      @end

      @begin
      KeyCode::COMMA,
      @end
    </autogen>
  </item>

  <item hidden="true">
    <identifier vk_config="true">notsave.private_launcher_mode_v72</identifier>

    <autogen>
      __BlockUntilKeyUp__ KeyCode::COMMA,
    </autogen>

        <autogen>
      __KeyToKey__
      KeyCode::A,
      KeyCode::1, ModifierFlag::SHIFT_L
		</autogen>

  </item>

And then you can add more autogen KeyToKey_ below it to map more things to the comma key.

Is this possible to do in Karabiner Elements?

Thank you.

@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Aug 27, 2017

Here is an example of my launcher, hope it helps.
Edit: Better example suggested below

{
    "description": "Launcher Mode",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "w"
            },
            "to": [
                {
                    "set_variable": {
                        "name": "launcher_mode",
                        "value": 1
                    }
                }
            ],
            "to_after_key_up": [
                {
                    "set_variable": {
                        "name": "launcher_mode",
                        "value": 0
                    }
                }
            ],
            "to_if_alone": [
                {
                    "key_code": "w"
                }
            ]
        },
        {
            "conditions": [
                {
                    "name": "launcher_mode",
                    "type": "variable_if",
                    "value": 1
                }
            ],
            "from": {
                "key_code": "e"
            },
            "to": [
                {
                    "shell_command": "open '/Applications/MindNode.app'"
                }
            ],
            "type": "basic"
        }
    ]
},

You can even run Keyboard Maestro macros this way. FYI it should also be possible to do that with Hammerspoon.

@nikitavoloboev

This comment has been minimized.

Copy link
Author

nikitavoloboev commented Aug 27, 2017

Wow. That's amazing.

So then if I press and hold w key, then press e, it will open MindNode right? How would I add more keys to the w key? How would that look?

One thing I've been thinking is that this JSON gets extremely large with all of its braces.

If this actually works, and once you can bind simultaneous keypresses with mouse mode (and scrolling), Karabiner Elements would be complete for me. 💛

@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Aug 27, 2017

Yeah. Just add an object to the array:

        {
            "conditions": [
                {
                    "name": "launcher_mode",
                    "type": "variable_if",
                    "value": 1
                }
            ],
            "from": {
                "key_code": "r"
            },
            "to": [
                {
                    "shell_command": "...'"
                }
            ],
            "type": "basic"
        }

It doesn't look too bad compared to the old xml file imho. I'm still trying it out but I think it's neat. I got inspired by all the materials you have shared 😉
You can also configure modifiers easily if you look at the doc, without having to create new conditions objects.

@nikitavoloboev

This comment has been minimized.

Copy link
Author

nikitavoloboev commented Aug 27, 2017

What is the value attribute here?

@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Aug 27, 2017

It's basically a boolean to set and check if the launcher is enabled or not.
A few examples here: https://github.com/pqrs-org/KE-complex_modifications/tree/master/src/json

@LoMiLiMiT

This comment has been minimized.

Copy link

LoMiLiMiT commented Sep 4, 2017

@cwagner22 I tried to use the launcher mode to map "Tab+q" to "Cmd+Tab" and "Tab+w" to "Cmd+Shift+Tab". However it doesn't work this way and i don't know why. The Application launcher appears no problem, but gets stuck after releasing the keys. Any ideas why?
I even tried to change the "Mu Mode" example, which brings me to the same issue.

    {
    "description": "Launcher Mode",
    "manipulators": [
        {
            "type": "basic",
            "from": {
                "key_code": "tab"
            },
            "to": [
                {
                    "set_variable": {
                        "name": "launcher_modev7",
                        "value": 1
                    }
                }
            ],
            "to_if_alone": [
                {
                    "key_code": "tab"
                }
            ],
            "to_after_key_up": [
                {
                    "set_variable": {
                        "name": "launcher_modev7",
                        "value": 0
                    }
                }
            ]
        },
        {
            "conditions": [
                {
                    "name": "launcher_modev7",
                    "type": "variable_if",
                    "value": 1
                }
            ],
            "from": {
                "key_code": "q"
            },
            "to": [
            {
              "key_code": "tab",
              "modifiers": [
                "left_command",
                "left_shift"
              ]
            }
          ],
            "type": "basic"
        },
	{
            "conditions": [
                {
                    "name": "launcher_modev7",
                    "type": "variable_if",
                    "value": 1
                }
            ],
            "from": {
                "key_code": "w"
            },
            "to": [
            {
              "key_code": "tab",
              "modifiers": [
                "left_command"
              ]
            }
          ],
            "type": "basic"
        }
    ]
},

@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Sep 5, 2017

Yeah I tried your example and have the same issue, no idea why...
Without the launcher mode it's working, like that: https://github.com/pqrs-org/KE-complex_modifications/blob/master/docs/json/application_window_tab_switch_with_right_cmd_hjklsemiquote.json (first example). But for tab+q I guess you need the launcher.

Pretty sure you can do that with hammerspoon, but it's more complicated. If you find a way let me know.

@Jimmy34742

This comment has been minimized.

Copy link

Jimmy34742 commented Nov 25, 2017

I'm trying to switch to apps via a single longpress. I don't know javascript very well, but I have the following code in the json file that mostly works:

{
  "description": "Launch MyApp return_or_enter is held.",
  "manipulators": [
    {
      "from": {
        "key_code": "return_or_enter",
        "modifiers": {
          "optional": [
            "any"
          ]
        }
      },
      "to": [
        {
    "shell_command": "open '/Applications/MyApp.app'"
        }
      ],
      "to_if_alone": [
          {
       "key_code": "return_or_enter"
        }
      ],
      "type": "basic"
    }
  ]
},

Longpressing the return key switches to MyApp, and there is no occurrence of a return character, which is all correct behavior. But when I tap the return key I get both the return and it switches to MyApp. When just doing a key tap, shouldn't the code only execute the to_if_alone branch and not the shell_command in the to-branch? I'm guessing I'm missing something simple, but I'm a newbie coding javascript and could use some help.

@massens

This comment has been minimized.

Copy link

massens commented Jan 23, 2018

@cwagner22 Thanks very much for the tip, very useful! I had problems while writing and and the apps where launching by error. I solved by changing to to to_if_held_down and setting "basic.to_if_held_down_threshold_milliseconds": 100.

Here you have the code:

        "complex_modifications": {
            "parameters": {
                "basic.to_delayed_action_delay_milliseconds": 500,
                "basic.to_if_alone_timeout_milliseconds": 800,
                "basic.to_if_held_down_threshold_milliseconds": 100
            },
            "rules": [
                {
                    "description": "Launcher Mode",
                    "manipulators": [
                        {
                            "from": {
                                "key_code": "o"
                            },
                            "to_if_held_down": [
                                {
                                    "set_variable": {
                                        "name": "launcher_mode",
                                        "value": 1
                                    }
                                }
                            ],
                            "to_after_key_up": [
                                {
                                    "set_variable": {
                                        "name": "launcher_mode",
                                        "value": 0
                                    }
                                }
                            ],
                            "to_if_alone": [
                                {
                                    "key_code": "o"
                                }
                            ],
                            "type": "basic"
                        },
                        {
                            "conditions": [
                                {
                                    "name": "launcher_mode",
                                    "type": "variable_if",
                                    "value": 1
                                }
                            ],
                            "from": {
                                "key_code": "r"
                            },
                            "to": [
                                {
                                    "shell_command": "open '/Applications/Crispgtg.app'"
                                }
                            ],
                            "type": "basic"
                        }
                    ]
                }
            ]
        },
@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Jan 23, 2018

@massens I think that's indeed a better solution, thanks.
So this avoids triggering the launcher mode if the launcher key is held for less than 100ms, which happens when you type fast and press the second key before the launcher key is released.

However in your example if you'd press the "r" key during this time period (<100ms) that means you would expect to have the letters "o" and then "r" printed but unfortunately the "o" key will be ignored so only "r" will be printed.
It's the same issue in my example, if you press the second key before releasing the launcher key then the launcher key won't be printed. That's the way to_if_alone works.

But it's still an improvement. Although the caveat is the launcher won't be fired if you press the second key less than 100 ms after starting holding down the launcher key. Complicated stuff...

@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Jan 23, 2018

@Jimmy34742 I think the events in to are always fired. Maybe launch the command in to_if_held_down with repeat set to false? Also set to_if_held_down_threshold_milliseconds to the value you want. Look at the doc.
If that doesn't work there is also to_delayed_action but the only example I see if for double tap, not long press.

@nikitavoloboev

This comment has been minimized.

Copy link
Author

nikitavoloboev commented Jan 23, 2018

Btw guys, I wanted to ask. Do you know if you can define variables in Karabiner?

For example I want to define a variable that calls an Applescript code similar to how you could do this in old Karabiner:

<vkopenurldef>
<name>KeyCode::VK_OPEN_URL_KM_RERUN_CMD_ITERM</name>
<url type="shell">
osascript -e '
tell application "Keyboard Maestro Engine"
do script "Capitalise word"
end tell
'
</url>
</vkopenurldef>
@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Jan 23, 2018

@nikitavoloboev Not that I know of, sorry. Tekezo seems to generate the json config file in erb templates but it's probably much easier to add the commands inline...

@Jimmy34742

This comment has been minimized.

Copy link

Jimmy34742 commented Jan 24, 2018

@cwagner22 Thanks, I forgot about this old question. Longpress has since become achievable using a to_if_alone followed by a to_if_held_down.

@xvrdm

This comment has been minimized.

Copy link

xvrdm commented Jan 24, 2018

@cwagner22 Do you know how this could be properly written inline? I tried this without success:

"to": [
  {
    "shell command": "osascript -e 'tell application \"Keyboard Maestro Engine\"\n do script \"open: Safari\" \n end tell'"
  }
],

Thanks a lot to all for brainstorming on this issue!

@cwagner22

This comment has been minimized.

Copy link

cwagner22 commented Jan 24, 2018

@xvrdm This is working for me:

   "to": [
        {
            "shell_command": "osascript -e 'tell application \"Keyboard Maestro Engine\" to do script \"91ADF247-2210-4743-8628-14D3DE0B94E3\"'"
        }
    ],

Did you forget the underscore in shell_command?

@xvrdm

This comment has been minimized.

Copy link

xvrdm commented Jan 24, 2018

I totally did! (+ I did not know about this applescript inline syntax) thanks!!!

@nikitavoloboev

This comment has been minimized.

Copy link
Author

nikitavoloboev commented Jan 24, 2018

Hey @xvrdm

Are you by chance using my KM macros I shared in my macOS? Just curious. 🙂

@xvrdm

This comment has been minimized.

Copy link

xvrdm commented Jan 24, 2018

Hey @nikitavoloboev I haven't seen the actual macros but I am definitely trying to reproduce what I think you are doing! So far, on the KM side, it is as simple as an "Activate application".

edit: I looked more into your write-up: it's genius!

@tekezo

This comment has been minimized.

Copy link
Owner

tekezo commented Mar 8, 2018

You can use simultaneous_options.key_down_order and simultaneous_options.key_up_order to achieve old __BlockUntilKeyUp__ behavior since Karabiner-Elements latest beta version.

Check for beta updates

json

The example json (Personal rules (@tekezo) Launcher Mode v4):
https://github.com/pqrs-org/KE-complex_modifications/blob/master/docs/json/personal_tekezo_launcher_mode_v4.json

json generator

The json generator:
https://github.com/pqrs-org/KE-complex_modifications/blob/master/src/json/personal_tekezo_launcher_mode_v4.json.rb

You can change the trigger key to comma by editing this line:
https://github.com/pqrs-org/KE-complex_modifications/blob/master/src/json/personal_tekezo_launcher_mode_v4.json.rb#L11

These are launcher definitions:
https://github.com/pqrs-org/KE-complex_modifications/blob/master/src/json/personal_tekezo_launcher_mode_v4.json.rb#L24-L39

Document of simultaneous_options

https://pqrs.org/osx/karabiner/json.html#simultaneous-options

@ricardomoral

This comment has been minimized.

Copy link

ricardomoral commented Apr 28, 2018

Guys I’m trying to configure the launcher so I can invoke apps pressing + + and for this I’m trying to setup two mandatory modifiers (CMD+SHIFT). But it’s not working. Do you know if it’s possible to request two mandatory modifiers in the “modifiers” clause?

@Jimmy34742

This comment has been minimized.

Copy link

Jimmy34742 commented Apr 28, 2018

Perhaps post your code?

@stale

This comment has been minimized.

Copy link

stale bot commented Jun 27, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 27, 2018

@stale stale bot closed this Jul 4, 2018

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.