I want to switch to another open app by typing a trigger combo and then as few letters as necessary to disambiguate the target app by the initial letter(s) of its name as the names would sort alphabetically. How might I set this up?
I see a couple of problems with this. The biggest problem is that it isn't clear WHICH window for an app that you want to bring up. Apps can have multiple windows. How is the macro supposed to know which one to bring up? The macro might require separate code for each app to solve this, but you haven't specified which apps you want this to work with. And if your answer is "I want all the windows for each app to be brought up," then you might end up with the windows in the wrong Z-order.
Another problem with your idea is that once the minimum number of characters has been entered, the remaining letters that you type would be sent to the apps as input. So this seems like a risky design for a macro.
Another problem, (kinda the same as the first problem above) which was just addressed in another thread this week, was that when you bring up an app, the app may currently have all its windows hidden, which means nothing but the app's menu bar will be visible until the user goes to the Window Menu to activate a window. Is that what you want?
Can we say that by "switch to" I mean have the effect of a mouse click on the target app's dock icon? Does that make the task easier?
It isn't the fewest possible keystrokes because of the way Spotlight filtering works, but how does this grab you?
Activate Open App from List.kmmacros (2.6 KB)
You could get it down to fewer keystrokes by
- Creating an "Activate" macro for each of your apps, all with the same keystroke
- Creating an activate/deactivate macro that enabled or disabled an application's "Activate" macro whenever that app was launched or quit
...which would result in a Conflict Palette that only listed the activation macros of your running apps. But that's a lot of work and, potentially, constantly changing typed strings as the list of running apps changed and, with that, changed "the next different character" in the Conflict Palette.
The issue with Prompt With LIst...
is that all that typing a letter will do is eliminate the list entries which do not contain the letter in any position in the entry's name, leaving all those which do contain the letter in any position. E.g, typing "i" with intent to select iTerm2
will just eliminate the one or two entries which contain no "i".
That helps a lot, but only if your taskbar is visible all the time. Is it? And the simple solution that I'm thinking of will require a little setup each time that you change the order/position of the apps on your dock. Is that ok?
Yes, the dock (=taskbar?) is always visible, and I'd accept a little overhead to changes in its composition.
Ok, I have an idea. I'm not sure if my idea has side effects or not. Let me try it out now.
So far, so good. It may take another hour, I think.
Take your time -- at your hourly rate, I can afford it!
Meanwhile I note that Prompt With LIst...
processes each character as it is typed, but what it does with the character is not what I need. I wonder if there is some existing facility to provide code that I'd write with each character as it's typed. There probably is in JXA. And I'm guessing there's a way to pass a KM variable value, such as the foreground apps list, to JXA code.
Yes -- and then typing a T
will limit it to all the entries that have IT
in them. I said as much in my post.
The problem is that you're taking what's normally done with a Conflict Palette-derived list and trying to make to work with only currently open apps. That means more work, and one way to do it was described in the second part of my post. Have you tried to do that yet?
Why does only open apps matter anyway? Most times, surely, you'll want to switch to an app because you want to use it -- regardless of whether it is currently open or not.
My solution appears to be working. Let me just test it a little more and then I will upload it.
I use some non-conventional techniques to make it work. And perhaps I misunderstood your problem, so maybe I'll need to modify my macro to make it work better.
Even if you don't like my solution, there are some sneaky techniques in it that some people may find illuminating.
And the fact that it's actually working is making me laugh. Personally, I wouldn't use it, but if you like it, that's all that matters.
Okay, here's my attempt at a solution. There's a 20% chance I misunderstood your requirements, but give this a shot. My Dock is on the left side of my screen, so to test this macro you will have to do the same thing (that can be fixed later.) Read the opening Comment action to learn what you have to do to set this up. Some of the setup can be automated but I don't want to automate anything if this isn't what you want.
I won't be upset if you are unhappy with this solution. I'm doing it because I enjoy this type of challenge. Don't worry about offending me if you don't like it. Even if you don't like it, you may find some of my techniques to be interesting.
The first thing you will notice is that it is triggered by every hotkey from A-Z, plus the Backquote. The macro is very careful to pass the appropriate key back to whatever app is running if it's not part of any "hotkey sequence" that you have defined in the variable called LocalData. This is one of my tricks to get your requirement to work.
Select App by Typing "Backquote AppNameAbbreviation" Macro (v11.0.3)
Select App by Typing "Backquote AppNameAbbreviation".kmmacros (26 KB)
I have edited my OP to more precisely specify the disambiguation process I want.
Only open apps matter because, in my case, the list is usually short -- six as I type this, and fairly constant. I can thus mentally automate what to type to switch to the target.
Thanks! I'm rejecting this solution on inspection of the image in your reply because it has too much overhead and too many ... sharp edges. However, I have downloaded the macro for further reading as, you indicated, I think I may find some techniques to be interesting.
At this writing then, I'm planning to look into a JAX solution. To repeat...
...in case anyone has any suggestions with respect to those two initial concerns. (I have little JS experience but lots of coding experience in many languages.)
It still doesn't matter if they are actually open or not -- if they are open they come to the front, if they aren't they'll launch and come to the front. The only reason it would matter is if you wanted to be unable to activate an app that wasn't open. Is that the case?
With only a few apps it's easy to manage your own list of "codes".
If you go the Conflict Palette route you can just your "opener" macros accordingly: m - Mail
, s - Safari
, and so on. Keep those first letters unique and you only need one keypress.
If you didn't want to be able to activate unopened apps then each "opener" could take the form of
if thisApp is running
activate thisApp
else
do nothing
end
...at the expense of having "unwanted" items on the palette for the not-running apps.
Of course, you don't actually need a list at all. Just give each macro its own, unique, hot key (again, easy with so few apps) -- ⌃M
for Mail, ⌃N
for Notes, ⌃S
for Safari, etc -- and every app is only a key chord away.
If you still want to go the "prompt from a list of only open apps" route you'd again have to manage your own codes, but could make use of KM's "friendly list" formatting and generate items in the format properName__code
that you could pick from. Something like this:
Activate Open App from List Switch Version.kmmacros (6.4 KB)
As you can see, there's a bunch of ways of getting close to what you want (if not quite all the way there) and it's starting to look like there's an inverse correlation between how much you have to type at runtime versus how much work you have to do in making/maintaining the system
The main problem with a JXA solution is the lack of a "filtering" dialog similar to the "Prompt from List" -- your keystroke(s) would only be submitted after you hit the "OK" button -- but, as above, for a few apps a lack of filtering isn't such a problem. You could do a filtering list with a Custom HTML prompt and JS change events that reduce an array of app choices -- but that seems like even more work!
The advantage of a "normal" dialog is that, unlike "Prompt with List", the select-as-you type is pinned to the start of each string. Whether that's useful will depend on your apps -- not so good if you use ones from Adobe or Microsoft!
The benefit of using individual macros and a Conflict Palette or your own "code list" is that you can use the names you want, not the ones the developer gives you
I guess this requires a robust solution:
For unopen apps, Launchpad is easy enough.
A single modifier key such as Ctrl wouldn't work, except possibly Option. E.g., I use ^N and ^S frequently in Vim.
Occasionally the list would expand by one or two for, say, a few minutes or a couple of weeks.
I don't mind initial work; as @Airy said above, "I enjoy this type of challenge." But I will further consider the Activate Open App from List Switch Version
approach. (In "when macro group is active," does "active" mean "enabled"?)
My first thought was that I use RCmd a lot with my split 31-key keyboard. But it's self-programmed, and there's no reason not to change to use only LCmd. So I'll now read the developer web page more closely.
I set up Activate Open App from List Switch Version
and think it may work for me, so I'm going to try it for a few days. For now, at least, I'm marking the reply providing it as the solution. Thank you for your perseverance!
I accept that polite critique, thanks.