Sending a list of path strings to the Finder via Scripting Bridge

  • Hi,

    I'd like to reveal/select multiple items in the Finder.
    NSWorkspace only handles single files as in

                [[NSWorkspace sharedWorkspace] selectFile:currentFilePath
                                inFileViewerRootedAtPath:currentFilePath];

    I searched Google and tried to pick up every scrap of information on the Scripting Bridge but I could not find anything about sending a LIST of paths.

    If all fails I'll have to convert the path strings to hfs paths and string-assemble a script to run using NSAppleScript in code - which feels clumsy.

    Thank you for any pointers!

    Peter
  • On May 24, 2012, at 23:56 , Peter wrote:

    > I'd like to reveal/select multiple items in the Finder.
    > NSWorkspace only handles single files as in
    >
    > [[NSWorkspace sharedWorkspace] selectFile:currentFilePath
    > inFileViewerRootedAtPath:currentFilePath];

    How about -[NSWorkspace activateFileViewerSelectingURLs:] (10.6+)?
  • Am 25.05.2012 um 09:09 schrieb Quincey Morris:

    > On May 24, 2012, at 23:56 , Peter wrote:
    >
    >> I'd like to reveal/select multiple items in the Finder.
    >> NSWorkspace only handles single files as in
    >>
    >> [[NSWorkspace sharedWorkspace] selectFile:currentFilePath
    >> inFileViewerRootedAtPath:currentFilePath];
    >
    > How about -[NSWorkspace activateFileViewerSelectingURLs:] (10.6+)?

    Oh, thanks - I admit I missed this one, but I am supporting OS 10.5, so I still have to find a way for it.
  • On 25/05/2012, at 4:56 PM, Peter wrote:

    > If all fails I'll have to convert the path strings to hfs paths and string-assemble a script to run using NSAppleScript in code

    If you do end up using NSAppleScript, you can still avoid HFS paths: just use 'POSIX file "/Users/fred/whatever.txt"'.

    --
    Shane Stanley <sstanley...>
    'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>
  • On May 25, 2012, at 00:14 , Peter wrote:

    > I am supporting OS 10.5, so I still have to find a way for it.

    Isn't there a solution using a sequence starting with:

    [[NSWorkspace sharedWorkspace] selectFile:currentFilePath [0] inFileViewerRootedAtPath: [currentFilePath stringByDeletingLastPathComponent];

    followed by a sequence of:

    [[NSWorkspace sharedWorkspace] selectFile:currentFilePath [n] inFileViewerRootedAtPath: nil];

    ? That's assuming the files are all in the same directory. If not, you're going to have to get the Finder to open multiple windows anyway.

    Even if it's not perfectly what you want, something based on that idea might be an acceptable workaround if used for 10.5 only, using the newer API for 10.6+.
  • Thanks Shane! This is indeed a nice trick - and it's so obvious, once you are told. ;-)

    Am 25.05.2012 um 09:24 schrieb Shane Stanley:

    > On 25/05/2012, at 4:56 PM, Peter wrote:
    >
    >> If all fails I'll have to convert the path strings to hfs paths and string-assemble a script to run using NSAppleScript in code
    >
    > If you do end up using NSAppleScript, you can still avoid HFS paths: just use 'POSIX file "/Users/fred/whatever.txt"'.
    >
    > --
    > Shane Stanley <sstanley...>
    > 'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/
    >
  • On May 25, 2012, at 2:24 AM, Shane Stanley wrote:

    > On 25/05/2012, at 4:56 PM, Peter wrote:
    >
    >> If all fails I'll have to convert the path strings to hfs paths and string-assemble a script to run using NSAppleScript in code
    >
    > If you do end up using NSAppleScript, you can still avoid HFS paths: just use 'POSIX file "/Users/fred/whatever.txt"'.

    While this is probably the best way to go, for completeness’s sake, I should point out that if you do need to create an HFS-style path for some reason, you don’t have to do it by hand; you can use CFURLCopyFileSystemPath with kCFURLHFSPathStyle to generate an HFS path automatically.

    Charles
  • Answering my own post:

    After much experimentation I come to the conclusion that this is impossible using Scripting Bridge.
    Interestingly, a code example from Apple called SBSetFinderComment, which illustrates setting Finder comments using Scripting Bridge includes a "Reveal in Finder" function - for which it uses the method -[NSWorkspace activateFileViewerSelectingURLs:] Quincey Morris pointed out to me.

    The reason for this, as far as I can see, is a fundamental design problem, i.e. to my utter astonishment, there is no way to assemble a list of arbitrary paths as the target of an AppleScript command.

    (a) All AS elements have to be added to a SBElementsArray before you can work with them.

    (b) There is no way to alloc-init an SBElementsArray to add arbitrary elements to it.

    (c) Therefore you have to use one of the SBElementsArrays prepared by the Finder, i.e. [finder items] (see the code example above), which BTW, as it would in plain AppleScript, by default designates the items on the user's Desktop. There seems to be no way to specify any user defined folder (!) - see (f) below.

    (d) There is no way to delete the items from a given SBElementsArray and then add elements by the user's choice: [[finder items] removeAllObjects] will not clear the array, but instead move all items on your Desktop to the trash! (I consider this to be a bug.)

    (e) It is perfectly possible to reveal multiple items in the Finder. It is as simple as issuing [[finder items] reveal]. The problem is that there is no way to specify multiple arbitrary items: You can easily loop over an array of file paths, convert them to NSURLs (although Finder.h maintains that the URLs have to be NSStrings), and issue [[[finder items] objectAtLocation:theFileURL] reveal] - but this way the items will be revealed consecutively and not simultaneously. There are of course a lot of occasions where consecutive execution may be perfectly viable, but not here.

    (f) The Scripting Bridge talks at length about efficient coding using bulk operation methods. On the other hand, it does not even seem to provide a simple means to, say, access the elements from a specific folder X and narrow these down using filteredArrayUsingPredicate - with the exceptions of those predefined in the Finder sdef/Finder.h: i.e. the trash, home, startup disk, desktop and the like. For all other cases you have to access items individually and therefore inefficiently using objectAtLocation: or similar.

    This is an ugly mess. I am sorry to say so. I could not believe it, which is why I asked here. At least, Scripting Bridge was certainly not designed with the Finder in mind. It may work better for other scriptable applications, though. One more half-baked technology from Apple (as is the new pasteboard API in its current implementation even if it looks very elegant on the surface - I guess quite a good deal of people will be bitten by it if it becomes compulsory, since it prevents you from doing some simple things possible with the current API; see my inquiry on this list a couple of weeks ago). It is a shame that appscript can no longer be supported for current and future OSes. It is/was far superior.

    In the end I chose to use NSAppleScript using Shane's trick below and it turns out to be astonishingly fast and easy. (Even if it is supposed to leak memory.)

    Thanks for all your comments!

    Am 25.05.2012 um 09:31 schrieb Peter:

    > Am 25.05.2012 um 09:24 schrieb Shane Stanley:
    >
    >> On 25/05/2012, at 4:56 PM, Peter wrote:
    >>
    >>> If all fails I'll have to convert the path strings to hfs paths and string-assemble a script to run using NSAppleScript in code
    >>
    >> If you do end up using NSAppleScript, you can still avoid HFS paths: just use 'POSIX file "/Users/fred/whatever.txt"'.
    >>
    >> --
    >> Shane Stanley <sstanley...>
    >> 'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>
  • On May 26, 2012, at 2:42 AM, Peter wrote:

    > One more half-baked technology from Apple (as is the new pasteboard API in its current implementation even if it looks very elegant on the surface - I guess quite a good deal of people will be bitten by it if it becomes compulsory, since it prevents you from doing some simple things possible with the current API; see my inquiry on this list a couple of weeks ago).

    This led me to look up your earlier messages, quoted below:

    On February 27, 2012, at 2:44 AM, Peter wrote:

    > I am still very much puzzled by the issue I described below, so I still hope to find a taker for it.
    >
    > While the OS 10.5 API cleanly separated pasteboard types, the 10.6 API converts NSURL data to strings and adds it to any existing string data - i.e. when pasting the data into e.g. a text view in 10.6 I get
    >
    > file://localhost/Users/peterjhartmann/Desktop/Eigene Bilder/jan.jpg
    > file://localhost/Users/peterjhartmann/Desktop/Eigene Bilder/Nob.jpg
    > jan
    > Nob
    >
    > instead of
    >
    > jan
    > Nob
    >
    > which is the result using the 10.5 API. As described, this happens no matter wether I use writeObjects: or setString: and no matter wether I write the URLs before or after the strings.
    >
    > I consider this to be a bug. Am I wrong? If so, what am I doing wrong?
    >
    > Does anybody use the 10.6 pasteboard API? Judging from my web searches it seems that almost nobody does.
    >
    > One member contacted my privately stating ...
    >
    >> Not sure if you've fixed this or had any other replies, but in reading it through, I notice you're not declaring the pasteboard type ([pb declareTypes:...]) within this block.  Does this explain the symptoms?
    >
    > but declareTypes belongs to the old API. Mixing this with the new API is discouraged on p. 33 of Apple's PasteboardGuide106.pdf.
    >
    > I'd be very happy about any pointers into the right direction.
    >
    > My original post is here:
    >
    > Am 19.02.2012 um 21:24 schrieb Peter:
    >
    >> I am using the following code:
    >>
    >> NSPasteboard *pb = [NSPasteboard generalPasteboard];
    >>
    >> if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_5) {
    >> //linesArray contains file paths as NSStrings
    >> //namesArray contains file names as NSStrings
    >> [pb declareTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, nil] owner:nil];
    >> [pb setPropertyList:linesArray forType:NSFilenamesPboardType];
    >> [pb setString:[namesArray componentsJoinedByString:@"\n"] forType:NSStringPboardType];
    >> }
    >> else { // >= 10.6
    >> //linesArray contains NSURLs
    >> //namesArray contains file names as NSStrings
    >> [pb clearContents];
    >> [pb setString:[namesArray componentsJoinedByString:@"\n"] forType:NSPasteboardTypeString];
    >> //[pb writeObjects:namesArray];
    >> [pb writeObjects:linesArray]; // write the URLs
    >> }

    I think you are failing to understand the nature of the change introduced with 10.6.  Prior to 10.6, there was always a single pasteboard item.  It could have multiple types/representations.

    Since it is clearly sometimes desirable to have multiple things on the pasteboard, there was a hack.  Some of the types were "plural", like NSFilenamesPboardType.  So, with your 10.5 code path, there's a single item.  One of its types/representations is an array of filenames, the other is a string (which you've constructed by joining multiple strings with newlines).

    From 10.6, the pasteboard supports multiple items.  _Each_ item can have multiple types/representations.  Because of that, it's no longer necessary to use plural types like NSFilenamesPboardType.  You can just add an array of NSURLs.

    However, if you add NSURLs and you add strings, you have established that _all_ of those items are on the pasteboard _individually_.  Given how you've done it, the URLs and the strings are not alternative representations of the same items, they are all separate items on the pasteboard.  It is not a bug for TextEdit to paste them all; it would be a bug for it to not do so.

    If what you want is a number of items, where each item has two types/representations – a URL or a string – then that's what you have to put on the pasteboard.  Create an NSPasteboardItem for each item.  For each item, for each type/representation, set the data.  So, if an item is supposed to have an NSURL representation and a string representation, do something like:

        for (NSString* type in [someURL writableTypesForPasteboard:pb])
            [item setPropertyList:[someURL pasteboardPropertyListForType:type] forType:type];
        [item setString:someString forType:NSPasteboardTypeString];

    Put all of the pasteboard items constructed in this manner into an array and write that array to the pasteboard using -writeObject:. Then you will have set up the pasteboard in a manner that's analogous to what you were doing with the 10.5 API.

    Regards,
    Ken
  • David,

    thank you, but no, this will not work. I should have stated this explicitly:

    '*** -[SBElementArray init]: should never be used.'

    is the exception I get when using the method proposed by you. In my experience, all other alloc-init variants fail in the same way. It is impossible to alloc and/or init an SBElementArray.

    (Posting this to the list, too, since it is a valuable addition to the discussion.)

    Am 26.05.2012 um 11:26 schrieb David A. Lyons:

    > I haven't tried it myself, but:
    >
    > <https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Scr
    iptingBridgeConcepts/UsingScriptingBridge/UsingScriptingBridge.html
    >
    >
    >> For adding scripting objects to element arrays, you may use NSMutableArray methods such as insertObject:atIndex: and addObject:. To remove objects from element arrays, call removeObject: (or a related method of NSMutableArray) on the element array.
    >
    > ...so perhaps you can call +[SBElementArray array] to get an empty one and then add to it.  Cheers,
    >
    > --Dave
    >
    >
    >
    > On May 26, 2012, at 12:42 AM, Peter <magnard...> wrote:
    >
    >> Answering my own post:
    >>
    >> After much experimentation I come to the conclusion that this is impossible using Scripting Bridge.
    >> Interestingly, a code example from Apple called SBSetFinderComment, which illustrates setting Finder comments using Scripting Bridge includes a "Reveal in Finder" function - for which it uses the method -[NSWorkspace activateFileViewerSelectingURLs:] Quincey Morris pointed out to me.
    >>
    >> The reason for this, as far as I can see, is a fundamental design problem, i.e. to my utter astonishment, there is no way to assemble a list of arbitrary paths as the target of an AppleScript command.
    >>
    >> (a) All AS elements have to be added to a SBElementsArray before you can work with them.
    >>
    >> (b) There is no way to alloc-init an SBElementsArray to add arbitrary elements to it.
    >>
    >> (c) Therefore you have to use one of the SBElementsArrays prepared by the Finder, i.e. [finder items] (see the code example above), which BTW, as it would in plain AppleScript, by default designates the items on the user's Desktop. There seems to be no way to specify any user defined folder (!) - see (f) below.
    >>
    >> (d) There is no way to delete the items from a given SBElementsArray and then add elements by the user's choice: [[finder items] removeAllObjects] will not clear the array, but instead move all items on your Desktop to the trash! (I consider this to be a bug.)
    >>
    >> (e) It is perfectly possible to reveal multiple items in the Finder. It is as simple as issuing [[finder items] reveal]. The problem is that there is no way to specify multiple arbitrary items: You can easily loop over an array of file paths, convert them to NSURLs (although Finder.h maintains that the URLs have to be NSStrings), and issue [[[finder items] objectAtLocation:theFileURL] reveal] - but this way the items will be revealed consecutively and not simultaneously. There are of course a lot of occasions where consecutive execution may be perfectly viable, but not here.
    >>
    >> (f) The Scripting Bridge talks at length about efficient coding using bulk operation methods. On the other hand, it does not even seem to provide a simple means to, say, access the elements from a specific folder X and narrow these down using filteredArrayUsingPredicate - with the exceptions of those predefined in the Finder sdef/Finder.h: i.e. the trash, home, startup disk, desktop and the like. For all other cases you have to access items individually and therefore inefficiently using objectAtLocation: or similar.
    >>
    >> This is an ugly mess. I am sorry to say so. I could not believe it, which is why I asked here. At least, Scripting Bridge was certainly not designed with the Finder in mind. It may work better for other scriptable applications, though. One more half-baked technology from Apple (as is the new pasteboard API in its current implementation even if it looks very elegant on the surface - I guess quite a good deal of people will be bitten by it if it becomes compulsory, since it prevents you from doing some simple things possible with the current API; see my inquiry on this list a couple of weeks ago). It is a shame that appscript can no longer be supported for current and future OSes. It is/was far superior.
    >>
    >> In the end I chose to use NSAppleScript using Shane's trick below and it turns out to be astonishingly fast and easy. (Even if it is supposed to leak memory.)
    >>
    >> Thanks for all your comments!
    >>
    >> Am 25.05.2012 um 09:31 schrieb Peter:
    >>
    >>> Am 25.05.2012 um 09:24 schrieb Shane Stanley:
    >>>
    >>>> On 25/05/2012, at 4:56 PM, Peter wrote:
    >>>>
    >>>>> If all fails I'll have to convert the path strings to hfs paths and string-assemble a script to run using NSAppleScript in code
    >>>>
    >>>> If you do end up using NSAppleScript, you can still avoid HFS paths: just use 'POSIX file "/Users/fred/whatever.txt"'.
    >>>>
    >>>> --
    >>>> Shane Stanley <sstanley...>
    >>>> 'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>

    >
    >
  • Ken,

    thank you very much for your enlightening and in-depth explanation! This is what I hoped somehow to receive back in February...

    Over the next days I will try and put your approach to practice. If it works as I hope I will certainly withdraw my comment about the new API being a half-baken technology.

    Since you are at it ;-), I remember having one more problem back then:

    With the old API I could (and still do) put a list of path strings with empty elements on the pasteboard, e.g. four paths, the third one empty as in

    /path1/item1
    /path2/item1

    /path2/item2

    but since the new API moved to NSURLs I don't see a way to accomplish this. I could not find something like an empty NSURL. I use this for copying data from a table area to another table or table area, meaning the empty element is a valid piece of data. Any ideas?

    Thank you!

    Am 26.05.2012 um 11:13 schrieb Ken Thomases:

    > On May 26, 2012, at 2:42 AM, Peter wrote:
    >
    >> One more half-baked technology from Apple (as is the new pasteboard API in its current implementation even if it looks very elegant on the surface - I guess quite a good deal of people will be bitten by it if it becomes compulsory, since it prevents you from doing some simple things possible with the current API; see my inquiry on this list a couple of weeks ago).
    >
    > This led me to look up your earlier messages, quoted below:
    >
    > On February 27, 2012, at 2:44 AM, Peter wrote:
    >
    >> I am still very much puzzled by the issue I described below, so I still hope to find a taker for it.
    >>
    >> While the OS 10.5 API cleanly separated pasteboard types, the 10.6 API converts NSURL data to strings and adds it to any existing string data - i.e. when pasting the data into e.g. a text view in 10.6 I get
    >>
    >> file://localhost/Users/peterjhartmann/Desktop/Eigene Bilder/jan.jpg
    >> file://localhost/Users/peterjhartmann/Desktop/Eigene Bilder/Nob.jpg
    >> jan
    >> Nob
    >>
    >> instead of
    >>
    >> jan
    >> Nob
    >>
    >> which is the result using the 10.5 API. As described, this happens no matter wether I use writeObjects: or setString: and no matter wether I write the URLs before or after the strings.
    >>
    >> I consider this to be a bug. Am I wrong? If so, what am I doing wrong?
    >>
    >> Does anybody use the 10.6 pasteboard API? Judging from my web searches it seems that almost nobody does.
    >>
    >> One member contacted my privately stating ...
    >>
    >>> Not sure if you've fixed this or had any other replies, but in reading it through, I notice you're not declaring the pasteboard type ([pb declareTypes:...]) within this block.  Does this explain the symptoms?
    >>
    >> but declareTypes belongs to the old API. Mixing this with the new API is discouraged on p. 33 of Apple's PasteboardGuide106.pdf.
    >>
    >> I'd be very happy about any pointers into the right direction.
    >>
    >> My original post is here:
    >>
    >> Am 19.02.2012 um 21:24 schrieb Peter:
    >>
    >>> I am using the following code:
    >>>
    >>> NSPasteboard *pb = [NSPasteboard generalPasteboard];
    >>>
    >>> if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_5) {
    >>> //linesArray contains file paths as NSStrings
    >>> //namesArray contains file names as NSStrings
    >>> [pb declareTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, nil] owner:nil];
    >>> [pb setPropertyList:linesArray forType:NSFilenamesPboardType];
    >>> [pb setString:[namesArray componentsJoinedByString:@"\n"] forType:NSStringPboardType];
    >>> }
    >>> else { // >= 10.6
    >>> //linesArray contains NSURLs
    >>> //namesArray contains file names as NSStrings
    >>> [pb clearContents];
    >>> [pb setString:[namesArray componentsJoinedByString:@"\n"] forType:NSPasteboardTypeString];
    >>> //[pb writeObjects:namesArray];
    >>> [pb writeObjects:linesArray]; // write the URLs
    >>> }
    >
    > I think you are failing to understand the nature of the change introduced with 10.6.  Prior to 10.6, there was always a single pasteboard item.  It could have multiple types/representations.
    >
    > Since it is clearly sometimes desirable to have multiple things on the pasteboard, there was a hack.  Some of the types were "plural", like NSFilenamesPboardType.  So, with your 10.5 code path, there's a single item.  One of its types/representations is an array of filenames, the other is a string (which you've constructed by joining multiple strings with newlines).
    >
    > From 10.6, the pasteboard supports multiple items.  _Each_ item can have multiple types/representations.  Because of that, it's no longer necessary to use plural types like NSFilenamesPboardType.  You can just add an array of NSURLs.
    >
    > However, if you add NSURLs and you add strings, you have established that _all_ of those items are on the pasteboard _individually_.  Given how you've done it, the URLs and the strings are not alternative representations of the same items, they are all separate items on the pasteboard.  It is not a bug for TextEdit to paste them all; it would be a bug for it to not do so.
    >
    > If what you want is a number of items, where each item has two types/representations – a URL or a string – then that's what you have to put on the pasteboard.  Create an NSPasteboardItem for each item.  For each item, for each type/representation, set the data.  So, if an item is supposed to have an NSURL representation and a string representation, do something like:
    >
    > for (NSString* type in [someURL writableTypesForPasteboard:pb])
    > [item setPropertyList:[someURL pasteboardPropertyListForType:type] forType:type];
    > [item setString:someString forType:NSPasteboardTypeString];
    >
    > Put all of the pasteboard items constructed in this manner into an array and write that array to the pasteboard using -writeObject:. Then you will have set up the pasteboard in a manner that's analogous to what you were doing with the 10.5 API.
    >
    > Regards,
    > Ken
    >
    >
  • In partial rehabilitation of the Scripting Bridge, I should add that it certainly makes life A LOT easier than using NSAppleScript when pulling out data from a scriptable application: just try to make sense of the NSAppleEventDescriptor NSAppleScript returns, even given the flaws I pointed out in my previous posts.
  • On 26/05/2012, at 8:24 PM, Peter wrote:

    > In partial rehabilitation of the Scripting Bridge, I should add that it certainly makes life A LOT easier than using NSAppleScript when pulling out data from a scriptable application: just try to make sense of the NSAppleEventDescriptor NSAppleScript returns, even given the flaws I pointed out in my previous posts.

    FWIW, if you didn't have to go back beyond 10.6, AppleScriptObjC also skirts that issue -- and the issue of trying to translate AppleScript back to SBStuff.

    --
    Shane Stanley <sstanley...>
    'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>
  • Am 26.05.2012 um 13:07 schrieb Shane Stanley:

    > On 26/05/2012, at 8:24 PM, Peter wrote:
    >
    >> In partial rehabilitation of the Scripting Bridge, I should add that it certainly makes life A LOT easier than using NSAppleScript when pulling out data from a scriptable application: just try to make sense of the NSAppleEventDescriptor NSAppleScript returns, even given the flaws I pointed out in my previous posts.
    >
    > FWIW, if you didn't have to go back beyond 10.6, AppleScriptObjC also skirts that issue -- and the issue of trying to translate AppleScript back to SBStuff.
    >
    > --
    > Shane Stanley <sstanley...>
    > 'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>

    Yes, I suppose so. On the other hand I have never seen/never tried to call AppleScript from Cocoa in AppleScriptObjC terms - if this wording makes sense at all. I don't remember reading about this in your book, which focuses of course on accessing Cocoa from AppleScript.

    ___ Peter Hartmann ________

    mailto:<hphartmann...>
  • On 26/05/2012, at 10:25 PM, Peter wrote:

    > On the other hand I have never seen/never tried to call AppleScript from Cocoa in AppleScriptObjC terms - if this wording makes sense at all. I don't remember reading about this in your book, which focuses of course on accessing Cocoa from AppleScript.

    It's not in the book, but it's pretty simple. You just need to stick to passing objects of the main classes (NSString, NSArray, NSNumber, NSDictionary, NSData) and coercing them in the receiving handler. So in this case you might have an AS "class" with a handler like this:

    on selectItemsInFinder_(arrayOfPaths)
    set arrayOfPaths to arrayOfPaths as list -- coerce from pseudo-pointer to AS object
    set fileList to {}
    repeat with aPath in arrayOfPaths
      set end of fileList to aPath as POSIX file
    end repeat
    tell application "Finder" to select fileList
    end selectItemsInFinder_

    And you can call it as either a class or instance method:

    NSArray *array = *paths*
    [ASClassInstance selectItemsInFinder:array];

    or:

    [[ASClassName alloc] init] selectItemsInFinder:array];

    or:

    [ASClassName selectItemsInFinder:array];

    --
    Shane Stanley <sstanley...>
    'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>
  • Thank you! You might want to add this to an appendix of your book some time.

    Am 26.05.2012 um 14:58 schrieb Shane Stanley:

    > On 26/05/2012, at 10:25 PM, Peter wrote:
    >
    >> On the other hand I have never seen/never tried to call AppleScript from Cocoa in AppleScriptObjC terms - if this wording makes sense at all. I don't remember reading about this in your book, which focuses of course on accessing Cocoa from AppleScript.
    >
    > It's not in the book, but it's pretty simple. You just need to stick to passing objects of the main classes (NSString, NSArray, NSNumber, NSDictionary, NSData) and coercing them in the receiving handler. So in this case you might have an AS "class" with a handler like this:

    Just for clarification:

    This AS handler would then live in a .applescript file in my project wrapped in

    script ASClassInstance
    > on selectItemsInFinder_(arrayOfPaths)
    > set arrayOfPaths to arrayOfPaths as list -- coerce from pseudo-pointer to AS object
    > set fileList to {}
    > repeat with aPath in arrayOfPaths
    > set end of fileList to aPath as POSIX file
    > end repeat
    > tell application "Finder" to select fileList
    > end selectItemsInFinder_
    end script

    > And you can call it as either a class or instance method:
    >
    > NSArray *array = *paths*
    > [ASClassInstance selectItemsInFinder:array];
    >
    > or:
    >
    > [[ASClassName alloc] init] selectItemsInFinder:array];
    >
    > or:
    >
    > [ASClassName selectItemsInFinder:array];

    And on of the above calls would live in a .m file containing

    #import <AppleScriptObjC/AppleScriptObjC.h> //no need to put this in main.m, I guess

    in a project with the AppleScriptObjC linked in.

    Is this correct? Does this require any special build settings?

    Thanks!

    ___ Peter Hartmann ________

    mailto:<hphartmann...>
  • On Fri, May 25, 2012 at 1:56 AM, Peter <magnard...> wrote:
    > I'd like to reveal/select multiple items in the Finder.
    > NSWorkspace only handles single files as in
    >
    >            [[NSWorkspace sharedWorkspace] selectFile:currentFilePath
    >                             inFileViewerRootedAtPath:currentFilePath];
    >
    > I searched Google and tried to pick up every scrap of information on the Scripting Bridge but I could not find anything about sending a LIST of paths.

    If you want an example of some very dark magic, here's some code that
    constructs an Apple Event and sends it to the Finder:

    https://uofi.box.com/s/91ef71641b6eeffdfc29

    I started out with MoreAppleEvents sample code, ripped out everything
    that didn't make it to 64bit (bunch of FSSpec stuff and IconSuites),
    then wrote a MoreFESetSelection() function because MoreAppleEvents
    didn't think to include one.

    It sends a kAESetData event to Finder for the pSelection property. It
    passes the files in as a list of FSRefs.
  • On 27/05/2012, at 12:30 AM, Peter wrote:

    > Just for clarification:
    >
    > This AS handler would then live in a .applescript file in my project wrapped in
    >
    > script ASClassInstance

    Yes.

    > And on of the above calls would live in a .m file containing
    >
    > #import <AppleScriptObjC/AppleScriptObjC.h> //no need to put this in main.m, I guess

    No. The #import line needs to go wherever the [[NSBundle mainBundle] loadAppleScriptObjectiveCScripts] is, and main.m is the logical place. You might want to add an informal protocol for the method to the calling .m file to keep the compiler happy.

    > Does this require any special build settings?

    You probably want to change the OSA Compile setting for Save as Execute-Only to YES.

    --
    Shane Stanley <sstanley...>
    'AppleScriptObjC Explored' <www.macosxautomation.com/applescript/apps/>
  • On May 26, 2012, at 4:41 AM, Peter wrote:

    > thank you very much for your enlightening and in-depth explanation!

    You're welcome.

    > With the old API I could (and still do) put a list of path strings with empty elements on the pasteboard, e.g. four paths, the third one empty as in
    >
    > /path1/item1
    > /path2/item1
    >
    > /path2/item2
    >
    > but since the new API moved to NSURLs I don't see a way to accomplish this. I could not find something like an empty NSURL. I use this for copying data from a table area to another table or table area, meaning the empty element is a valid piece of data. Any ideas?

    I'm not certain.  You can try putting an NSPasteboardItem to which you haven't added any data in the list of items.  You can try adding some other type of data, perhaps a custom type which indicates to your app that there's no data.  You can put a different kind of NSURL, rather than a file URL, perhaps with a custom scheme meaningful only to your app.  Etc.

    The main thing is to think of the pasteboard contents as multiple items, each with its own types/representations, which can be (but doesn't have to be) different from all of the other items.

    Regards,
    Ken
previous month may 2012 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today