Created
July 5, 2015 14:46
-
-
Save robjwells/9d1480e4b7a1a8312eca to your computer and use it in GitHub Desktop.
NSAppleScript category to make calling AppleScript handlers (functions) easier
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSAppleScript+RunHandler.h | |
// astest | |
// | |
// Created by Rob Wells on 30/01/2014. | |
// Copyright (c) 2014 Rob Wells. All rights reserved. | |
// | |
#ifndef kASAppleScriptSuite | |
#define kASAppleScriptSuite 'ascr' | |
#endif | |
#ifndef kASSubroutineEvent | |
#define kASSubroutineEvent 'psbr' | |
#endif | |
#ifndef keyASSubroutineName | |
#define keyASSubroutineName 'snam' | |
#endif | |
#import <Foundation/Foundation.h> | |
@interface NSAppleScript (RunHandler) | |
- (id)fetchObjectFromDescriptor:(NSAppleEventDescriptor *)descriptor; | |
- (NSAppleEventDescriptor *)makeParameters:(NSArray *)paramArray; | |
- (NSAppleEventDescriptor *)callHandler:(NSString *)handlerName | |
withParameters:(NSAppleEventDescriptor *)parameters; | |
- (id)getResultFromHandler:(NSString *)handlerName | |
withParameters:(NSAppleEventDescriptor *)parameters; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSAppleScript+RunHandler.m | |
// astest | |
// | |
// Created by Rob Wells on 30/01/2014. | |
// Copyright (c) 2014 Rob Wells. All rights reserved. | |
// | |
#import "NSAppleScript+RunHandler.h" | |
@implementation NSAppleScript (RunHandler) | |
- (NSAppleEventDescriptor *)makeParameters:(NSArray *)paramArray { | |
// Create list of parameters | |
NSAppleEventDescriptor *paramsDescriptor = [NSAppleEventDescriptor listDescriptor]; | |
// Loop through paramArray, turning the objects into descriptors | |
int i; | |
for (i = 0; i < paramArray.count; i++) { | |
id parameter = paramArray[i]; | |
if ([parameter isKindOfClass:[NSAppleEventDescriptor class]]) { | |
// Already a descriptor, add it as is | |
[paramsDescriptor insertDescriptor:parameter atIndex:i + 1]; | |
} else if ([parameter isKindOfClass:[NSString class]]) { | |
// Create a string descriptor | |
[paramsDescriptor | |
insertDescriptor:[NSAppleEventDescriptor | |
descriptorWithString:parameter] | |
atIndex:i + 1]; | |
} else if ([parameter respondsToSelector:@selector(intValue)]) { | |
// Create descriptor with number's int value | |
[paramsDescriptor | |
insertDescriptor:[NSAppleEventDescriptor | |
descriptorWithInt32:[parameter intValue]] | |
atIndex:i + 1]; | |
} else if ([parameter isKindOfClass:[NSArray class]]) { | |
// Create a list descriptor from an NSArray | |
NSAppleEventDescriptor *arrayParam = [self makeParameters:parameter]; | |
[paramsDescriptor insertDescriptor:arrayParam | |
atIndex:i + 1]; | |
} else { | |
return nil; | |
} | |
} | |
return paramsDescriptor; | |
} | |
- (NSAppleEventDescriptor *)callHandler:(NSString *)handlerName | |
withParameters:(NSAppleEventDescriptor *)parameters { | |
// Create the AppleEvent target | |
ProcessSerialNumber psn = {0, kCurrentProcess}; | |
NSAppleEventDescriptor *target = [NSAppleEventDescriptor | |
descriptorWithDescriptorType:typeProcessSerialNumber | |
bytes:&psn | |
length:sizeof(ProcessSerialNumber)]; | |
// Create descriptor with handler to call | |
// Routine name must be lowercase | |
NSAppleEventDescriptor *handler = [NSAppleEventDescriptor | |
descriptorWithString:[handlerName lowercaseString]]; | |
// Create the event for an AppleScript subroutine, | |
// set the method name and the list of parameters | |
NSAppleEventDescriptor *event = [NSAppleEventDescriptor | |
appleEventWithEventClass:kASAppleScriptSuite | |
eventID:kASSubroutineEvent | |
targetDescriptor:target | |
returnID:kAutoGenerateReturnID | |
transactionID:kAnyTransactionID]; | |
[event setParamDescriptor:handler forKeyword:keyASSubroutineName]; | |
if (parameters) { | |
[event setParamDescriptor:parameters forKeyword:keyDirectObject]; | |
} | |
// Call the event in AppleScript | |
NSDictionary *errorDict; | |
NSAppleEventDescriptor *returnedDescriptor = [self executeAppleEvent:event | |
error:&errorDict]; | |
if (!returnedDescriptor) { | |
NSLog(@"%@: %@", handlerName, errorDict[NSAppleScriptErrorMessage]); | |
} | |
return returnedDescriptor; | |
} | |
- (id)getResultFromHandler:(NSString *)handlerName | |
withParameters:(NSAppleEventDescriptor *)parameters { | |
NSAppleEventDescriptor *rawResult = [self callHandler:handlerName | |
withParameters:parameters]; | |
return [self fetchObjectFromDescriptor:rawResult]; | |
} | |
- (id)fetchObjectFromDescriptor:(NSAppleEventDescriptor *)descriptor { | |
NSString *returnType = NSFileTypeForHFSTypeCode([descriptor descriptorType]); | |
if ([returnType isEqualToString:@"'utxt'"]) { | |
// Returned data is a string | |
return [descriptor stringValue]; | |
} else if ([returnType isEqualToString:@"'long'"]) { | |
// Integer | |
return [NSNumber numberWithInt:[descriptor int32Value]]; | |
} else if ([returnType isEqualToString:@"'doub'"]) { | |
// Floating-point number | |
CGFloat result; | |
[[descriptor data] getBytes:&result length:[descriptor data].length]; | |
return [NSNumber numberWithFloat:result]; | |
} else if ([returnType isEqualToString:@"'list'"]) { | |
// List (array) - note AppleScript is 1-based | |
NSMutableArray *resultArray = [[NSMutableArray alloc] init]; | |
NSInteger i; | |
for (i = 1; i <= [descriptor numberOfItems]; i++) { | |
[resultArray addObject: | |
[self fetchObjectFromDescriptor:[descriptor descriptorAtIndex:i]]]; | |
} | |
return resultArray; | |
} else if ([returnType isEqualToString:@"'reco'"]) { | |
// Record (dictionary) | |
// Stored as a list in the descriptor's internal array of returned | |
// objects, in the form [key, value, key, value…] | |
NSArray *recordAsArray = [self fetchObjectFromDescriptor: | |
[descriptor descriptorAtIndex:1]]; | |
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; | |
NSInteger i; | |
for (i = 0; i < recordAsArray.count; i += 2) { | |
[dict setObject:recordAsArray[i + 1] forKey:recordAsArray[i]]; | |
} | |
return dict; | |
} | |
return [NSNull null]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment