Which bit of VIM? The bit I'm thinking of is eg 4dd to delete 4 lines and so on -- but that doesn't sound like your description.
If these are to be done in "text entry" situations, take a look at typed string triggers. If they're to be available in all contexts, try using your "leader" to activate the Spotlight search field and using that as the target for your typed string -- yes, KM will detect and act on characters typed there.
⌃⌥M will open Spotlight and activate the "HK Demo", after which typing a number then b will "beep" that number of times, while a number and f will flash a dialog.
Outside of typed string triggers, multi-key triggers are -- tricky. You'll need to use hot key triggers to "swallow" the keystrokes so they aren't typed into the frontmost app, but it should be possible by chaining Group activation and macro enablement -- but it could get complicated very quickly!
An easier way would be to use careful naming and the Conflict Palette -- that would work for your last two examples (eg "isp - Insert into Proton" and "pg - CHatGPT"), though harder work for your first.
Don't forget that there are Activate/Deactivate Macro Group actions, so you will be able to chain as you wish.
But if you can get away with them, typed string triggers will be much easier!
"...one action", not "...one Action" -- ie a key press, click on a palette icon, etc.
Thinking further outside the box -- I'm assuming this works in a similar fashion to other vi modes, where you keystroke into "macro mode" and following keystrokes are captured until either a macro code is matched or you exit the mode.
You could do similar in KM, with a "Main" macro that activated on a key chord and had every keystroke as a hot key trigger. Each trigger value would be appended to a global variable and that variable checked for a matching "macro code", "Main" remaining active until either a code was matched or ESC was pressed.
Something like this, where ⌃⌥M activates "Main" and following that with one or more digits then a B runs "Beep n times", while one or more digits and an F runs Flash...":
Using "Switch/Case" is just for proof of concept -- you might want to keep your macro codes and UUIDs in a tab-delimited list, which would not only make for a smaller macro but would also make it easy to check if you'd entered a series of keystrokes that will never match if you continue.
I've had similar idea but my leader key is single tap of shift ⇧
That cannot be done on group. the logic is diff.
the other problem is that I have too many hotkeys to list them like this. I have so many that I don't have enough keys to put them on. Therefore: sequence keys.
But! your script gave me an idea. I could do it completely diff.
I'll post when I catch time to get in to it.
Sequence keys are very different from KM's hotkey philosophy. But KM is so powerful it is possible to use KM to implement sequence keys. At least I've done it. But it's very messy and very complicated, so I recommend that you don't try.
There's another problem. KM doesn't have any trigger for a modifier key tapped by itself. But KM can do polling to detect when you press the Shift key. Again, messy.
If you want to see a macro I recently uploaded that detects sequences and takes action based on a sequence, read this post. If you really want to tackle sequence key triggers, it may help to study the macro that I uploaded there.
The macro that I uploaded on that page has been running (unintentionally) on my Mac for the last week, and while my Mac has still been usable with that macro running, my keyboard has been acting a little strangely during this time. I just realize an hour ago that it was still running so I turned it off.
If you read my macro, and fully understand it, and like it, I can help you make it better to support your requirements.
When the "Main" macro is active it intercept the typed key, appends it to a variable, then checks if that variable is a complete key sequence -- if so, it triggers the appropriate macro.
But you have to add all the individual keys -- A-Z, 0-9, punctuation, etc -- as hot key triggers in "Main" because (AFAIK) that's the only way that the Engine can "swallow" them, stopping them from being sent to the frontmost application.
It also sounds like you've too many macros to list in any reasonable "Swich/Case" action. That's where you'd resort to text matching against a list instead. A tab-delimited list in the format
sequence\tmacroUUID
...would be easiest, then each time a character was added to %Variable%Global_macroString% you'd do something like (untested):
You could also test to see if you are still building a valid sequence with (again, untested):
It's the ease of that sanity check that makes me think a text list is going to be better a Dictionary containing {keySequence,macroUUID} elements.
I does. You have to just think a bit out of the box typing trigger > shift for example but not on the group. you have to trigger group by a macro.
This is my puzzlement about why would groups have diff triggers than macros? (@peternlewis if you don't mind telling.)
@Airy thanks for sharing. I've read it but this is quite complicated to maintain. I have better solution but I need to find time to do it.
yeah, I've solved it with check if macro can be executed - else cancel + 10sec timeout + disable group after single triggering of a macro* (if I understood why the macro was hanging)
Kind offer. Thanks. I'll post here after I try my thing.
You said twice there that groups have triggers. I don't think that's correct, as I cannot see any triggers on groups. Can you rephrase that sentence or upload a macro to illustrate what you mean?
I also don't know what you mean by "typing trigger > shift." Can you upload a macro so I can see what you are referring to?
The group is set to be activated only by Status Menu. That way it is not triggered by anything.
Then I have a macro that is set to activate that group for one action if I tap just [shift ⇧]
It's elegant.
My problem is that I have strings of 2,3 sometimes 4 keys. (My hands type by themselves. Muscle memory.) For that I would need several levels of groups and that is a bit unwieldy to maintain.
Therefor, a diff solution is needed.
It is much clearer now. I think it's also elegant. I had no idea "shift" could be used in the "type string" box. Sorry I missed that earlier.
One problem with your method is that it may only work when there is a text cursor in an active text edit window. That's because if you are not in a text edit window, the "Simulate N deletes" flag in the action could "delete" something else. For example, if you are using the KM Editor, and you are not in an edit field, the KM editor's simulated delete keys would delete several entire actions. This already happened to me while I was testing your action. So it feels dangerous to me. I also observed some sort of timing issue. If you are typing too fast this method of triggering seems to miss some triggers (and you did say you type very fast.)
You can use the USB Device Key trigger to detect a modifier being tapped as well as noted above using the Typed String trigger.
This makes no sense. Macros have triggers. Macro Groups do not have triggers.
There are some ways that macro groups can be activated depending on specific settings, but they are not triggers. Maybe in some other universe Macro Group configurations which have ways of activating them might be triggers, but they aren't in this universe.
This is irrelevant because a) the trigger is always active whether you are in a text field or not; b) modifier keys do not generate corresponding delete keys; and c) you can (and should) turn that facility off.
That's neat -- especially the "0 deletes" because it's only the Shift key.
And the problem is that KM can only really handle that, especially the fact that some of your sequences include variables, via typed string triggers. I mean, you could use dialogs -- but that's getting you further away from your desired behaviour of "just type some characters".
The big problem is that the vi/vim app is a controlled environment. Key strokes are only sent to the "document" when you are in the correct modes, making it very easy to have them be macro trigger sequences when not in those modes.
You can't easily generalise that to working across the whole OS and all apps because what happens when you press a key is context-dependent. And any sequence of "proper" characters will need to be deleted, for those times when a text field is active -- but when you aren't in a text field those deletions can lead to the problems @Airy described above. Or they might be shortcuts when typed outside a text field.
So you need to spoof vi/vim's behaviour and make sure the keystrokes don't reach the frontmost app. I showed you two ways of doing that:
Force a context where you can safely type and delete -- you could use Stickies, a TextEdit document, or similar, but I used a Spotlight search window as it's IMNO the least intrusive
Force a context that captures every keystroke, preventing them from reaching the frontmost app, and including a way to stop that capture -- that's the "activate a macro hot key-triggered by any keystroke, evaluating the sequence after each one" method
Something else?
For the first you are using typed string triggers directly. For the second you're effectively doing your own typed string detection on a capture buffer. For the third -- whatever you come up with!
you get a list of macros and just type what you want to execute. it's more user friendly.
.. but not exactly sequence keys..
I've solved it but it's not neat. Meaning keystrokes are still registered/interact with focused window. it is annoying but here it is:
create a group that is Activated with - nothing. But it has to be enabled because there is lag between action enable group and how fast you can start triggering macros in it.
create a macro (outside the group "SequenceMacros") and set that is activated by typing trigger (Shift ⇧ in my case) which activates group "SequenceMacros"
then create as many macros as you want that are activated by typing. Caveat: keys are still gonna interact with active window. Have to think a bit more on it. I didn't want to do it by scripting but I think it might be necessary in this case.
AND there has to be Deactivate Macro Group at the end of each macro. Didn't figure out how to embed this into trigger macro or macro group.