Revision: 22629
http://sourceforge.net/p/bibdesk/svn/22629
Author: hofman
Date: 2018-09-18 12:29:37 +0000 (Tue, 18 Sep 2018)
Log Message:
-----------
Use "any" type for add and remove script commands, evaluate the app event
descriptors ourselves
Modified Paths:
--------------
trunk/bibdesk/BDSKAddCommand.m
trunk/bibdesk/BDSKAppController.m
trunk/bibdesk/BDSKRemoveCommand.m
trunk/bibdesk/Scripting/BibDesk.sdef
Modified: trunk/bibdesk/BDSKAddCommand.m
===================================================================
--- trunk/bibdesk/BDSKAddCommand.m 2018-09-18 06:30:38 UTC (rev 22628)
+++ trunk/bibdesk/BDSKAddCommand.m 2018-09-18 12:29:37 UTC (rev 22629)
@@ -49,112 +49,94 @@
- (id)performDefaultImplementation {
// get the actual objects to insert
id directParameter = [self directParameter];
- id receiver = [self evaluatedReceivers];
- NSArray *insertionObjects = nil;
- NSMutableArray *returnValue = nil;
- BOOL isArray;
+ // for "any" type, directParameter is an NSAppleEventDescriptor and
evaulatedReceiver is nil
+ NSArray *insertionObjects = [directParameter objCObjectValue];
- if ([directParameter isKindOfClass:[NSAppleEventDescriptor class]] &&
[directParameter descriptorType] == typeAEList) {
- NSMutableArray *array = [NSMutableArray array];
- NSUInteger i, iMax = [directParameter numberOfItems];
- for (i = 1; i <= iMax; i++)
- [array addObject:[directParameter descriptorAtIndex:i]];
- directParameter = array;
+ // evaluate object specifiers
+ if ([insertionObjects
respondsToSelector:@selector(objectsByEvaluatingSpecifier)] ||
+ ([insertionObjects isKindOfClass:[NSArray class]] &&
+ NSNotFound == [insertionObjects indexOfObjectPassingTest:^BOOL(id
obj, NSUInteger idx, BOOL *stop){ return NO == [obj
respondsToSelector:@selector(objectsByEvaluatingSpecifier)]; }])) {
+ insertionObjects = [insertionObjects
valueForKey:@"objectsByEvaluatingSpecifier"];
}
- isArray = [directParameter isKindOfClass:[NSArray class]] || [receiver
isKindOfClass:[NSArray class]];
-
- if (directParameter && [directParameter isKindOfClass:[NSArray class]] ==
NO)
- directParameter = [NSArray arrayWithObjects:directParameter, nil];
-
- if (NSNotFound == [directParameter indexOfObjectPassingTest:^BOOL(id obj,
NSUInteger idx, BOOL *stop){ return NO == [obj
respondsToSelector:@selector(keyClassDescription)]; }]) {
- insertionObjects = [receiver isKindOfClass:[NSArray class]] ? receiver
: [NSArray arrayWithObjects:receiver, nil];
- } else if (NSNotFound == [directParameter
indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ return NO
== [obj isKindOfClass:[NSAppleEventDescriptor class]]; }]) {
- insertionObjects = [directParameter valueForKey:@"objCObjectValue"];
- }
-
if (insertionObjects == nil) {
[self setScriptErrorNumber:NSArgumentsWrongScriptError];
[self setScriptErrorString:NSLocalizedString(@"Invalid or missing
objects to add", @"Error description")];
} else {
- // get the location to insert
- id locationSpecifier = [[self arguments] objectForKey:@"ToLocation"];
- id insertionContainer = nil;
- NSString *insertionKey = nil;
- NSInteger insertionIndex = -1;
- NSScriptClassDescription *containerClassDescription = nil;
- NSArray *classDescriptions = [insertionObjects
valueForKey:@"scriptClassDescription"];
- NSScriptClassDescription *insertionClassDescription =
[classDescriptions containsObject:[NSNull null]] ? nil :
[NSScriptClassDescription commonAncestorForClassDescriptions:classDescriptions];
+ // make sure we have an (unnested) array
+ if ([insertionObjects isKindOfClass:[NSArray class]] == NO)
+ insertionObjects = [NSArray arrayWithObjects:insertionObjects,
nil];
+ else if (NSNotFound == [insertionObjects
indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ return NO
== [obj isKindOfClass:[NSArray class]]; }])
+ insertionObjects = [insertionObjects
valueForKeyPath:@"@unionOfArrays.self"];
- if ([locationSpecifier isKindOfClass:[NSPositionalSpecifier class]]) {
- [locationSpecifier
setInsertionClassDescription:insertionClassDescription];
- insertionContainer = [locationSpecifier insertionContainer];
- insertionKey = [locationSpecifier insertionKey];
- insertionIndex = [locationSpecifier insertionIndex];
- } else if ([locationSpecifier isKindOfClass:[NSPropertySpecifier
class]]) {
- insertionContainer = [[locationSpecifier containerSpecifier]
objectsByEvaluatingSpecifier];
- insertionKey = [locationSpecifier key];
- } else if (locationSpecifier) {
- insertionContainer = [locationSpecifier
objectsByEvaluatingSpecifier];
- // make sure this is a valid object, so not something like a range
specifier
- if ([insertionContainer
respondsToSelector:@selector(objectSpecifier)] == NO)
- insertionContainer = nil;
- containerClassDescription = [insertionContainer
scriptClassDescription];
- if ([classDescriptions containsObject:[NSNull null]] == NO) {
- for (NSString *key in [containerClassDescription
toManyRelationshipKeys]) {
- NSScriptClassDescription *keyClassDescription =
[containerClassDescription classDescriptionForKey:key];
- if ([insertionClassDescription
isKindOfClassDescription:keyClassDescription] &&
- [containerClassDescription
isLocationRequiredToCreateForKey:key] == NO) {
- insertionKey = key;
- break;
+ if ([insertionObjects count]) {
+
+ // get the location to insert
+ id locationSpecifier = [[self arguments]
objectForKey:@"ToLocation"];
+ id insertionContainer = nil;
+ NSString *insertionKey = nil;
+ NSInteger insertionIndex = -1;
+ NSScriptClassDescription *containerClassDescription = nil;
+ NSArray *classDescriptions = [insertionObjects
valueForKey:@"scriptClassDescription"];
+ NSScriptClassDescription *insertionClassDescription =
[classDescriptions containsObject:[NSNull null]] ? nil :
[NSScriptClassDescription commonAncestorForClassDescriptions:classDescriptions];
+
+ if ([locationSpecifier isKindOfClass:[NSPositionalSpecifier
class]]) {
+ [locationSpecifier
setInsertionClassDescription:insertionClassDescription];
+ insertionContainer = [locationSpecifier insertionContainer];
+ insertionKey = [locationSpecifier insertionKey];
+ insertionIndex = [locationSpecifier insertionIndex];
+ } else if ([locationSpecifier isKindOfClass:[NSPropertySpecifier
class]]) {
+ insertionContainer = [[locationSpecifier containerSpecifier]
objectsByEvaluatingSpecifier];
+ insertionKey = [locationSpecifier key];
+ } else if (locationSpecifier) {
+ insertionContainer = [locationSpecifier
objectsByEvaluatingSpecifier];
+ // make sure this is a valid object, so not something like a
range specifier
+ if ([insertionContainer
respondsToSelector:@selector(objectSpecifier)] == NO)
+ insertionContainer = nil;
+ containerClassDescription = [insertionContainer
scriptClassDescription];
+ if ([classDescriptions containsObject:[NSNull null]] == NO) {
+ for (NSString *key in [containerClassDescription
toManyRelationshipKeys]) {
+ NSScriptClassDescription *keyClassDescription =
[containerClassDescription classDescriptionForKey:key];
+ if ([insertionClassDescription
isKindOfClassDescription:keyClassDescription] &&
+ [containerClassDescription
isLocationRequiredToCreateForKey:key] == NO) {
+ insertionKey = key;
+ break;
+ }
}
}
}
- }
-
- // check if the insertion location is valid
- if (containerClassDescription == nil && insertionContainer)
- containerClassDescription = [insertionContainer
scriptClassDescription];
- if (insertionContainer == nil || insertionKey == nil ||
- [[containerClassDescription toManyRelationshipKeys]
containsObject:insertionKey] == NO) {
- [self setScriptErrorNumber:NSArgumentsWrongScriptError];
- [self setScriptErrorString:NSLocalizedString(@"Could
not find container to add to", @"Error description")];
- insertionObjects = nil;
- } else {
- // check if the inserted objects are valid for the insertion
container key
- NSScriptClassDescription *requiredClassDescription =
[containerClassDescription classDescriptionForKey:insertionKey];
- if ([insertionClassDescription
isKindOfClassDescription:requiredClassDescription] == NO ||
- (insertionIndex == -1 && [containerClassDescription
isLocationRequiredToCreateForKey:insertionKey])) {
+ // check if the insertion location is valid
+ if (containerClassDescription == nil && insertionContainer)
+ containerClassDescription = [insertionContainer
scriptClassDescription];
+ if (insertionContainer == nil || insertionKey == nil ||
+ [[containerClassDescription toManyRelationshipKeys]
containsObject:insertionKey] == NO) {
[self setScriptErrorNumber:NSArgumentsWrongScriptError];
- [self setScriptErrorString:NSLocalizedString(@"Invalid
container to add to", @"Error description")];
+ [self setScriptErrorString:NSLocalizedString(@"Could not find
container to add to", @"Error description")];
+ insertionObjects = nil;
} else {
- // insert using scripting KVC
- if (insertionIndex >= 0) {
- for (id obj in insertionObjects)
- [insertionContainer insertValue:obj
atIndex:insertionIndex++ inPropertyWithKey:insertionKey];
+ // check if the inserted objects are valid for the insertion
container key
+ NSScriptClassDescription *requiredClassDescription =
[containerClassDescription classDescriptionForKey:insertionKey];
+
+ if ([insertionClassDescription
isKindOfClassDescription:requiredClassDescription] == NO ||
+ (insertionIndex == -1 && [containerClassDescription
isLocationRequiredToCreateForKey:insertionKey])) {
+ [self setScriptErrorNumber:NSArgumentsWrongScriptError];
+ [self setScriptErrorString:NSLocalizedString(@"Invalid
container to add to", @"Error description")];
} else {
- for (id obj in insertionObjects)
- [insertionContainer insertValue:obj
inPropertyWithKey:insertionKey];
+ // insert using scripting KVC
+ if (insertionIndex >= 0) {
+ for (id obj in insertionObjects)
+ [insertionContainer insertValue:obj
atIndex:insertionIndex++ inPropertyWithKey:insertionKey];
+ } else {
+ for (id obj in insertionObjects)
+ [insertionContainer insertValue:obj
inPropertyWithKey:insertionKey];
+ }
}
-
- // get the return value, either by getting the objectSpecifier
or the AppleEventDescriptor
- returnValue = [NSMutableArray array];
- for (id obj in insertionObjects) {
- id returnObj = nil;
- if ([obj respondsToSelector:@selector(objectSpecifier)])
- returnObj = [obj objectSpecifier];
- if (returnObj == nil)
- returnObj = [obj aeDescriptorValue];
- if (returnObj)
- [returnValue addObject:returnObj];
- }
-
}
}
}
- return isArray ? returnValue : [returnValue firstObject];
+ return nil;
}
@end
Modified: trunk/bibdesk/BDSKAppController.m
===================================================================
--- trunk/bibdesk/BDSKAppController.m 2018-09-18 06:30:38 UTC (rev 22628)
+++ trunk/bibdesk/BDSKAppController.m 2018-09-18 12:29:37 UTC (rev 22629)
@@ -329,6 +329,11 @@
selector:@selector(fileURLWithAEDesc:)
forDescriptorTypes:typeFileURL, typeAlias,
typeFSRef, 'fss ', 'bmrk', nil];
+ // register NSScriptObjectSpecifier as conversion handler for specifier
type
+ [NSAppleEventDescriptor registerConversionHandler:[NSScriptObjectSpecifier
class]
+
selector:@selector(objectSpecifierWithDescriptor:)
+ forDescriptorTypes:typeObjectSpecifier,
nil];
+
// register URL handler
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self
andSelector:@selector(handleGetURLEvent:withReplyEvent:)
forEventClass:kInternetEventClass andEventID:kAEGetURL];
}
Modified: trunk/bibdesk/BDSKRemoveCommand.m
===================================================================
--- trunk/bibdesk/BDSKRemoveCommand.m 2018-09-18 06:30:38 UTC (rev 22628)
+++ trunk/bibdesk/BDSKRemoveCommand.m 2018-09-18 12:29:37 UTC (rev 22629)
@@ -39,6 +39,7 @@
#import "BDSKRemoveCommand.h"
#import "NSAppleEventDescriptor_BDSKExtensions.h"
#import "NSScriptClassDescription_BDSKExtensions.h"
+#import "KFASHandlerAdditions-TypeTranslation.h"
#import "NSObject_BDSKExtensions.h"
@@ -47,81 +48,80 @@
- (id)performDefaultImplementation {
// get the actual objects to remove
id directParameter = [self directParameter];
- id receiver = [self evaluatedReceivers];
- NSArray *removeObjects = nil;
+ // for "any" type, directParameter is an NSAppleEventDescriptor and
evaulatedReceiver is nil
+ NSArray *removeObjects = [directParameter objCObjectValue];
- if ([directParameter isKindOfClass:[NSAppleEventDescriptor class]] &&
[directParameter descriptorType] == typeAEList) {
- NSMutableArray *array = [NSMutableArray array];
- NSUInteger i, iMax = [directParameter numberOfItems];
- for (i = 1; i <= iMax; i++)
- [array addObject:[directParameter descriptorAtIndex:i]];
- directParameter = array;
+ // evaluate object specifiers
+ if ([removeObjects
respondsToSelector:@selector(objectsByEvaluatingSpecifier)] ||
+ ([removeObjects isKindOfClass:[NSArray class]] &&
+ NSNotFound == [removeObjects indexOfObjectPassingTest:^BOOL(id obj,
NSUInteger idx, BOOL *stop){ return NO == [obj
respondsToSelector:@selector(objectsByEvaluatingSpecifier)]; }])) {
+ removeObjects = [removeObjects
valueForKey:@"objectsByEvaluatingSpecifier"];
}
- if (directParameter && [directParameter isKindOfClass:[NSArray class]] ==
NO)
- directParameter = [NSArray arrayWithObjects:directParameter, nil];
-
- if (NSNotFound == [directParameter indexOfObjectPassingTest:^BOOL(id obj,
NSUInteger idx, BOOL *stop){ return NO == [obj
respondsToSelector:@selector(keyClassDescription)]; }]) {
- removeObjects = [receiver isKindOfClass:[NSArray class]] ? receiver :
[NSArray arrayWithObjects:receiver, nil];
- } else if (NSNotFound == [directParameter
indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ return NO
== [obj isKindOfClass:[NSAppleEventDescriptor class]]; }]) {
- removeObjects = [directParameter valueForKey:@"objCObjectValue"];
- }
-
if (removeObjects == nil) {
[self setScriptErrorNumber:NSArgumentsWrongScriptError];
[self setScriptErrorString:NSLocalizedString(@"Invalid or missing
objects to remove", @"Error description")];
} else {
- // get the container to remove from
- id containerSpecifier = [[self arguments]
objectForKey:@"FromContainer"];
- id removeContainer = nil;
- NSString *removeKey = nil;
- NSScriptClassDescription *containerClassDescription = nil;
- NSArray *classDescriptions = [removeObjects
valueForKey:@"scriptClassDescription"];
- NSScriptClassDescription *removeClassDescription = [classDescriptions
containsObject:[NSNull null]] ? nil : [NSScriptClassDescription
commonAncestorForClassDescriptions:classDescriptions];
+ // make sure we have an (unnested) array
+ if ([removeObjects isKindOfClass:[NSArray class]] == NO)
+ removeObjects = [NSArray arrayWithObjects:removeObjects, nil];
+ else if (NSNotFound == [removeObjects
indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ return NO
== [obj isKindOfClass:[NSArray class]]; }])
+ removeObjects = [removeObjects
valueForKeyPath:@"@unionOfArrays.self"];
- if (containerSpecifier == nil) {
- id obj = directParameter;
- if ([obj isKindOfClass:[NSArray class]])
- obj = [obj firstObject];
- if ([obj respondsToSelector:@selector(containerSpecifier)])
- containerSpecifier = [obj containerSpecifier];
- }
-
- if ([containerSpecifier isKindOfClass:[NSPropertySpecifier class]]) {
- removeContainer = [[containerSpecifier containerSpecifier]
objectsByEvaluatingSpecifier];
- removeKey = [containerSpecifier key];
- } else if (containerSpecifier) {
- removeContainer = [containerSpecifier
objectsByEvaluatingSpecifier];
- // make sure this is a valid object, so not something like a range
specifier
- if ([removeContainer
respondsToSelector:@selector(objectSpecifier)] == NO)
- removeContainer = nil;
- containerClassDescription = [removeContainer
scriptClassDescription];
- for (NSString *key in [containerClassDescription
toManyRelationshipKeys]) {
- NSScriptClassDescription *keyClassDescription =
[containerClassDescription classDescriptionForKey:key];
- if ([removeClassDescription
isKindOfClassDescription:keyClassDescription]) {
- removeKey = key;
- break;
+ if ([removeObjects count]) {
+
+ // get the container to remove from
+ id containerSpecifier = [[self arguments]
objectForKey:@"FromContainer"];
+ id removeContainer = nil;
+ NSString *removeKey = nil;
+ NSScriptClassDescription *containerClassDescription = nil;
+ NSArray *classDescriptions = [removeObjects
valueForKey:@"scriptClassDescription"];
+ NSScriptClassDescription *removeClassDescription =
[classDescriptions containsObject:[NSNull null]] ? nil :
[NSScriptClassDescription commonAncestorForClassDescriptions:classDescriptions];
+
+ if (containerSpecifier == nil) {
+ id obj = directParameter;
+ if ([obj isKindOfClass:[NSArray class]])
+ obj = [obj firstObject];
+ if ([obj respondsToSelector:@selector(containerSpecifier)])
+ containerSpecifier = [obj containerSpecifier];
+ }
+
+ if ([containerSpecifier isKindOfClass:[NSPropertySpecifier
class]]) {
+ removeContainer = [[containerSpecifier containerSpecifier]
objectsByEvaluatingSpecifier];
+ removeKey = [containerSpecifier key];
+ } else if (containerSpecifier) {
+ removeContainer = [containerSpecifier
objectsByEvaluatingSpecifier];
+ // make sure this is a valid object, so not something like a
range specifier
+ if ([removeContainer
respondsToSelector:@selector(objectSpecifier)] == NO)
+ removeContainer = nil;
+ containerClassDescription = [removeContainer
scriptClassDescription];
+ for (NSString *key in [containerClassDescription
toManyRelationshipKeys]) {
+ NSScriptClassDescription *keyClassDescription =
[containerClassDescription classDescriptionForKey:key];
+ if ([removeClassDescription
isKindOfClassDescription:keyClassDescription]) {
+ removeKey = key;
+ break;
+ }
}
}
- }
-
- // check if the remove location is valid
- if (containerClassDescription == nil && removeContainer)
- containerClassDescription = [removeContainer
scriptClassDescription];
- if (removeContainer == nil || removeKey == nil ||
- [[containerClassDescription toManyRelationshipKeys]
containsObject:removeKey] == NO) {
- [self setScriptErrorNumber:NSArgumentsWrongScriptError];
- [self setScriptErrorString:NSLocalizedString(@"Could
not find container to remove from", @"Error description")];
- } else {
- NSScriptClassDescription *requiredClassDescription =
[containerClassDescription classDescriptionForKey:removeKey];
- if ([removeClassDescription
isKindOfClassDescription:requiredClassDescription] == NO) {
+ // check if the remove location is valid
+ if (containerClassDescription == nil && removeContainer)
+ containerClassDescription = [removeContainer
scriptClassDescription];
+ if (removeContainer == nil || removeKey == nil ||
+ [[containerClassDescription toManyRelationshipKeys]
containsObject:removeKey] == NO) {
[self setScriptErrorNumber:NSArgumentsWrongScriptError];
- [self setScriptErrorString:NSLocalizedString(@"Invalid
container to remove from", @"Error description")];
+ [self setScriptErrorString:NSLocalizedString(@"Could not find
container to remove from", @"Error description")];
} else {
- // remove using KVC, I don't know how to use scripting KVC as
I don't know how to get the indexes in general
- [[removeContainer mutableArrayValueForKey:removeKey]
removeObjectsInArray:removeObjects];
+ NSScriptClassDescription *requiredClassDescription =
[containerClassDescription classDescriptionForKey:removeKey];
+
+ if ([removeClassDescription
isKindOfClassDescription:requiredClassDescription] == NO) {
+ [self setScriptErrorNumber:NSArgumentsWrongScriptError];
+ [self setScriptErrorString:NSLocalizedString(@"Invalid
container to remove from", @"Error description")];
+ } else {
+ // remove using KVC, I don't know how to use scripting KVC
as I don't know how to get the indexes in general
+ [[removeContainer mutableArrayValueForKey:removeKey]
removeObjectsInArray:removeObjects];
+ }
}
}
}
Modified: trunk/bibdesk/Scripting/BibDesk.sdef
===================================================================
--- trunk/bibdesk/Scripting/BibDesk.sdef 2018-09-18 06:30:38 UTC (rev
22628)
+++ trunk/bibdesk/Scripting/BibDesk.sdef 2018-09-18 12:29:37 UTC (rev
22629)
@@ -443,13 +443,7 @@
<command name="add" code="BDSKAdd "
description="Add items to a collection.">
<cocoa class="BDSKAddCommand"/>
- <direct-parameter
- description="the object(s) to add.">
- <type type="specifier"/>
- <type type="specifier" list="yes"/>
- <type type="any"/>
- <type type="any" list="yes"/>
- </direct-parameter>
+ <direct-parameter type="any" description="the object(s) to add.">
<parameter name="to" code="insh"
description="The container or location to add the item to.">
<cocoa key="ToLocation"/>
@@ -456,24 +450,12 @@
<type type="specifier"/>
<type type="location specifier"/>
</parameter>
- <result description="the added item">
- <type type="specifier"/>
- <type type="specifier" list="yes"/>
- <type type="any"/>
- <type type="any" list="yes"/>
- </result>
</command>
<command name="remove" code="BDSKRemv"
description="Remove items from a collection.">
<cocoa class="BDSKRemoveCommand"/>
- <direct-parameter
- description="the object(s) to remove.">
- <type type="specifier"/>
- <type type="specifier" list="yes"/>
- <type type="any"/>
- <type type="any" list="yes"/>
- </direct-parameter>
+ <direct-parameter type="any" description="the object(s) to
remove.">
<parameter name="from" code="from" optional="yes"
description="The container to remove the object(s) from.">
<cocoa key="FromContainer"/>
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit