开发者

applescript elements, classes, and objects

开发者 https://www.devze.com 2023-02-24 15:12 出处:网络
I\'m writing an applescript to automate some tedious work in Aperture, and I\'m having a hell of a time understanding some of the peculiarities of the language. In particular, I\'m having a really dif

I'm writing an applescript to automate some tedious work in Aperture, and I'm having a hell of a time understanding some of the peculiarities of the language. In particular, I'm having a really difficult time dealing with collections (lists and elements). I'm stumped by object specifiers that include collections and applying commands to elements in a collection. Moreover, I'm confused by strange differences in object specifiers that seem to behave differently when referring to object elements by their class within a class versus, well, let me show you.

Here's the beginning of a script.

prop Movies : {}

tell Application "Aperture"
     set Movies to every image version whose name of every keywords contains "Movie"
end tell

length of Movies   -- result => 601

The application object in Aperture contains an elements collection of image versions. image version objects contain an elements collection of keywords. keywords are objects/lists with a name and id property.

So the global script property Movies now contains all of the image version objects in my Aperture library that are actually videos. Now, when I try to do this:

repeat with movie in Movies
    log ("Movie name is '" & name of movie & "'.")
    log ("  the class of this object is '" & class of movie & "'.")
end

the output, as expected, is:

Movie name is 'MOV03510.MPG'.
  the class of this object is 'image version'.
Movie name is 'MOV00945'.
  the class of this object is 'image version'.
Movie name is 'MOV03228.MPG'.
  the class of this object is 'image version'.
Movie name is 'MOV02448'.
  the class of this object is 'image version'.
...

However, I'm stuck with how to access an elements collection within those image versions. When I do this:

repeat with movie in Movies

    log ("Movie name is '" & name of movie & "'.")
    log ("  the class of this object is '" & class of movie & "'.")
    set kwnamelist to name of every keyword in movie
    if kwnamelist contains "Movie"
       log ("    Yes, '" & name of movie & "' is indeed a video.")
    end if
end

gives me

find_videos.applescript:1089:1096: script error: Expected class name but found identifier. (-2741)

The error, to me, sounds like applescript is confused by the object specifier name of every keyword in movie. BUT, the reason I'm so confused about this is that if I write this code:

tell Application "Aperture"
    repeat with imageind from 1 to 1000
        set img to item imageind of image versions
        tell me to log ("Image name is '" & name of img & "'.")
        tell me to log ("  the class of this object is '" & class of img & "'.")
        set kwnamelist to name of every keyword in img
        if kwnamelist contains "Movie" 
            tell me to log ("    '" & name of img & "' is actually a video!")
        end if
    end
end tell

then I get the expected output:

...
Image name is 'DSC_4650'.
  the class of this object is 'image version'.
Image name is '104-0487_IMG'.
  the class of this object is 'image version'.
Image name is 'MOV02978.MPG'.
  the class of this object is 'image version'.
    'MOV02978.MPG' is actually a video!
Image name is '108-0833_IMG'.
  the class of this object is 'image version'.

...

Can anyone tell me what's wrong with my object specifier? Why is it that I can essentially apply get name to every keyword in img when the image version is in one context, but I can't in a different context? Is there something I'm missing here? Is it that the keyword class is internal to the Aperture application object? How would I specify something like application::keyword if that's the case?

UPDATE:

I've solved this particular problem, but I'd really appreciate it if someone could explain exactly why this solves it. I did this:

tell Application "Aperture"
    repeat with movie in Movies
        tell me to log ("Movie name is '" & name of movie & "'.")
        tell me to log ("  the class of this object is '" & class of movie & "'.")
        set kwnamelist to name of every keyword in movie
        if kwnamelist contains "Movie"
            tell me to log ("    Yes, '" & name of movie & "' is indeed a video.")
        end if
    end
end tell

gives the expected output:

...
Movie name is 'IMG_0359'.
  the class of this object is 'image version'.
    Yes, 'IMG_0359' is indeed a video.
Movie name is 'MOV02921.MPG'.
  the class of this object is 'image version'.
    Yes, 'MOV02921.MPG' is indeed a video.
Movie name is 'MOV02249'.
  the class of this object is 'image version'.
 开发者_StackOverflow   Yes, 'MOV02249' is indeed a video.
...

It seems like there's a very peculiar scope issue at work here. Could someone explain to me how keyword objects are in scope in this new version, but out of scope in the previous version where we weren't in a tell block? I thought that tell blocks were just for directing commands without direct parameters? Do they determine type scope as well? Or is there a command hidden somewhere here in the construction/execution of the object specifier that depends on getting sent to the Application "Aperture" object?


If I understand the core of your question correctly - because you have solved the practical part, screwy dereferencing, which is a bit of an old chestnut for applescripters - you must only use terminology inside the relevant tell blocks, so if your application (Aperture) supplies the terminology "keyword", you can't refer to "keyword" unless you are inside a tell application "Aperture" block.

OR if for some reason you want to use terminology from a given app without using a tell block, you can wrap your code like this:

using terms from application "Aperture"
  -- blah blah about 'keyword' and other Aperture terminology
end using terms from


Applescript is rather funny like this unfortunately and often times it's hit or miss. In this case repeat with item in list, item is a reference to the contents, not the contents itself. Often times AppleScript will dereference this for you, but not always. Typically I always use the repeat with x from 1 to count method to avoid this problem.


About scripting Aperture keywords

Keyword scripting in Aperture 3 is quite unintuitive. Here's what Ive learned:

  • A keyword's id is a string with the path from the keyword name up to its top-level parent, with each parent's name preceded by a tab.
  • The value of the parents property is just the id without the name and, if the keyword is not at the top-level, the tab following the name.
  • Keywords don't compare equal even if their values are the same; in fact, keyword 1 of animage != keyword 1 of anImage.
  • An image may have multiple keywords with the same name if they have different parents. However, the name will only appear once wherever the image's metadata is displayed.
  • The way to add a keyword to anImage with name aName and parents theParents is tell anImage to make new keyword with properties {name:aName, parents:theParents, id:aName&tab&theParents}

See my entry here for a fuller explanation plus add and remove handlers.

0

精彩评论

暂无评论...
验证码 换一张
取 消