Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make Cocoa application respond to simple AppleScript command

I am trying to add a trivial AppleScript support to a Cocoa application. The application performs a check periodically and I just want to be able to tell it to perform it on demand.

I am trying to follow the SimpleScriptingVerbs Apple example.

I have subclassed NSScriptCommand as follows:

Header:

#import <Cocoa/Cocoa.h>

@interface rdrNotifierUpdateCommand : NSScriptCommand {

}
-(id)performDefaultImplementation;
@end

Implementation:

#import "rdrNotifierUpdateCommand.h"
#import "rdrNotifierAppDelegate.h"

@implementation rdrNotifierUpdateCommand

-(id)performDefaultImplementation {
  NSLog(@"Works at last");
  [((rdrNotifierAppDelegate *)[[NSApplication sharedApplication] delegate])
   checkForNewItems];  // This just fires the timer
  return nil;
}
@end

My .sdef file goes as follows (and the problem seems to be there, but I cannot find it):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="Dictionary" xmlns:xi="http://www.w3.org/2003/XInclude">
    <xi:include href="file:///System/Library/ScriptingDefinitions/CocoaStandard.sdef" xpointer="xpointer(/dictionary/suite)"/>
    <suite name="rdrNotifier Suite" code="rdrN" description="rdrNotifier application specific scripting facilities.">
        <command name="do update" code="rdrNUpdt" description="Check for new items">
            <cocoa class="rdrNotifierUpdateCommand"/>
        </command>
    </suite>
</dictionary>

The Info.plist is set up appropriately.

But, when I try to run the following script in AppleScript editor:

tell application "rdrNotifier"
    do update
end tell

I receive an error about variable "update" not being defined.

I can open the dictionary for my application from AppleScript Editor (i.e. it is successfully registered).

Edit: Found a solution

The problem was indeed in the sdef file: I was not specifying that the application can reply to the command. My final definition goes as follows (Obj-C code unchanged):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dictionary SYSTEM "file://localhost/System/Library/DTDs/sdef.dtd">
<dictionary title="Dictionary" xmlns:xi="http://www.w3.org/2003/XInclude">
  <!-- I have removed the standard suite as the application does not open, print... -->
  <suite name="rdrNotifier Suite" code="rdrN" description="rdrNotifier application specific scripting facilities.">
    <command name="do update" code="rdrNUpdt" description="Check for new items">
      <cocoa class="rdrNotifierUpdateCommand"/>
    </command>
    <class name="application" code="Capp">
      <cocoa class="NSApplication"/>
      <responds-to name="do update">
        <!-- Note you need to specify a method here,
             although it is blank -->
        <cocoa method=""/>
      </responds-to>
    </class>
  </suite>
</dictionary>

Any improvements/tips/criticisms are still welcome.

like image 487
Raúl Pedroche Avatar asked May 14 '11 19:05

Raúl Pedroche


1 Answers

Thanks for making the effort of adding applescript support to your app! Just a quick observation / criticism: When constructing terminology, by all means include spaces, but if that terminology takes the form of 'verb noun' (like 'do update') appleScripters will be irritated if the noun 'update' is not a properly modelled object, and if 'do' is not a proper command.

I would argue that 'do' is a poor choice for a command name, because it is very vague. What's wrong with just using 'update' as the command? (i.e. treat it as a verb).

This issue is treated in some detail by Apple's own technote 2106 (currently here), which you definitely should read and digest if you hope to please your AppleScripting user community.

Apple themselves are not beyond stupid terminology choices such as updatePodcast and updateAllPodcasts (in iTunes). These are stupid choices because (according to tn2106) they contain no spaces, and because the better choice would be to have a proper podcast class and then have an update command which could be used on an individual podcast, all podcasts, or a particular chosen set of podcasts.

like image 128
brennanyoung Avatar answered Nov 30 '22 02:11

brennanyoung