I'm trying to code a script which can be able to extract the menu structure of a given app. This is a simplified working example:
tell application "System Events"
tell process "Terminal"
tell menu bar 1
set listA to name of every menu bar item
set listB to name of every menu of every menu bar item
set listC to name of every menu item of every menu of every menu bar item
set listD to name of every menu of every menu item of every menu of every menu bar item
set listE to name of every menu item of every menu of every menu item of every menu of every menu bar item
end tell
end tell
end tell
return {listA, listB, listC, listD, listE}
When I run this script on Script Editor, the result is a set of nested lists, like this (real result is too long, so I'm giving a sample):
{{{"Option1", "Option2", "Option3"}, {{"subOption1.1", "subOption1.2"}, {"subOption2.1", subOption2.2", "subOption2.3"}, {"subOption3.1"}}}
Thus, it's easy to know that menu Option1 has two items inside and so on...
But when I run this same script from python, using "osascript -e", the list structure and braces are gone, like this
{{"Option1", "Option2", "Option3"}, {"subOption1.1", "subOption1.2", "subOption2.1", subOption2.2", "subOption2.3", "subOption3.1"}}
So there is no way to know which sub-list corresponds to each other.
Is there a way to keep those braces or converting them into something different you can manage later on, or write this in a sort of "raw" data which keeps that nested structure?
Thanks in advance!
CodePudding user response:
Following @red_menace advice, I finally managed to get all application menu structure:
itemList = []
def findit():
level = 0
while True:
part = ""
for lev in range(level):
if lev % 2 == 0:
part = " of every menu" part
else:
part = " of every menu item" part
subCmd = "set itemList to name" part " of every menu bar item"
if level % 2 == 0: # Grabbing items only (menus will have non-empty lists on the next level)
cmd = """
on run arg1
set procName to arg1 as string
tell application "System Events"
tell process procName
tell menu bar 1
%s
end tell
end tell
end tell
return itemList as list
end run
""" % subCmd
# https://stackoverflow.com/questions/69774133/how-to-use-global-variables-inside-of-an-applescript-function-for-a-python-code
# Didn't find a way to get the "injected code" working when passed as argument
proc = subprocess.Popen(['osascript', '-s', 's', '-', str(self._parent._app.localizedName())],
stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding='utf8')
ret, err = proc.communicate(cmd)
ret = ret.replace("\n", "").replace('missing value', '"separator"').replace("{", "[").replace("}", "]")
item = ast.literal_eval(ret)
if err is None and not self._isListEmpty(item):
itemList.append(item)
else:
break
level = 1
return itemList != []
def fillit(subList):
# Pending: build hierarchy structure (dict format) from list
if findit():
print(itemList)
fillit(itemList)