diff options
author | Max <post@wickenrode.com> | 2015-07-05 01:03:33 +0200 |
---|---|---|
committer | Max <post@wickenrode.com> | 2015-07-05 01:03:33 +0200 |
commit | 1b0938196c23225917b72ea172605adf33d6843d (patch) | |
tree | 91beedc7f02b8370655208d68dfb530678523685 /Source | |
parent | c124db7ac403cdd92cc2c26e572f37f7b7d4ae75 (diff) | |
download | sequelpro-1b0938196c23225917b72ea172605adf33d6843d.tar.gz sequelpro-1b0938196c23225917b72ea172605adf33d6843d.tar.bz2 sequelpro-1b0938196c23225917b72ea172605adf33d6843d.zip |
Add the possibility to search for whole words in "Goto Database"
This is done by wrapping the search term in single or double quotes. re: #2165, #1857
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPGotoDatabaseController.h | 2 | ||||
-rw-r--r-- | Source/SPGotoDatabaseController.m | 108 | ||||
-rw-r--r-- | Source/SPStringAdditions.h | 4 |
3 files changed, 93 insertions, 21 deletions
diff --git a/Source/SPGotoDatabaseController.h b/Source/SPGotoDatabaseController.h index 3ae15d95..ac838eff 100644 --- a/Source/SPGotoDatabaseController.h +++ b/Source/SPGotoDatabaseController.h @@ -36,7 +36,7 @@ * keyboard-based navigation between databases. The dialog also enables * jumping to a database by C&P-ing its full name. */ -@interface SPGotoDatabaseController : NSWindowController <NSTableViewDataSource,NSControlTextEditingDelegate> +@interface SPGotoDatabaseController : NSWindowController <NSTableViewDataSource,NSControlTextEditingDelegate,NSUserInterfaceValidations> { IBOutlet NSSearchField *searchField; IBOutlet NSButton *okButton; diff --git a/Source/SPGotoDatabaseController.m b/Source/SPGotoDatabaseController.m index 23b43ee2..b48b77b7 100644 --- a/Source/SPGotoDatabaseController.m +++ b/Source/SPGotoDatabaseController.m @@ -47,7 +47,10 @@ - (IBAction)okClicked:(id)sender; - (IBAction)cancelClicked:(id)sender; - (IBAction)searchChanged:(id)sender; +- (IBAction)toggleWordSearch:(id)sender; +- (BOOL)qualifiesForWordSearch:(NSString *)s; +- (BOOL)qualifiesForWordSearch; //takes s from searchField @end @implementation SPGotoDatabaseController @@ -127,6 +130,26 @@ [okButton setEnabled:([databaseListView selectedRow] >= 0)]; } +- (IBAction)toggleWordSearch:(id)sender +{ + //if the search field is empty just add two " and put the caret in-between + if(![[searchField stringValue] length]) { + [searchField setStringValue:@"\"\""]; + [[searchField currentEditor] setSelectedRange:NSMakeRange(1, 0)]; + + } + else if (![self qualifiesForWordSearch]) { + [searchField setStringValue:[NSString stringWithFormat:@"\"%@\"",[searchField stringValue]]]; + //change the selection to be inside the quotes + [[searchField currentEditor] setSelectedRange:NSMakeRange(1, [[searchField stringValue] length]-2)]; + } + else { + NSString *str = [searchField stringValue]; + [searchField setStringValue:[str substringWithRange:NSMakeRange(1, [str length]-2)]]; + } + [self searchChanged:nil]; +} + #pragma mark - #pragma mark Public @@ -184,35 +207,73 @@ [NSNumber numberWithInt:NSUnderlineStyleSingle],NSUnderlineStyleAttributeName, nil]; - for (NSString *db in unfilteredList) { - - NSArray *matches = nil; - BOOL hasMatch = [db nonConsecutivelySearchString:filter matchingRanges:&matches]; - - if(!hasMatch) continue; + NSStringCompareOptions opts = NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch|NSWidthInsensitiveSearch; + + // interpret a quoted string as 'looking for exact submachtes only' + if([self qualifiesForWordSearch:filter]) { + //remove quotes for matching + filter = [filter substringWithRange:NSMakeRange(1, [filter length]-2)]; - // Should we check for exact match AND have not yet found one? - if (exactMatch && !*exactMatch) { - if([matches count] == 1) { - NSRange match = [(NSValue *)[matches objectAtIndex:0] rangeValue]; - if (match.location == 0 && match.length == [db length]) { + //look for matches + for (NSString *db in unfilteredList) { + NSRange matchRange = [db rangeOfString:filter options:opts]; + + if(matchRange.location == NSNotFound) continue; + + // Should we check for exact match AND have not yet found one? + if (exactMatch && !*exactMatch) { + if (matchRange.location == 0 && matchRange.length == [db length]) { *exactMatch = YES; } } + + NSMutableAttributedString *attrMatch = [[NSMutableAttributedString alloc] initWithString:db]; + [attrMatch setAttributes:attrs range:matchRange]; + [filteredList addObject:[attrMatch autorelease]]; } - - NSMutableAttributedString *attrMatch = [[NSMutableAttributedString alloc] initWithString:db]; - - for (NSValue *matchValue in matches) { - [attrMatch setAttributes:attrs range:[matchValue rangeValue]]; + } + // default to a per-character search + else { + for (NSString *db in unfilteredList) { + + NSArray *matches = nil; + BOOL hasMatch = [db nonConsecutivelySearchString:filter matchingRanges:&matches]; + + if(!hasMatch) continue; + + // Should we check for exact match AND have not yet found one? + if (exactMatch && !*exactMatch) { + if([matches count] == 1) { + NSRange match = [(NSValue *)[matches objectAtIndex:0] rangeValue]; + if (match.location == 0 && match.length == [db length]) { + *exactMatch = YES; + } + } + } + + NSMutableAttributedString *attrMatch = [[NSMutableAttributedString alloc] initWithString:db]; + + for (NSValue *matchValue in matches) { + [attrMatch setAttributes:attrs range:[matchValue rangeValue]]; + } + + [filteredList addObject:[attrMatch autorelease]]; } - - [filteredList addObject:[attrMatch autorelease]]; } [attrs release]; } +- (BOOL)qualifiesForWordSearch:(NSString *)s +{ + return (s && ([s length] > 1) && (([s hasPrefix:@"\""] && [s hasSuffix:@"\""]) || ([s hasPrefix:@"'"] && [s hasSuffix:@"'"]))); +} + +- (BOOL)qualifiesForWordSearch +{ + return [self qualifiesForWordSearch:[searchField stringValue]]; +} + #pragma mark - #pragma mark NSTableViewDataSource @@ -268,6 +329,17 @@ } #pragma mark - +#pragma mark NSUserInterfaceValidations + +- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem +{ + if([anItem action] == @selector(toggleWordSearch:)) { + [(NSMenuItem *)anItem setState:([self qualifiesForWordSearch]? NSOnState : NSOffState)]; + } + return YES; +} + +#pragma mark - - (void)dealloc { diff --git a/Source/SPStringAdditions.h b/Source/SPStringAdditions.h index 7c0bfb90..5f1c0e6d 100644 --- a/Source/SPStringAdditions.h +++ b/Source/SPStringAdditions.h @@ -86,12 +86,12 @@ static inline id NSMutableAttributedStringAttributeAtIndex(NSMutableAttributedSt * In regex-speak that would mean "abc" is matched as /a.*b.*c/ (not anchored). * This is a SEARCH function, NOT a MATCHING function! * Namely the following options will be applied when matching: - * NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch|NSDiacriticInsensitiveSearch + * NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch|NSWidthInsensitiveSearch * Additionaly this method might match even when it should not. * * @param other String to match against self * @param submatches Pass the pointer to a variable that will be set to an NSArray * - * of NSNumber *s of NSRanges. This will only be the case if + * of NSValue *s of NSRanges. This will only be the case if * the method also returns YES. The variable will not be modified * otherwise. * Pass NULL if you don't care for the ranges. |