I will restart Mavericks because I just checked the values returned, not the behavior with the used syntax.
KOENIG Yvan (VALLAURIS, France) samedi 20 juillet 2013 15:18:15
I will restart Mavericks because I just checked the values returned, not the behavior with the used syntax.
KOENIG Yvan (VALLAURIS, France) samedi 20 juillet 2013 15:18:15
Hello
Some things are really bad.
I tested with TextEdit so I was able to run the script with nothing selected : menu item inactive
or with something selected : menu item active
(1) the whose filter is no longer usable. We must use something like that :
tell application "System Events"
set theProcess to (first application process whose frontmost is true)
set theProcess to process "TextEdit"
tell theProcess
tell menu 1 of menu bar item 4 of menu bar 1
#set cutEnabled to (properties of (get first menu item whose value of attribute "AXMenuItemCmdChar" is "X"))
-- Invalid index
set theValues to value of attribute "AXMenuItemCmdChar" of every menu item
set {maybe, cutenabled} to {0, false}
repeat with i from 1 to count theValues
if item i of theValues is "X" then
set maybe to i
exit repeat
end if
end repeat
if maybe = 0 then
# no item whose shortcut letter is X in the menu
else
# test the value of attribute "AXMenuItemCmdModifiers"
tell menu item maybe
properties of every attribute
set cutenabled to value of attribute "AXMenuItemCmdModifiers" is in {1, true}
end tell
end if
end tell
end tell
end tell
In both cases the properties of the attributes of menu item Cut were the same :
{
{value:“AXMenuItem”, class:attribute, settable:false, name:“AXRole”},
{value:“commande de menu”, class:attribute, settable:false, name:“AXRoleDescription”},
{value:menu “Édition” of menu bar item “Édition” of menu bar 1 of application process “TextEdit” of application “System Events”, class:attribute, settable:false, name:“AXParent”},
{value:false, class:attribute, settable:false, name:“AXEnabled”},
{value:{0, 54}, class:attribute, settable:false, name:“AXPosition”},
{value:{298, 19}, class:attribute, settable:false, name:“AXSize”},
{value:“Couper”, class:attribute, settable:false, name:“AXTitle”},
{value:missing value, class:attribute, settable:false, name:“AXHelp”},
{value:false, class:attribute, settable:true, name:“AXSelected”},
{value:“X”, class:attribute, settable:false, name:“AXMenuItemCmdChar”},
{value:missing value, class:attribute, settable:false, name:“AXMenuItemCmdVirtualKey”},
{value:missing value, class:attribute, settable:false, name:“AXMenuItemCmdGlyph”},
{value:false, class:attribute, settable:false, name:“AXMenuItemCmdModifiers”},
{value:missing value, class:attribute, settable:false, name:“AXMenuItemMarkChar”},
{value:missing value, class:attribute, settable:false, name:“AXMenuItemPrimaryUIElement”}}
For sure filing a bug report is needed but as I wrote I am unable to do that since 2013/06/11
Worse, as I wrote here about Mavericks, maybe Apple will ban me from SEEDs :roll eyes:
Yvan KOENIG (VALLAURIS, France) samedi 20 juillet 2013 15:56:59
You can go to the dev forums. (In case someone’s wondering the dev forums are also down. I think it’s day 3 now.)
I try your workaround, though I believe whose
is still working. Try the following:
set cutEnabled to (enabled of first menu item whose value of attribute "AXMenuItemCmdModifiers" is false)
The bug could be that whose can’t use strings anymore?
Whose is down for the test upon the value of attribute “AXMenuItemCmdChar” only in Mavericks. It behaves flawlessly in Mountain Lion.
As I can’t file a report, I will not waste time switching between two systems.
I will continue to test new products only when Apple engineers will decide to wake up and restore my broken access.
whose seems to be usable for value of attribute “AXMenuItemCmdModifiers” but alas, it’s the value itself which is no longer meaningful. It’s set to false when the menu item is active and when it’s inactive.
KOENIG Yvan (VALLAURIS, France) samedi 20 juillet 2013 16:28:39
Gotcha. I have been unsuccessful getting this to work. The code always returns, no matter whether the Cut item is enabled or not. I can’t wrap my head around the code any longer at the moment. Will try again later. Thanks for all the help!
What with this one :
set theApp to "TextEdit"
activate application theApp
tell application "System Events"
#tell (first application process whose frontmost is true) -- Or a named, frontmost process.
tell process theApp
set CutEnabled to false
set maybe to first menu item of menu 1 of menu bar item 4 of menu bar 1 whose value of attribute "AXMenuItemCmdChar" is "X"
if value of attribute "AXMenuItemCmdModifiers" of maybe is in {0, false} then
set CutEnabled to enabled of maybe
end if
end tell
end tell
Don’t forget that if you run the script from the Script Editor, it’s the Editor which is at front.
In my late code, I failed to activate TextEdit before calling System Events.
Due to that the tested parameters were those of the Editor, not those of TextEdit.
KOENIG Yvan (VALLAURIS, France) samedi 20 juillet 2013 17:13:05
In my late code, I failed to activate TextEdit before calling System Events.
Due to that the tested parameters were those of the Editor, not those of TextEdit.
You are not the first, nor the last one, to do such a thing.
My late proposal fails under Mavericks.
Nigel Garvey sent a code which does the trick :
tell application "TextEdit" to activate
tell application "System Events"
tell (first application process whose frontmost is true)
set {AXMenuItemCmdCharVals, AXMenuItemCmdModifierVals, enabledVals} to {value of attribute "AXMenuItemCmdChar", value of attribute "AXMenuItemCmdModifiers", enabled} of every menu item of menu 1 of menu bar item 4 of menu bar 1
end tell
end tell
repeat with i from 1 to (count AXMenuItemCmdCharVals)
if ((item i of AXMenuItemCmdCharVals is "X") and (item i of AXMenuItemCmdModifierVals is in {0, false})) then
set cutenabled to item i of enabledVals
exit repeat
end if
end repeat
cutenabled
I just had to replace a test upon 0 to a test upon the list {0, false}.
Just for info, under pre Mavericks systems, I saw these values for the attribute “AXMenuItemCmdModifiers” :
0, 1, 2, 3, 8, 10, 24 and I’m sure that I missed some other ones.
Under Mavericks we get only true or false.
Yvan KOENIG (VALLAURIS, France) samedi 20 juillet 2013 21:47:37
Indeed, Yvan and Nigel, this latest version does the trick. Thanks for all your help! I couldn’t figure this out on my own.
Since my last message I discovered other numerical values for the attribute “AXMenuItemCmdModifiers”
The entire list is :
0 cmd +
1 cmd + maj +
2 cmd + option +
3 cmd + option + maj +
4 cmd + ctrl +
6 cmd + option + ctrl +
8
10
12 ctrl +
13 ctrl + maj +
24 fn fn
To identify menu items whose shortcut contains Escape, Delete, up arrow, down arrow, left arrow, right arrow it’s useful to extract also :
value of attribute “AXMenuItemCmdVirtualKey”
value of attribute “AXMenuItemCmdGlyph”
Here is a script which return the descriptions of menu items (1st level) of an application.
set theApp to "Safari"
activate application theApp
set params to {}
tell application "System Events" to tell process theApp to tell menu bar 1
set nbM to count menu bar items
repeat with i from 1 to nbM
tell menu 1 of menu bar item i
copy theApp & ", menu " & i & " ( " & name & " )" to end of params
repeat with j from 1 to count menu items
set maybe to {}
tell menu item j
copy name to end of maybe
try
copy value of attribute "AXMenuItemCmdChar" to end of maybe
on error
copy "" to end of maybe
end try
try
copy value of attribute "AXMenuItemCmdVirtualKey" to end of maybe
on error
copy "" to end of maybe
end try
try
copy value of attribute "AXMenuItemCmdGlyph" to end of maybe
on error
copy "" to end of maybe
end try
try
copy value of attribute "AXMenuItemCmdModifiers" to end of maybe
on error
copy "" to end of maybe
end try
end tell # menu item j
copy my recolle(maybe, tab) to end of params
end repeat
end tell # menu 1 of .
copy "" to end of params
end repeat
end tell # System Events .
set params to my recolle(params, return)
set nomDuRapport to (path to desktop as text) & theApp & (do shell script "date +_%Y%m%d_%H%M%S.txt")
my writeto(nomDuRapport, params, text, false)
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to "" & l
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as text
set openFile to open for access file targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access file targetFile
end try
return false
end try
end writeto
#=====
As is, it apply to Safari.
KOENIG Yvan (VALLAURIS, France) mercredi 24 juillet 2013 12:39:43
Magnifiqué.
( I can’t speak a word of French, but this is really brilliant Yvan! )
Since my last message I discovered other numerical values for the attribute “AXMenuItemCmdModifiers”
The entire list is :
0 cmd +
1 cmd + maj +
2 cmd + option +
3 cmd + option + maj +
4 cmd + ctrl +
6 cmd + option + ctrl +
8
10
12 ctrl +
13 ctrl + maj +
24 fn fn
Thanks, Yvan.
It looks like a jerry-rigged bit-flag system:
Bit 0 set (value = 1): shift down
Bit 1 set (value = 2): option down
Bit 2 set (value = 4): control down
Bit 3 set (value = 8): command UP
Bits 3 and 4 set (value = 24): fn fn
Hello Nigel
I understood the bit scheme but I don’t understand some values.
In every applications, Force quit. has the shortcut cmd + option + escape
value of attribute “AXMenuItemCmdChar” is missing
value of attribute “AXMenuItemCmdVirtualKey” is 53
value of attribute “AXMenuItemCmdGlyph” is 27 (ASCII value for escape)
value of attribute “AXMenuItemCmdModifiers” is 2 (cmd + option)
Do you know a resource giving explanations about VirtualKey and Glyph values ?
Start Dictation has Glyph 148 and Modifiers 24
Page précédente 123 100 0 cmd + left arrow
Page suivante 124 101 0 cmd + right arrow
Vider la corbeille. 51 23 1 cmd + maj + delete
Vider la corbeille 51 23 3 cmd + option + maj + delete
Vider la corbeille en mode sécurisé. 53 27 6 cmd + option + ctrl + escape ???
Vider la corbeille en mode sécurisé 10 cmd UP + option but the item is also visible without option. Would be more consistent if the item was also defined with the modifiers 8.
Close has two shortcuts cmd + W and cmd + maj + W
Save As. has two shortcuts cmd + S and cmd + maj + S
Move to Trash has two shortcuts cmd + delete and cmd + option + delete
but cmd + Z and cmd + maj + Z are two different commands.
Worse, cmd + A is Select All while cmd + maj + A is « Remplissage automatique de formulaires ». Honestly I don’t guess the relation between these two items.
Problem of consistency.
I don’t understand why Hide Safari and Hide others are always visible but
Quit Safari and Quit and keep windows behave differently (the late one appears only when option is depressed).
And worse, why all these useful informations are no longer available in “you know what” ?
KOENIG Yvan (VALLAURIS, France) mercredi 24 juillet 2013 15:34:49
Do you know a resource giving explanations about VirtualKey and Glyph values ?
Take a look at Carbon Accessibility Reference > Attributes > Menu-specific attributes
Enhanced version treating also sub-menu items.
set theApp to "TextEdit"
activate application theApp
set params to {"Name" & tab & "Char" & tab & "VirtualKey" & tab & "Glyph" & tab & "Modifiers" & tab & "Shortcut"}
tell application "System Events" to tell process theApp to tell menu bar 1
set nbM to count menu bar items
repeat with i from 1 to nbM
tell menu 1 of menu bar item i
copy theApp & ", menu " & i & " ( " & name & " )" to end of params
repeat with j from 1 to count menu items
set maybe to {}
tell menu item j
set theName to name
try # required for the first item of Help menu
theName
on error
set theName to ""
end try
copy theName to end of maybe
try # required for the first item of Help menu
set theChar to value of attribute "AXMenuItemCmdChar"
end try
try
theChar
on error
set theChar to ""
end try
copy theChar to end of maybe
try
copy value of attribute "AXMenuItemCmdVirtualKey" to end of maybe
on error
copy "" to end of maybe
end try
try # required for the first item of Help menu
set theGlyph to value of attribute "AXMenuItemCmdGlyph"
end try
try
theGlyph
on error
set theGlyph to ""
end try
copy theGlyph to end of maybe
try # required for the first item of Help menu
set theModifiers to value of attribute "AXMenuItemCmdModifiers"
end try
try
theModifiers
on error
set theModifiers to ""
end try
copy theModifiers to end of maybe
set prefix to ""
if theName > "" then
set prefix to my buildPrefix(theModifiers)
if theChar > "" then
if prefix > "" then copy prefix & theChar to end of maybe
else
# here, theChar is empty. We may have to decipher a glyph
set nameOfGlyph to my specialKey(theGlyph)
if nameOfGlyph > "" then copy prefix & nameOfGlyph to end of maybe
end if # theChar
end if # theName
#copy my recolle(maybe, tab) to end of params # Take care of possible submenus
# Now treat possible submenus
if {i, j} is not {1, 9} then # Skip Apple > Recent items
try
tell menu 1
set k to count menu items
# We are here if the menu item has submenu
# Pass the title of the menu
copy theName to end of params
repeat with k from 1 to count menu items
set maybe to {}
tell menu item k
set theName to name
try
theName
on error
set theName to ""
end try
copy "> " & theName to end of maybe
try
set theChar to value of attribute "AXMenuItemCmdChar"
end try
try
theChar
on error
set theChar to ""
end try
copy theChar to end of maybe
try
copy value of attribute "AXMenuItemCmdVirtualKey" to end of maybe
on error
copy "" to end of maybe
end try
set theGlyph to value of attribute "AXMenuItemCmdGlyph"
try
theGlyph
on error
set theGlyph to ""
end try
copy theGlyph to end of maybe
set theModifiers to value of attribute "AXMenuItemCmdModifiers"
try
theModifiers
on error
set theModifiers to ""
end try
copy theModifiers to end of maybe
set prefix to ""
if theName > "" then
set prefix to my buildPrefix(theModifiers)
if theChar > "" then
if prefix > "" then copy prefix & theChar to end of maybe
else
# here, theChar is empty. We may have to decipher a glyph
set nameOfGlyph to my specialKey(theGlyph)
if nameOfGlyph > "" then copy prefix & nameOfGlyph to end of maybe
end if # theChar
end if # theName
copy my recolle(maybe, tab) to end of params
end tell # menu item k
end repeat
end tell
on error
# We are here if the item has no submenus
copy my recolle(maybe, tab) to end of params
end try
else
# We are here if {i,j} is {1,9} Apple > Recent Items has no shortcut.
copy theName to end of params
end if # {i,j} is not {1,9}
end tell # menu item j
end repeat
end tell # menu 1 of .
copy "" to end of params
end repeat
end tell # System Events .
set params to my recolle(params, return)
set nomDuRapport to (path to desktop as text) & theApp & (do shell script "date +_%Y%m%d_%H%M%S.txt")
my writeto(nomDuRapport, params, text, false)
#tell application "Numbers" to open file nomDuRapport
#=====
on buildPrefix(the_Modifiers)
if the_Modifiers is 0 then
return "cmd + "
else if the_Modifiers is 1 then
return "cmd + maj + "
else if the_Modifiers is 2 then
return "cmd + option + "
else if the_Modifiers is 3 then
return "cmd + option + maj + "
else if the_Modifiers is 4 then
return "cmd + ctrl + "
else if the_Modifiers is 6 then
return "cmd + option + ctrl + "
else if the_Modifiers is 10 then
return "option + "
else
return ""
end if
end buildPrefix
#=====
on specialKey(the_Glyph)
if the_Glyph = 2 then
return "tab"
else if the_Glyph = 23 then
return "delete"
else if the_Glyph = 27 then
return "escape"
else if the_Glyph = 100 then
return "left arrow"
else if the_Glyph = 101 then
return "right arrow"
else if the_Glyph = 104 then
return "up arrow"
else if the_Glyph = 106 then
return "down arrow"
else if the_Glyph = 148 then
return "fn fn"
else
return ""
end if # the_Glyph
end specialKey
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to "" & l
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as text
set openFile to open for access file targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access file targetFile
end try
return false
end try
end writeto
#=====
I hope that I forgot nothing.
KOENIG Yvan (VALLAURIS, France) jeudi 25 juillet 2013 17:33:28
Enhanced version treating also sub-menu items.
And if you’d like it to ignore separators and to be several times as fast (or even if you wouldn’t):
-- Optimised from a script by Yvan Koenig.
main("TextEdit")
on main(theApp)
activate application theApp
set params to {"Name" & tab & "Char" & tab & "VirtualKey" & tab & "Glyph" & tab & "Modifiers" & tab & "Shortcut"}
tell application "System Events" to set {menuNames, {menuItemNames, {menuItemAttributeNames, menuItemAttributeValues}, {submenuItemNames, {submenuItemAttributeNames, submenuItemAttributeValues}}}} to {name, {name, {name, value} of attributes, {name, {name, value} of attributes} of menu items of menu 1} of menu items of menu 1} of menu bar items of menu bar 1 of application process theApp
repeat with mbIdx from 1 to (count menuNames)
set end of params to return & theApp & ", menu " & mbIdx & " ( " & item mbIdx of menuNames & " )"
repeat with mIdx from 1 to (count item mbIdx of menuItemNames)
set miName to item mIdx of item mbIdx of menuItemNames
if (miName is not missing value) then
set miLine to parseAttributes(miName, item mIdx of item mbIdx of menuItemAttributeNames, item mIdx of item mbIdx of menuItemAttributeValues)
set end of params to miLine
repeat with smIdx from 1 to (count item mIdx of item mbIdx of submenuItemNames)
set smiName to item smIdx of item mIdx of item mbIdx of submenuItemNames
if (smiName is not missing value) then
set miLine to parseAttributes("> " & smiName, item smIdx of item mIdx of item mbIdx of submenuItemAttributeNames, item smIdx of item mIdx of item mbIdx of submenuItemAttributeValues)
set end of params to miLine
end if
end repeat
end if
end repeat
end repeat
set params to my recolle(params, return)
set nomDuRapport to (path to desktop as text) & theApp & (do shell script "date +_%Y%m%d_%H%M%S.txt")
writeto(nomDuRapport, params, text, false)
end main
#tell application "Numbers" to open file nomDuRapport
#=====
on parseAttributes(miName, attrNames, attrValues)
set {theChar, theVirtualKey, theGlyph, theModifiers, theShortcut} to {"", "", "", "", ""}
repeat with miaIdx from 1 to (count attrNames)
set thisAttrName to item miaIdx of attrNames
if (thisAttrName is "AXMenuItemCmdChar") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theChar to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdVirtualKey") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theVirtualKey to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdGlyph") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theGlyph to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdModifiers") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theModifiers to thisAttrValue
end if
end repeat
if ((count theChar) > 0) then
set theShortcut to buildPrefix(theModifiers) & theChar
else if (theGlyph's class is integer) then
set theShortcut to buildPrefix(theModifiers) & specialKey(theGlyph)
end if
return recolle({miName, theChar, theVirtualKey, theGlyph, theModifiers, theShortcut}, tab)
end parseAttributes
on buildPrefix(the_Modifiers)
if the_Modifiers is 0 then
return "cmd + "
else if the_Modifiers is 1 then
return "cmd + shift + "
else if the_Modifiers is 2 then
return "cmd + option + "
else if the_Modifiers is 3 then
return "cmd + option + shift + "
else if the_Modifiers is 4 then
return "cmd + ctrl + "
else if the_Modifiers is 6 then
return "cmd + option + ctrl + "
else if the_Modifiers is 10 then
return "option + "
else
return ""
end if
end buildPrefix
#=====
on specialKey(the_Glyph)
if the_Glyph = 2 then
return "tab"
else if the_Glyph = 23 then
return "delete"
else if the_Glyph = 27 then
return "escape"
else if the_Glyph = 100 then
return "left arrow"
else if the_Glyph = 101 then
return "right arrow"
else if the_Glyph = 104 then
return "up arrow"
else if the_Glyph = 106 then
return "down arrow"
else if the_Glyph = 148 then
return "fn fn"
else
return ""
end if # the_Glyph
end specialKey
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to "" & l
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as text
set openFile to open for access file targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access file targetFile
end try
return false
end try
end writeto
#=====
Hello
I discovered that two values of modifiers which I didn’t deciphered are used so I edited a bit the Nigel’s version
-- Optimised from a script by Yvan Koenig.
-- completed by Yvan Koenig (2013/07/27)
# optionally added the separators
property showSeparators : true
# drop the submenu items of the Recent Items menu
# added two modifiers values : 5 & 7 which are used by two services :
# > Convertir le texte du chinois simplifié au chinois traditionnel
# > Convertir le texte du chinois traditionnel au chinois simplifié
main("TextEdit")
on main(theApp)
activate application theApp
set params to {"Name" & tab & "Char" & tab & "VirtualKey" & tab & "Glyph" & tab & "Modifiers" & tab & "Shortcut"}
tell application "System Events" to set {menuNames, {menuItemNames, {menuItemAttributeNames, menuItemAttributeValues}, {submenuItemNames, {submenuItemAttributeNames, submenuItemAttributeValues}}}} to {name, {name, {name, value} of attributes, {name, {name, value} of attributes} of menu items of menu 1} of menu items of menu 1} of menu bar items of menu bar 1 of application process theApp
repeat with mbIdx from 1 to (count menuNames)
set end of params to return & theApp & ", menu " & mbIdx & " ( " & item mbIdx of menuNames & " )"
repeat with mIdx from 1 to (count item mbIdx of menuItemNames)
set miName to item mIdx of item mbIdx of menuItemNames
if (miName is not missing value) then
if {mbIdx, mIdx} is not {1, 9} then
set miLine to parseAttributes(miName, item mIdx of item mbIdx of menuItemAttributeNames, item mIdx of item mbIdx of menuItemAttributeValues)
set end of params to miLine
repeat with smIdx from 1 to (count item mIdx of item mbIdx of submenuItemNames)
set smiName to item smIdx of item mIdx of item mbIdx of submenuItemNames
if (smiName is not missing value) then
set miLine to parseAttributes("> " & smiName, item smIdx of item mIdx of item mbIdx of submenuItemAttributeNames, item smIdx of item mIdx of item mbIdx of submenuItemAttributeValues)
set end of params to miLine
end if
end repeat
else
set end of params to item mIdx of item mbIdx of menuItemNames
end if # {mbIdx, mIdx} is not {1, 9}
else
# I wish to keep the separators
if showSeparators then set end of params to "-----------"
end if # (miName is not missing value)
end repeat
end repeat
set params to my recolle(params, return)
set nomDuRapport to (path to desktop as text) & theApp & (do shell script "date +_%Y%m%d_%H%M%S.txt")
writeto(nomDuRapport, params, text, false)
end main
#tell application "Numbers" to open file nomDuRapport
#=====
on parseAttributes(miName, attrNames, attrValues)
set {theChar, theVirtualKey, theGlyph, theModifiers, theShortcut} to {"", "", "", "", ""}
repeat with miaIdx from 1 to (count attrNames)
set thisAttrName to item miaIdx of attrNames
if (thisAttrName is "AXMenuItemCmdChar") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theChar to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdVirtualKey") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theVirtualKey to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdGlyph") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theGlyph to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdModifiers") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theModifiers to thisAttrValue
end if
end repeat
if ((count theChar) > 0) then
set theShortcut to buildPrefix(theModifiers) & theChar
else if (theGlyph's class is integer) then
set theShortcut to buildPrefix(theModifiers) & specialKey(theGlyph)
end if
return recolle({miName, theChar, theVirtualKey, theGlyph, theModifiers, theShortcut}, tab)
end parseAttributes
on buildPrefix(the_Modifiers)
if the_Modifiers is 0 then
return "cmd + "
else if the_Modifiers is 1 then
return "cmd + shift + "
else if the_Modifiers is 2 then
return "cmd + option + "
else if the_Modifiers is 3 then
return "cmd + option + shift + "
else if the_Modifiers is 4 then
return "cmd + ctrl + "
else if the_Modifiers is 5 then
return "cmd + shift + ctrl + "
else if the_Modifiers is 6 then
return "cmd + option + ctrl + "
else if the_Modifiers is 7 then
return "cmd + option + shift + ctrl + "
else if the_Modifiers is 10 then
return "option + "
else
return ""
end if
end buildPrefix
#=====
on specialKey(the_Glyph)
if the_Glyph = 2 then
return "tab"
else if the_Glyph = 23 then
return "delete"
else if the_Glyph = 27 then
return "escape"
else if the_Glyph = 100 then
return "left arrow"
else if the_Glyph = 101 then
return "right arrow"
else if the_Glyph = 104 then
return "up arrow"
else if the_Glyph = 106 then
return "down arrow"
else if the_Glyph = 148 then
return "fn fn"
else
return ""
end if # the_Glyph
end specialKey
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to "" & l
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as text
set openFile to open for access file targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access file targetFile
end try
return false
end try
end writeto
#=====
KOENIG Yvan (VALLAURIS, France) samedi 27 juillet 2013 21:31:21
I discovered that two values of modifiers which I didn’t deciphered are used so I edited a bit the Nigel’s version
Aha! Well here’s a shorter version of the buildPrefix() handler which will automatically cover any combination of the four modifier keys so far used:
on buildPrefix(the_Modifiers)
set prefix to ""
if (the_Modifiers mod 2 is 1) then set prefix to "shift + "
if (the_Modifiers div 2 mod 2 is 1) then set prefix to "option + " & prefix
if (the_Modifiers div 4 mod 2 is 1) then set prefix to prefix & "ctrl + "
if (the_Modifiers div 8 mod 2 is 0) then set prefix to "cmd + " & prefix
return prefix
end buildPrefix
Edit: Or slightly shorter still:
on buildPrefix(the_Modifiers)
set prefix to ""
if (the_Modifiers mod 2 is 1) then set prefix to "shift + "
if (the_Modifiers mod 4 > 1) then set prefix to "option + " & prefix
if (the_Modifiers mod 8 > 3) then set prefix to prefix & "ctrl + "
if (the_Modifiers mod 16 < 8) then set prefix to "cmd + " & prefix
return prefix
end buildPrefix
Hello
Some applications use Function keys as shortcuts so I edited the specialKey handler to treat such behavior :
on specialKey(the_Glyph)
if the_Glyph = 2 then
return "tab"
else if the_Glyph = 23 then
return "delete"
else if the_Glyph = 27 then
return "escape"
else if the_Glyph = 100 then
return "left arrow"
else if the_Glyph = 101 then
return "right arrow"
else if the_Glyph = 104 then
return "up arrow"
else if the_Glyph = 106 then
return "down arrow"
else if (the_Glyph > 110) and (the_Glyph < 130) then # range 111 . 129
return "F" & (the_Glyph - 110)
else if the_Glyph = 148 then
return "fn fn"
else
return ""
end if # the_Glyph
end specialKey
KOENIG Yvan (VALLAURIS, France) lundi 29 juillet 2013 10:40:21
Thanks to Nigel, I retrieved this thread.
Here is the now current version :
-- Optimised from a script by Yvan Koenig.
-- completed by Yvan Koenig (2013/07/27)
# optionally added the separators
property showSeparators : true
# drop the submenu items of the Recent Items menu
# added two modifiers values : 5 & 7 which are used by two services :
# > Convertir le texte du chinois simplifié au chinois traditionnel
# > Convertir le texte du chinois traditionnel au chinois simplifié
main("Numbers")
on main(theApp)
activate application theApp
set params to {"Name" & tab & "Char" & tab & "VirtualKey" & tab & "Glyph" & tab & "Modifiers" & tab & "Shortcut"}
tell application "System Events" to set {menuNames, {menuItemNames, {menuItemAttributeNames, menuItemAttributeValues}, {submenuItemNames, {submenuItemAttributeNames, submenuItemAttributeValues}}}} to {name, {name, {name, value} of attributes, {name, {name, value} of attributes} of menu items of menu 1} of menu items of menu 1} of menu bar items of menu bar 1 of application process theApp
repeat with mbIdx from 1 to (count menuNames)
set end of params to return & theApp & ", menu " & mbIdx & " ( " & item mbIdx of menuNames & " )"
repeat with mIdx from 1 to (count item mbIdx of menuItemNames)
set miName to item mIdx of item mbIdx of menuItemNames
if (miName is not missing value) then
if {mbIdx, mIdx} is not {1, 9} then
set miLine to parseAttributes(miName, item mIdx of item mbIdx of menuItemAttributeNames, item mIdx of item mbIdx of menuItemAttributeValues)
set end of params to miLine
repeat with smIdx from 1 to (count item mIdx of item mbIdx of submenuItemNames)
set smiName to item smIdx of item mIdx of item mbIdx of submenuItemNames
if (smiName is not missing value) then
set miLine to parseAttributes("> " & smiName, item smIdx of item mIdx of item mbIdx of submenuItemAttributeNames, item smIdx of item mIdx of item mbIdx of submenuItemAttributeValues)
set end of params to miLine
end if
end repeat
else
set end of params to item mIdx of item mbIdx of menuItemNames
end if # {mbIdx, mIdx} is not {1, 9}
else
# I wish to keep the separators
if showSeparators then set end of params to "-----------"
end if # (miName is not missing value)
end repeat
end repeat
set params to my recolle(params, return)
set nomDuRapport to (path to desktop as text) & theApp & (do shell script "date +_%Y%m%d_%H%M%S.txt")
writeto(nomDuRapport, params, text, false)
end main
#tell application "Numbers" to open file nomDuRapport
#=====
on parseAttributes(miName, attrNames, attrValues)
set {theChar, theVirtualKey, theGlyph, theModifiers, theShortcut} to {"", "", "", "", ""}
repeat with miaIdx from 1 to (count attrNames)
set thisAttrName to item miaIdx of attrNames
if (thisAttrName is "AXMenuItemCmdChar") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theChar to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdVirtualKey") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theVirtualKey to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdGlyph") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theGlyph to thisAttrValue
else if (thisAttrName is "AXMenuItemCmdModifiers") then
set thisAttrValue to item miaIdx of attrValues
if (thisAttrValue is not missing value) then set theModifiers to thisAttrValue
end if
end repeat
if ((count theChar) > 0) then
set theShortcut to buildPrefix(theModifiers) & theChar
else if (theGlyph's class is integer) then
set theShortcut to buildPrefix(theModifiers) & specialKey(theGlyph)
end if
return recolle({miName, theChar, theVirtualKey, theGlyph, theModifiers, theShortcut}, tab)
end parseAttributes
on buildPrefix(the_Modifiers)
set prefix to ""
if (the_Modifiers mod 2 is 1) then set prefix to "shift + "
if (the_Modifiers mod 4 > 1) then set prefix to "option + " & prefix
if (the_Modifiers mod 8 > 3) then set prefix to prefix & "ctrl + "
if (the_Modifiers mod 16 < 8) then set prefix to "cmd + " & prefix
return prefix
end buildPrefix
#=====
on specialKey(the_Glyph)
if the_Glyph = 2 then
return "tab"
else if the_Glyph = 23 then
return "delete"
else if the_Glyph = 27 then
return "escape"
else if the_Glyph = 100 then
return "left arrow"
else if the_Glyph = 101 then
return "right arrow"
else if the_Glyph = 104 then
return "up arrow"
else if the_Glyph = 106 then
return "down arrow"
else if (the_Glyph > 110) and (the_Glyph < 130) then # range 111 . 129
return "F" & (the_Glyph - 110)
else if the_Glyph = 148 then
return "fn fn"
else
return ""
end if # the_Glyph
end specialKey
#=====
on recolle(l, d)
local oTIDs, t
set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
set t to "" & l
set AppleScript's text item delimiters to oTIDs
return t
end recolle
#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
-- targetFile is the path to the file you want to write
-- theData is the data you want in the file.
-- dataType is the data type of theData and it can be text, list, record etc.
-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
try
set targetFile to targetFile as text
set openFile to open for access file targetFile with write permission
if not apendData then set eof of openFile to 0
write theData to openFile starting at eof as dataType
close access openFile
return true
on error
try
close access file targetFile
end try
return false
end try
end writeto
#=====
Yvan KOENIG (VALLAURIS, France) lundi 11 novembre 2013 18:04:18