From bc01bc7bcfe8b332ffa638c0f89adb8f2e5f748a Mon Sep 17 00:00:00 2001 From: Bibiko Date: Thu, 21 Jan 2010 10:15:31 +0000 Subject: =?UTF-8?q?=E2=80=A2=20completion=20-=20CTRL+ESC=20invokes=20the?= =?UTF-8?q?=20fuzzy=20search=20completion;=20eg:=20i=5Fs.pcss.=20=20will?= =?UTF-8?q?=20show=20all=20fields=20from=20`information=5Fschema`.`PROCESS?= =?UTF-8?q?LIST`.=20if=20no=20other=20matches=20are=20found;=20the=20searc?= =?UTF-8?q?h=20is=20a=20regexp=20".*=3Fi.*=3F=5F.*=3Fs.*=3F\.=20=E2=80=A6"?= =?UTF-8?q?=20etc.=20by=20using=20RegexKitLite=20which=20is=20much=20more?= =?UTF-8?q?=20faster=20than=20NSPredicate=20and=20can=20handle=20long=20re?= =?UTF-8?q?gexps=20-=20improved=20type=20display:=20if=20a=20type=20defini?= =?UTF-8?q?tion=20contains=20a=20,=20split=20it=20to=20avoid=20splitting?= =?UTF-8?q?=20of=20the=20tokenFields=20-=20while=20insertion=20of=20an=20i?= =?UTF-8?q?tem=20and=20holding=20down=20the=20CTRL=20key=20the=20list=20ke?= =?UTF-8?q?eps=20open=20to=20allow=20to=20insert=20more=20suggestions=20se?= =?UTF-8?q?parated=20by=20",=20"=20from=20the=20current=20list=20(very=20u?= =?UTF-8?q?seful=20if=20one=20wants=20to=20insert=20only=20selected=20fiel?= =?UTF-8?q?ds=20from=20a=20table)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/CMTextView.m | 13 ++--- Source/SPNarrowDownCompletion.h | 1 + Source/SPNarrowDownCompletion.m | 106 +++++++++++++++++++++++++++------------- 3 files changed, 79 insertions(+), 41 deletions(-) (limited to 'Source') diff --git a/Source/CMTextView.m b/Source/CMTextView.m index 1cceac97..7378253a 100644 --- a/Source/CMTextView.m +++ b/Source/CMTextView.m @@ -304,7 +304,9 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) for(id field in sortedFields) { if(![field hasPrefix:@" "]) { NSString *typ = [theTable objectForKey:field]; - if(typ && [typ hasPrefix:@"set("] || [typ hasPrefix:@"enum("]) { + // Check if type definition contains a , if so replace the bracket content by … and add + // the bracket content as "list" key to prevend the token field to split them by , + if(typ && [typ rangeOfString:@","].length) { NSString *t = [typ stringByReplacingOccurrencesOfRegex:@"\\(.*?\\)" withString:@"(…)"]; NSString *lst = [typ stringByMatching:@"\\(([^\\)]*?)\\)" capture:1L]; [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys: @@ -541,7 +543,6 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) if(fuzzySearch) { filter = [[NSString stringWithString:[[self string] substringWithRange:parseRange]] stringByReplacingOccurrencesOfString:@"`" withString:@""]; - if([filter length]>15) return; completionRange = parseRange; } @@ -814,10 +815,10 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) long curFlags = ([theEvent modifierFlags] & allFlags); if ([theEvent keyCode] == 53){ // ESC key for internal completion - // if(curFlags==(NSControlKeyMask)) - // [self doCompletionByUsingSpellChecker:NO fuzzyMode:YES]; - // else - [self doCompletionByUsingSpellChecker:NO fuzzyMode:NO]; + if(curFlags==(NSControlKeyMask)) + [self doCompletionByUsingSpellChecker:NO fuzzyMode:YES]; + else + [self doCompletionByUsingSpellChecker:NO fuzzyMode:NO]; // Remove that attribute to suppress auto-uppercasing of certain keyword combinations if(![self selectedRange].length && [self selectedRange].location) [[self textStorage] removeAttribute:kSQLkeyword range:[self getRangeForCurrentWord]]; diff --git a/Source/SPNarrowDownCompletion.h b/Source/SPNarrowDownCompletion.h index f8f12a83..1927b671 100644 --- a/Source/SPNarrowDownCompletion.h +++ b/Source/SPNarrowDownCompletion.h @@ -47,6 +47,7 @@ BOOL fuzzyMode; BOOL noFilterString; BOOL cursorMovedLeft; + BOOL commaInsertionMode; NSInteger backtickMode; NSFont *tableFont; NSRange theCharRange; diff --git a/Source/SPNarrowDownCompletion.m b/Source/SPNarrowDownCompletion.m index 80d8c20c..cc941924 100644 --- a/Source/SPNarrowDownCompletion.m +++ b/Source/SPNarrowDownCompletion.m @@ -33,6 +33,7 @@ #import "SPStringAdditions.h" #import "ImageAndTextCell.h" #import "SPConstants.h" +#import "RegexKitLite.h" #include @interface NSTableView (MovingSelectedRow) @@ -151,6 +152,7 @@ dbStructureMode = theDbMode; cursorMovedLeft = caretMovedLeft; backtickMode = theBackTickMode; + commaInsertionMode = NO; if(aStaticPrefix) staticPrefix = [aStaticPrefix retain]; @@ -299,6 +301,9 @@ [b setAltersStateOfSelectedItem:NO]; [b setControlSize:NSMiniControlSize]; NSMenu *m = [[NSMenu alloc] init]; + NSMenuItem *aMenuItem = [[[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Type Declaration:", @"type declaration header") action:NULL keyEquivalent:@""] autorelease]; + [aMenuItem setEnabled:NO]; + [m addItem:aMenuItem]; [m addItemWithTitle:[[filtered objectAtIndex:rowIndex] objectForKey:@"list"] action:NULL keyEquivalent:@""]; [b setMenu:m]; [m release]; @@ -385,38 +390,45 @@ [newFiltered addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", nil]]; } else { @try{ - NSPredicate* predicate; - if(fuzzyMode) { - NSMutableString *fuzzyRegexp = [[NSMutableString alloc] initWithCapacity:3]; - [fuzzyRegexp setString:@".*"]; - NSInteger i; - unichar c; - for(i=0; i<[[self filterString] length]; i++) { - if(i>20) break; - c = [[self filterString] characterAtIndex:i]; - if(c != '`') { - if(c == '.' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') - [fuzzyRegexp appendString:[NSString stringWithFormat:@"\\%c.*",c]]; - else - [fuzzyRegexp appendString:[NSString stringWithFormat:@"%c.*",c]]; + if(fuzzyMode) { // eg filter = "inf" this regexp search will be performed: (?i).*?i.*?n.*?f + + NSMutableString *fuzzyRegexp = [[NSMutableString alloc] initWithCapacity:3]; + NSInteger i; + unichar c; + + if(!caseSensitive) + [fuzzyRegexp setString:@"(?i)"]; + + for(i=0; i<[[self filterString] length]; i++) { + c = [[self filterString] characterAtIndex:i]; + if(c != '`') { + if(c == '.' || c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') + [fuzzyRegexp appendString:[NSString stringWithFormat:@".*?\\%c",c]]; + else + [fuzzyRegexp appendString:[NSString stringWithFormat:@".*?%c",c]]; + } } + + for(id s in suggestions) + if([[s objectForKey:@"display"] isMatchedByRegex:fuzzyRegexp] || [[s objectForKey:@"isRef"] isMatchedByRegex:fuzzyRegexp]) + [newFiltered addObject:s]; + + + [fuzzyRegexp release]; + + } else { + NSPredicate* predicate; + if(caseSensitive) + predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH %@ OR (match == NULL AND display BEGINSWITH %@)", [self filterString], [self filterString]]; + else + predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH[c] %@ OR (match == NULL AND display BEGINSWITH[c] %@)", [self filterString], [self filterString]]; + [newFiltered addObjectsFromArray:[suggestions filteredArrayUsingPredicate:predicate]]; } - // NSLog(@"re %@", fuzzyRegexp); - if(caseSensitive) - predicate = [NSPredicate predicateWithFormat:@"display MATCHES %@ OR isRef MATCHES %@", fuzzyRegexp, fuzzyRegexp]; - else - predicate = [NSPredicate predicateWithFormat:@"display MATCHES[c] %@ OR isRef MATCHES[c] %@", fuzzyRegexp, fuzzyRegexp]; - [fuzzyRegexp release]; - } else { - if(caseSensitive) - predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH %@ OR (match == NULL AND display BEGINSWITH %@)", [self filterString], [self filterString]]; - else - predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH[c] %@ OR (match == NULL AND display BEGINSWITH[c] %@)", [self filterString], [self filterString]]; - } - [newFiltered addObjectsFromArray:[suggestions filteredArrayUsingPredicate:predicate]]; } @catch(id ae) { + if(newFiltered) [newFiltered release]; NSLog(@"%@", @"Couldn't filter suggestion due to internal regexp error"); + closeMe = YES; } } @@ -513,19 +525,29 @@ if (([event modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)) == NSAlternateKeyMask || [[event characters] length] == 0) { [NSApp sendEvent: event]; + + if(commaInsertionMode) + break; + [mutablePrefix appendString:[event characters]]; theCharRange = NSMakeRange(theCharRange.location, theCharRange.length+[[event characters] length]); theParseRange = NSMakeRange(theParseRange.location, theParseRange.length+[[event characters] length]); [self filter]; } - else if((flags & NSControlKeyMask) || (flags & NSAlternateKeyMask) || (flags & NSCommandKeyMask)) + else if((flags & NSAlternateKeyMask) || (flags & NSCommandKeyMask)) { [NSApp sendEvent:event]; break; } else if([event keyCode] == 53) // escape { - break; + if(flags & NSControlKeyMask) { + fuzzyMode = YES; + [theTableView setBackgroundColor:[NSColor colorWithCalibratedRed:0.9f green:0.9f blue:0.9f alpha:1.0f]]; + [self filter]; + } else { + break; + } } else if(key == NSCarriageReturnCharacter || key == NSTabCharacter) { @@ -534,20 +556,24 @@ else if(key == NSBackspaceCharacter || key == NSDeleteCharacter) { [NSApp sendEvent:event]; - if([mutablePrefix length] == 0) + if([mutablePrefix length] == 0 || commaInsertionMode) break; [mutablePrefix deleteCharactersInRange:NSMakeRange([mutablePrefix length]-1, 1)]; - theCharRange = NSMakeRange(theCharRange.location, theCharRange.length-1); - theParseRange = NSMakeRange(theParseRange.location, theParseRange.length-1); + theCharRange.length--; + theParseRange.length--; [self filter]; } else if([textualInputCharacters characterIsMember:key]) { [NSApp sendEvent:event]; + + if(commaInsertionMode) + break; + [mutablePrefix appendString:[event characters]]; - theCharRange = NSMakeRange(theCharRange.location, theCharRange.length+1); - theParseRange = NSMakeRange(theParseRange.location, theParseRange.length+1); + theCharRange.length++; + theParseRange.length++; [self filter]; [self insertCommonPrefix]; } @@ -663,7 +689,17 @@ } } } - closeMe = YES; + + // Pressing CTRL while inserting an item the suggestion list keeps open + // to allow to add more field/table names comma separated + if([selectedItem objectForKey:@"isRef"] && [[NSApp currentEvent] modifierFlags] & (NSControlKeyMask)) { + [theView insertText:@", "]; + theCharRange = [theView selectedRange]; + theParseRange = [theView selectedRange]; + commaInsertionMode = YES; + } else { + closeMe = YES; + } } @end -- cgit v1.2.3