Home > OS >  osascript: how to keep nested lists structure when output from command-line
osascript: how to keep nested lists structure when output from command-line

Time:02-14

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)
  • Related