Spotlight can do exact searches using quotation marks, IE %a"tom waits" will do a case insensitive search for all music by Tom Waits
parent
d6e7efd2c1
commit
70ae3cec1c
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
@interface NSComparisonPredicate (CogPredicate)
|
@interface NSComparisonPredicate (CogPredicate)
|
||||||
|
|
||||||
+ (NSPredicate *)predicateForMdKey:(NSString *)key withString:(NSString *)aString;
|
+ (NSPredicate*)predicateForMdKey:(NSString*)key
|
||||||
|
withString:(NSString*)aString
|
||||||
|
exactString:(BOOL)exactString;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -14,12 +14,17 @@ static const unsigned OPTIONS = (NSCaseInsensitivePredicateOption|
|
||||||
|
|
||||||
@implementation NSComparisonPredicate (CogPredicate)
|
@implementation NSComparisonPredicate (CogPredicate)
|
||||||
|
|
||||||
+ (NSPredicate *)predicateForMdKey:(NSString *)key withString:(NSString *)aString
|
+ (NSPredicate*)predicateForMdKey:(NSString *)key
|
||||||
|
withString:(NSString *)aString
|
||||||
|
exactString:(BOOL)exactString
|
||||||
{
|
{
|
||||||
NSString * likeString = [NSString stringWithFormat:@"*%@*", aString];
|
// We don't want an exact string, so wrap it in wildcards
|
||||||
|
if(!exactString)
|
||||||
|
aString = [NSString stringWithFormat:@"*%@*", aString];
|
||||||
|
|
||||||
return [NSComparisonPredicate
|
return [NSComparisonPredicate
|
||||||
predicateWithLeftExpression:[NSExpression expressionForKeyPath:key]
|
predicateWithLeftExpression:[NSExpression expressionForKeyPath:key]
|
||||||
rightExpression:[NSExpression expressionForConstantValue:likeString]
|
rightExpression:[NSExpression expressionForConstantValue:aString]
|
||||||
modifier:NSDirectPredicateModifier
|
modifier:NSDirectPredicateModifier
|
||||||
type:NSLikePredicateOperatorType
|
type:NSLikePredicateOperatorType
|
||||||
options:OPTIONS];
|
options:OPTIONS];
|
||||||
|
|
|
@ -81,49 +81,95 @@ static NSPredicate * musicOnlyPredicate = nil;
|
||||||
NSMutableArray *subpredicates = [NSMutableArray arrayWithCapacity:10];
|
NSMutableArray *subpredicates = [NSMutableArray arrayWithCapacity:10];
|
||||||
|
|
||||||
NSScanner *scanner = [NSScanner scannerWithString:self.searchString];
|
NSScanner *scanner = [NSScanner scannerWithString:self.searchString];
|
||||||
|
BOOL exactString;
|
||||||
|
NSString * scannedString;
|
||||||
|
NSMutableString * parsingString;
|
||||||
while (![scanner isAtEnd])
|
while (![scanner isAtEnd])
|
||||||
{
|
{
|
||||||
NSString *scannedString;
|
exactString = NO;
|
||||||
if ([scanner scanUpToString:@" " intoString:&scannedString])
|
if ([scanner scanUpToString:@" " intoString:&scannedString])
|
||||||
{
|
{
|
||||||
if ([scannedString length] < MINIMUM_SEARCH_STRING_LENGTH)
|
if ([scannedString length] < MINIMUM_SEARCH_STRING_LENGTH)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ([scannedString characterAtIndex:0] == '%')
|
// We use NSMutableString because this string will get abused a bit
|
||||||
|
// It potentially could be reading the entire search string
|
||||||
|
|
||||||
|
parsingString = [NSMutableString stringWithCapacity: [self.searchString length]];
|
||||||
|
[parsingString setString: scannedString];
|
||||||
|
|
||||||
|
|
||||||
|
if ([parsingString characterAtIndex:0] == '%')
|
||||||
{
|
{
|
||||||
if ([scannedString length] < (MINIMUM_SEARCH_STRING_LENGTH + 2))
|
if ([parsingString length] < (MINIMUM_SEARCH_STRING_LENGTH + 2))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if ([parsingString characterAtIndex:2] == '\"')
|
||||||
|
{
|
||||||
|
exactString = YES;
|
||||||
|
// If the string does not end in a quotation mark and we're not at the end,
|
||||||
|
// scan until we find one.
|
||||||
|
// Allows strings within quotation marks to include spaces
|
||||||
|
if ([parsingString characterAtIndex:([parsingString length] - 1)] != '\"' &&
|
||||||
|
![scanner isAtEnd])
|
||||||
|
{
|
||||||
|
NSString *restOfString;
|
||||||
|
[scanner scanUpToString:@"\"" intoString:&restOfString];
|
||||||
|
[parsingString appendFormat:@" %@", restOfString];
|
||||||
|
}
|
||||||
|
else if ([parsingString characterAtIndex:([parsingString length] - 1)] == '\"')
|
||||||
|
{
|
||||||
|
// pick off the quotation mark at the end
|
||||||
|
[parsingString deleteCharactersInRange:
|
||||||
|
NSMakeRange([parsingString length] - 1, 1)];
|
||||||
|
|
||||||
|
}
|
||||||
|
// eliminate beginning quotation mark
|
||||||
|
[parsingString deleteCharactersInRange: NSMakeRange(2, 1)];
|
||||||
|
}
|
||||||
|
|
||||||
// Search for artist
|
// Search for artist
|
||||||
if([scannedString characterAtIndex:1] == 'a')
|
if([parsingString characterAtIndex:1] == 'a')
|
||||||
{
|
{
|
||||||
[subpredicates addObject:
|
[subpredicates addObject:
|
||||||
[NSComparisonPredicate predicateForMdKey:@"kMDItemAuthors"
|
[NSComparisonPredicate predicateForMdKey:@"kMDItemAuthors"
|
||||||
withString:[scannedString substringFromIndex:2]]];
|
withString:[parsingString substringFromIndex:2]
|
||||||
|
exactString:exactString]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for album
|
// Search for album
|
||||||
if([scannedString characterAtIndex:1] == 'l')
|
if([parsingString characterAtIndex:1] == 'l')
|
||||||
{
|
{
|
||||||
[subpredicates addObject:
|
[subpredicates addObject:
|
||||||
[NSComparisonPredicate predicateForMdKey:@"kMDItemAlbum"
|
[NSComparisonPredicate predicateForMdKey:@"kMDItemAlbum"
|
||||||
withString:[scannedString substringFromIndex:2]]];
|
withString:[parsingString substringFromIndex:2]
|
||||||
|
exactString:exactString]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for title
|
// Search for title
|
||||||
if([scannedString characterAtIndex:1] == 't')
|
if([parsingString characterAtIndex:1] == 't')
|
||||||
{
|
{
|
||||||
[subpredicates addObject:
|
[subpredicates addObject:
|
||||||
[NSComparisonPredicate predicateForMdKey:@"kMDItemTitle"
|
[NSComparisonPredicate predicateForMdKey:@"kMDItemTitle"
|
||||||
withString:[scannedString substringFromIndex:2]]];
|
withString:[parsingString substringFromIndex:2]
|
||||||
|
exactString:exactString]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for genre
|
||||||
|
if([parsingString characterAtIndex:1] == 'g')
|
||||||
|
{
|
||||||
|
[subpredicates addObject:
|
||||||
|
[NSComparisonPredicate predicateForMdKey:@"kMDItemMusicalGenre"
|
||||||
|
withString:[parsingString substringFromIndex:2]
|
||||||
|
exactString:exactString]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[subpredicates addObject:
|
[subpredicates addObject:
|
||||||
[NSComparisonPredicate predicateForMdKey:@"*"
|
[NSComparisonPredicate predicateForMdKey:@"*"
|
||||||
withString:scannedString]];
|
withString:parsingString
|
||||||
|
exactString:exactString]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue