Smart Group Syntax for Keyboard Shortcuts: how to include Macro Group hot keys

I am extremely happy and very grateful for your macro @CRLF .

I was wondering if it is possible and simple modify the script to sort by keyboard shortcut the results displayed in the HTML window.

It would save me havint to print the HTML window and sorting the Keyboard Shortcuts by hand.
Only if you have time and the effort is minimal.

thank you very much and sorry for the follow-up request

1 Like

Hi Ronald,

No problem, no apologies needed!

I'm glad the macros are working for you. Sorting on modifier and key should be a quick edit.

The AppleScript outputs crude preformatted html.

If I had any html skills whatsoever I might try rejiggering some sortable columns, but will have to go with hard-coding sorting into the AppleScript. Sorting will be on: 1. modifier 2. key 3. name.

I hope you don't mind that instead of uploading a revised macro, but I just have you copy and paste the AppleScript sort lines.

There are two versions of the macro and two edits, depending on the mode you're using.

Edit 1:

Find this line that gets the formatted html from the variables:

set hrefLines to {}

On the line above it, paste these sort lines:

set modifiersDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"Modifiers" ascending:true selector:"compare:"
set keyCodeDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"KeyCode" ascending:true selector:"compare:"
set nameDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"Name" ascending:true selector:"localizedStandardCompare:"
set groupDicts to groupDicts's sortedArrayUsingDescriptors:{modifiersDesc, keyCodeDesc, nameDesc}

The "set hrefLines to {}" line occurs in two handlers on the most recent macro upload, so you'll need to do this twice and you're done.

(If you would like to experiment with formatting the "all groups" html yourself, these are the variables to play with: keyCodeCharacters, modifiersSymbols, groupName, groupUID, enabled)

Edit 2:

