aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorMax <post@wickenrode.com>2015-07-05 01:03:33 +0200
committerMax <post@wickenrode.com>2015-07-05 01:03:33 +0200
commit1b0938196c23225917b72ea172605adf33d6843d (patch)
tree91beedc7f02b8370655208d68dfb530678523685 /Source
parentc124db7ac403cdd92cc2c26e572f37f7b7d4ae75 (diff)
downloadsequelpro-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.h2
-rw-r--r--Source/SPGotoDatabaseController.m108
-rw-r--r--Source/SPStringAdditions.h4
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.