views:

42

answers:

1

Is there a way to do a remote copy within a container from Scripting Bridge? In AppleScript, this looks like "copy [element] of [container] to [location in container]". For example, in the context of a tell to a TextEdit document, you can "copy first paragraph of its text to end of its text" to copy the first paragraph to the end of the document while preserving all formatting.

Is there any way to do with from Objective-C using Scripting Bridge?

I tried something like this:

SBObject* foo = [container objectAtIndex: 0];
[container addObject: foo];

And got a message "can't add an object that already exists." on the console; it appears that addObject and the various replace* methods only work when you're building a new SBObject instance and inserting it.

+1  A: 

When the second parameter to AppleScript's built-in copy command is an application reference, AppleScript 'helpfully' aliases to an application duplicate or set command, depending on whether the first parameter is another reference or not. To avoid confusion, it's best to use duplicate or set explicitly when dealing with scriptable apps in AppleScript.

As for SB, you would need to look for a duplicate... method in the header file. Be aware that SB's duplicate command is semi-crippled (SB has quite a few shortcomings) since it can only deal with a single object at a time. Most applications will allow you to manipulate multiple objects in a single command (caveat any bugs in their scripting support), e.g. AppleScript will let you say:

tell application "iTunes"
    duplicate (every track whose artist is "Foo") to (playlist "Bar")
end tell

but SB won't; instead you have to extract a list of single references and iterate over those, processing them one at a time. Makes your code rather longwinded, and can be very inefficient if you've a large number of objects elsewhere.

Another option is objc-appscript, which does all this stuff correctly and is much less prone to application compatibility issues in general ('quirk-for-quirk compatibility', as Matt Neuburg puts it). Plus you get ASTranslate, which converts AppleScript commands to the equivalent Python/Ruby/ObjC syntax - very handy when figuring out how to phrase a command correctly:

#import "ITGlue/ITGlue.h"
ITApplication *itunes = [ITApplication applicationWithName: @"iTunes"];
ITReference *ref = [[itunes tracks] byTest: [[ITIts artist] equals: @"Foo"]];
ITDuplicateCommand *cmd = [[ref duplicate] to: [[itunes playlists] byName: @"Bar"]];
id result = [cmd send];

Yet another option, if you're on 10.6, would be to use the AppleScriptObjC bridge, which allows you to combine AS and ObjC in the same program without any of that nasty NSAppleScript nonsense. That would allow you to use AppleScript for what it's best at (communicating with other apps) and ObjC for everything else. Official documentation is limited, but a web-search should throw up various third-party resources. MacScripter.net might be a good place to start - in addition to the ASOC forum, Craig Williams posted a series of tutorials a while back.

(BTW, Craig also contributed a chapter about ASOC to the third edition of Apress's Learn AppleScript, which I co-wrote, and which includes lots of information on application scripting principles and practices, including clarification of set/duplicate/copy.)

has
Thanks for the very thorough treatment! I'm currently using a mix of Scripting Bridge and ASOC, and it looks like I'll be able to scrape by with that.
Walter Mundt
I found a `- duplicateTo:(SBObject*) withProperties:(NSDictionary*)` method, but how do I build an `SBObject*` specifying "end of [container]" or some similar interstitial location not containing an actual object?
Walter Mundt
Y'know, I don't actually know. It's entirely possible that the SB developers forgot to add a way to do that, but it's hard to say for sure without further research, given that the documentation is lousy and the API addled and opaque. (SB is the reason I wrote objc-appscript, btw.) Have you tried passing a reference to the container itself, on the off-chance that this works? (Some apps expect a container reference anyway.) If that fails, I'd suggest posting to applescript-implementors and try to get the attention of an AS engineer. Or use appscript, which basically Just Works.
has
Well, I've already written an AppleScriptObjC class basically for the sole purpose of running this copy (though it does a bit more to give it a decent home in the object model). I'll definitely just go straight to appscript the next time I need to do anything with the wonderful world of Apple Events.
Walter Mundt