To edit the "active groups" mode, find and replace this repeat block:

	repeat with aGroup in groupHKDicts
			set {hotKey, groupName, groupUID} to (aGroup's objectsForKeys:{"key", "name", "uid"} notFoundMarker:true) as list
			set href to "<a href= \"keyboardmaestro://m=" & groupUID & "\">" & groupName & "</a> " & hotKey
			set end of hrefLines to href
		end repeat

with this:

	set keyDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"key" ascending:false selector:"compare:"
	set nameDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"name" ascending:true selector:"compare:"
	set groupHKDicts to groupHKDicts's sortedArrayUsingDescriptors:{keyDesc, nameDesc}
	set tempDicts to groupHKDicts's dictionaryWithValuesForKeys:{"key", "name", "uid"}
	set {thekeys, theNames, uids} to tempDicts's objectsForKeys:{"key", "name", "uid"} notFoundMarker:"not found"
	repeat with i from 1 to count of theNames
		set {hotKey, groupName, groupUID} to {item i of thekeys, item i of theNames, item i of uids}
		set href to "<a href= \"keyboardmaestro://m=" & groupUID & "\">" & groupName & "</a> " & hotKey
		set end of hrefLines to href
	end repeat

Done.

(If you would like to experiment with formatting the active groups html yourself, these are the variables to play with:thekeys, theNames, uids)

I've only run this once or twice, so do let me know if this doesn't work or isn't what you had in mind.

1 Like

The initial macro works perfectly.
The new uploaded version (without the changes you mention in this last post) shows only a few macro groups, so I would rather just stick to the old version and sort manually. You have already spent too much time on this project. I am once again extremely grateful.

You need not. Edit 1 will work for the old macro too.

Just one find and paste.

If you can't get it going, I will upload the revised macro.

The edit is minor, really. I'd hate to leave you hanging on that alone.

Give this a try. I've also changed the info linesso that the hot keys come first.

If it isn't what you had in mind, don't hesitate to ask.

Being as specific as possible is helpful.

It doesn't sound like it's a big or unreasonable ask.

Display Macro Group Hot Keys - Sorted by Hot Key.kmmacros (7.4 KB)

thank you again for your time and expertise.

1- below is the script which I attempted to modify the original macro as per your instructions, and yields an error message. I hope that I did not bungle the script editing.

KM Engine log
Execute an AppleScript failed with script error: text-script:2316:2328: execution error: The variable groupHKDicts is not defined. (-2753).

2- the macro downloaded from your latest post gives erroneous results. In the (see ScreenShot below) item (1) (F7) is from your initial macro and is correct and item (2) from your latest post is incorrect (F3)

3- minor issue: the HTML window is very small. No problem. I just stretch it manually.. It was much better with your very very initial macro which I can no longer find. I tried to "modify engine window" both before and after the HTML action to no avail. I can't find where you define the window size.

thank you again. If you have any urge to throw your Mac out the window, please stop working on this project !

0use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use framework "Foundation"
property author : "@CRLF"
--┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
--┃ Outputs information on Macro Groups with hot keys
--┃ in preformatted html. 
--┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
tell application id "com.stairways.keyboardmaestro.editor"
	set groupXMLs to group xml of macro groups whose activation xml contains "KeyCode" and activation xml does not contain "32767"
	set groupDicts to (current application's NSMutableArray's arrayWithArray:groupXMLs)'s valueForKeyPath:"propertyList"
end tell
(*
--To browse all possible info keys, uncomment:
if groupDicts's |count|() > 0 then
	return ((((groupDicts's objectAtIndex:0)'s allKeys())'s sortedArrayUsingSelector:"compare:")'s componentsJoinedByString:linefeed)
end if
*)
set keyCodeDict to keyCodeLookUps()
repeat with aGroup in groupDicts
	set temporaryDict to (aGroup's dictionaryWithValuesForKeys:{"Name", "KeyCode", "Modifiers", "UID"})'s mutableCopy()
	set {aKeyCode, theModifiers} to (temporaryDict's objectsForKeys:{"KeyCode", "Modifiers"} notFoundMarker:"not found")
	set keyCodeCharacters to (keyCodeDict's objectForKey:(aKeyCode)) as text
	set modifiersSymbols to (modifiersToSymbols((theModifiers) as text))
	set modifiersSymbols to reorderModifiersKMStyle(modifiersSymbols)
	(aGroup's addEntriesFromDictionary:(current application's NSDictionary's dictionaryWithObjects:{keyCodeCharacters, modifiersSymbols} forKeys:{"KeyCodeCharacters", "ModifiersSymbols"}))
end repeat
set modifiersDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"Modifiers" ascending:true selector:"compare:"
set keyCodeDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"KeyCode" ascending:true selector:"compare:"
set nameDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"Name" ascending:true selector:"localizedStandardCompare:"
set groupDicts to groupDicts's sortedArrayUsingDescriptors:{modifiersDesc, keyCodeDesc, nameDesc}
set hrefLines to {}


set keyDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"key" ascending:false selector:"compare:"
	set nameDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"name" ascending:true selector:"compare:"
	set groupHKDicts to groupHKDicts's sortedArrayUsingDescriptors:{keyDesc, nameDesc}
	set tempDicts to groupHKDicts's dictionaryWithValuesForKeys:{"key", "name", "uid"}
	set {thekeys, theNames, uids} to tempDicts's objectsForKeys:{"key", "name", "uid"} notFoundMarker:"not found"
	repeat with i from 1 to count of theNames
		set {hotKey, groupName, groupUID} to {item i of thekeys, item i of theNames, item i of uids}
		set href to "<a href= \"keyboardmaestro://m=" & groupUID & "\">" & groupName & "</a> " & hotKey
		set end of hrefLines to href
	end repeat
set beginning of hrefLines to "<pre>"
set end of hrefLines to "</pre>"
set {TID, text item delimiters} to {text item delimiters, linefeed}
return (hrefLines as text)
--===============HANDLERS=================
on keyCodeLookUps()
	set allObjects to {"A", "S", "D", "F", "H", "G", "Z", "X", "C", "V", "B", "Q", "W", "E", "R", "Y", "T", "1", "2", "3", "4", "6", "5", "=", "9", "7", "-", "8", "0", "]", "O", "U", "[", "I", "P", "Return", "L", "J", "'", "K", ";", "\\", ",", "/", "N", "M", ".", "Tab", "Space", "`", "Delete", "Enter", "Escape", "RightCommand", "Command", "Shift", "CapsLock", "Option", "Control", "RightShift", "RightOption", "RightControl", "Function", "F17", "Key Pad .", "Key Pad *", "Key Pad +", "Clear", "Key Pad /", "Enter", "Key Pad -", "F18", "F19", "Key Pad =", "Key Pad 0", "Key Pad 1", "Key Pad 2", "Key Pad 3", "Key Pad 4", "Key Pad 5", "Key Pad 6", "Key Pad 7", "F20", "Key Pad 8", "Key Pad 9", "F5", "F6", "F7", "F3", "F8", "F9", "F11", "F13", "F16", "F14", "F10", "F12", "F15", "Help", "Home", "PageUp", "Forward Delete", "F4", "End", "F2", "Page Down", "F1", "LeftArrow", "RightArrow", "DownArrow", "UpArrow"}
	set allKeys to {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 67, 69, 71, 75, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 96, 97, 98, 99, 100, 101, 103, 105, 106, 107, 109, 111, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126}
	return current application's NSDictionary's dictionaryWithObjects:allObjects forKeys:allKeys
end keyCodeLookUps

on modifiersToSymbols(bitmask)
	set modifierMap to {¬
		{"⌘", 256}, ¬
		{"⇧", 512}, ¬
		{"⌥", 2048}, ¬
		{"⌃", 4096}, ¬
		{"⇪", 1024}}
	set detected to {}
	repeat with i from 1 to count of modifierMap
		set {symbol, value} to item i of modifierMap
		if (bitmask div value) mod 2 is 1 then
			set end of detected to symbol
		end if
	end repeat
	return detected
end modifiersToSymbols

on reorderModifiersKMStyle(symbolString)
	-- KM-style display order
	set kmOrder to {"⌃", "⌥", "⇧", "⌘", "⇪", "Fn"}
	set reordered to {}
	repeat with s in kmOrder
		if symbolString contains (s as string) then set end of reordered to contents of s
	end repeat
	return reordered as text
end reorderModifiersKMStyle

The instructions are for the most recent version of the macro -- the first version that you're trying to edit doesn't set an initial groupHKDicts variable so the new line

	set groupHKDicts to groupHKDicts's sortedArrayUsingDescriptors:{keyDesc, nameDesc}

...will error.

1 Like

this is why I used the original ver 1 with one replacement only. I must be confused. thank you for your comment.

Thank you for the detailed feedback.

I'm sorry for all the confusion.

Mac defenestration.

Not something I've ever tried...:rofl:

It should still be at the end of my second post:

Link

Smart Group Syntax for Keyboard Shortcuts: how to include Macro Group hot keys - #6 by CRLF

Excellent.

I may be trying to do too many things at once, so let's start from there, since that means these are not problems:

Even assuming the latter, nonetheless please indulge me and verify that the key reporting using the initial macro is correct. I'm a bit spooked at this point and would like to fix any mapping problem if they never worked in the first place (My own list of macro groups using hotkeys is quite short).

If mapping is not an issue, the current issue will be sorting. (Window sizing will go to the back burner.)

I've reuploaded the first posted macro.

The only change is a new sort line segment.

To inspect it, look for this:

--BEGIN SORT
set modifiersDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"Modifiers" ascending:true selector:"compare:"
set keyCodeDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"KeyCode" ascending:true selector:"compare:"
set nameDesc to current application's NSSortDescriptor's sortDescriptorWithKey:"Name" ascending:true selector:"localizedStandardCompare:"
set groupDicts to groupDicts's sortedArrayUsingDescriptors:{modifiersDesc, keyCodeDesc, nameDesc}
--END SORT

It will sort in this order: 1. modifer 2. key 3. name

It uses the original numeric values of modifier and key for sorting.

If sorting works, we we'll move on to window sizing. (Though I have a few reporting refinements to suggest as well.)

Display Macro Group Hot Keys Usage - hot key sort.kmmacros (7.4 KB)

1 Like

Works perfectly !! a gem. I am speechless. Superb ! I am calling the British museum to open a display. thank you so much !

and thank you for interest in the discussion and your comments

Great! So glad!

Thank you for your feedback and sorry for the run around.

At the risk of making the better the enemy of the good...

To set the window size:

Insert a "Set Variable to Text" action named localHTML just after the Execute an AppleScript.

Paste this into it:

<html>
<head>
  <title>Macro Goups with hot keys</title>
</head>
<style>
body {width: 420px;}
</style>
<body data-kmwindow="SCREEN(Main,Left,20%),SCREEN(Main,Top,20%),420,560">
%Variable%localHTML%
</body> 
</html>

The opening body tag is from the example given on this page:
Custom_HTML_Prompt

As shown the previous image, you can also click the gear icon on the Custom HTML Prompt action and select Help

As always, Nige_S makes an excellent point:

With that in mind, here's a refinement to consider.

If you like, we could add abbreviated application availability info:

Option Abbreviation
Available in all applications
Available in these applications In (app list)
Available except in these applications Excluding (app list)
Available when these applications are running When running (app list)
Available when these applications are running but not active Running but not active (app list)

Finally--again at the risk messing thngs up--I could add a more user friendly keycodee mapping that makes it easier for users to as Nige_S says, "roll their own".

Refined or unrefined, I think it best to leave the poor British museum out of it.:sunglasses:

1 Like

I have been playing around with it and everything really seems perfect. No additions necessary. thanks very much for the window and the wiki info. You have a very pleasant and crystal clear and didactic and I will add all your explanations to my personal KBM "manual". Thanks very very much !

1 Like