diff options
-rw-r--r-- | Source/SPNarrowDownCompletion.h | 49 | ||||
-rw-r--r-- | Source/SPNarrowDownCompletion.m | 436 |
2 files changed, 254 insertions, 231 deletions
diff --git a/Source/SPNarrowDownCompletion.h b/Source/SPNarrowDownCompletion.h index 670d1a29..153f8b78 100644 --- a/Source/SPNarrowDownCompletion.h +++ b/Source/SPNarrowDownCompletion.h @@ -34,12 +34,12 @@ @interface SPNarrowDownCompletion : NSWindow <NSTableViewDelegate, NSTableViewDataSource> { - NSArray* suggestions; - NSMutableString* mutablePrefix; - NSString* staticPrefix; - NSString* currentDb; - NSArray* filtered; - NSTableView* theTableView; + NSArray *suggestions; + NSMutableString *mutablePrefix; + NSString *staticPrefix; + NSString *currentDb; + NSArray *filtered; + NSTableView *theTableView; NSPoint caretPos; BOOL isAbove; BOOL closeMe; @@ -70,11 +70,11 @@ NSUInteger timeCounter; id theView; - + NSInteger maxWindowWidth; NSInteger spaceCounter; - - NSMutableCharacterSet* textualInputCharacters; + + NSMutableCharacterSet *textualInputCharacters; SPDatabaseStructure *databaseStructureRetrieval; #ifndef SP_CODA @@ -82,15 +82,29 @@ #endif } -- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix - additionalWordCharacters:(NSString*)someAdditionalWordCharacters caseSensitive:(BOOL)isCaseSensitive - charRange:(NSRange)initRange parseRange:(NSRange)parseRange inView:(id)aView - dictMode:(BOOL)mode dbMode:(BOOL)theDbMode tabTriggerMode:(BOOL)tabTriggerMode fuzzySearch:(BOOL)fuzzySearch - backtickMode:(NSInteger)theBackTickMode withDbName:(NSString*)dbName withTableName:(NSString*)tableName - selectedDb:(NSString*)selectedDb caretMovedLeft:(BOOL)caretMovedLeft autoComplete:(BOOL)autoComplete oneColumn:(BOOL)oneColumn - alias:(NSString*)anAlias withDBStructureRetriever:(SPDatabaseStructure *)theDatabaseStructure; +- (id) initWithItems:(NSArray *)someSuggestions + alreadyTyped:(NSString *)aUserString + staticPrefix:(NSString *)aStaticPrefix + additionalWordCharacters:(NSString *)someAdditionalWordCharacters + caseSensitive:(BOOL)isCaseSensitive + charRange:(NSRange)initRange + parseRange:(NSRange)parseRange + inView:(id)aView + dictMode:(BOOL)mode + dbMode:(BOOL)theDbMode + tabTriggerMode:(BOOL)tabTriggerMode + fuzzySearch:(BOOL)fuzzySearch + backtickMode:(NSInteger)theBackTickMode + withDbName:(NSString *)dbName + withTableName:(NSString *)tableName + selectedDb:(NSString *)selectedDb + caretMovedLeft:(BOOL)caretMovedLeft + autoComplete:(BOOL)autoComplete + oneColumn:(BOOL)oneColumn + alias:(NSString *)anAlias + withDBStructureRetriever:(SPDatabaseStructure *)theDatabaseStructure; - (void)setCaretPos:(NSPoint)aPos; -- (void)insert_text:(NSString* )aString; +- (void)insert_text:(NSString *)aString; - (void)insertAutocompletePlaceholder; - (void)removeAutocompletionPlaceholderUsingFastMethod:(BOOL)useFastMethod; - (void)adjustWorkingRangeByDelta:(NSInteger)delta; @@ -98,5 +112,4 @@ - (void)updateSyncArrowStatus; - (void)reInvokeCompletion; - @end diff --git a/Source/SPNarrowDownCompletion.m b/Source/SPNarrowDownCompletion.m index af5b2428..f590822a 100644 --- a/Source/SPNarrowDownCompletion.m +++ b/Source/SPNarrowDownCompletion.m @@ -67,11 +67,9 @@ - (BOOL)SP_NarrowDownCompletion_canHandleEvent:(NSEvent*)anEvent { - NSInteger visibleRows = (NSInteger)floor(NSHeight([self visibleRect]) / ([self rowHeight]+[self intercellSpacing].height)) - 1; - struct { unichar key; NSInteger rows; } const key_movements[] = - { + struct { unichar key; NSInteger rows; } const key_movements[] = { { NSUpArrowFunctionKey, -1 }, { NSDownArrowFunctionKey, +1 }, { NSPageUpFunctionKey, -visibleRows }, @@ -81,19 +79,17 @@ }; unichar keyCode = 0; - if([anEvent type] == NSKeyDown && [[anEvent characters] length] == 1) + if([anEvent type] == NSKeyDown && [[anEvent characters] length] == 1) { keyCode = [[anEvent characters] characterAtIndex:0]; + } - - for(size_t i = 0; i < (sizeof(key_movements) / sizeof(key_movements[0])); ++i) - { - if(keyCode == key_movements[i].key) - { + for(size_t i = 0; i < (sizeof(key_movements) / sizeof(key_movements[0])); ++i) { + if(keyCode == key_movements[i].key) { NSInteger row = MAX(0, MIN([self selectedRow] + key_movements[i].rows, [self numberOfRows]-1)); if(row == 0 && ![[[self delegate] tableView:self selectionIndexesForProposedSelection:[NSIndexSet indexSetWithIndex:row]] containsIndex:0]) { - if(visibleRows > 1) - [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row+1] byExtendingSelection:NO]; - } else { + if(visibleRows > 1) [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row+1] byExtendingSelection:NO]; + } + else { [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; } [self scrollRowToVisible:row]; @@ -103,7 +99,6 @@ } return NO; - } @end @@ -114,7 +109,6 @@ // ============================= - (id)init { - maxWindowWidth = 450; if((self = [super initWithContentRect:NSMakeRect(0,0,maxWindowWidth,0) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES])) @@ -140,15 +134,13 @@ #endif [self setupInterface]; - syncArrowImages = [[NSArray alloc] initWithObjects: - [NSImage imageNamed:@"sync_arrows_01"], - [NSImage imageNamed:@"sync_arrows_02"], - [NSImage imageNamed:@"sync_arrows_03"], - [NSImage imageNamed:@"sync_arrows_04"], - [NSImage imageNamed:@"sync_arrows_05"], - [NSImage imageNamed:@"sync_arrows_06"], - nil]; - + syncArrowImages = [[NSArray alloc] initWithObjects:[NSImage imageNamed:@"sync_arrows_01"], + [NSImage imageNamed:@"sync_arrows_02"], + [NSImage imageNamed:@"sync_arrows_03"], + [NSImage imageNamed:@"sync_arrows_04"], + [NSImage imageNamed:@"sync_arrows_05"], + [NSImage imageNamed:@"sync_arrows_06"], + nil]; } return self; } @@ -177,7 +169,6 @@ - (void)close { - // Invalidate the timer now to prevent retain cycles preventing deallocation if (stateTimer != nil) { [stateTimer invalidate]; @@ -205,7 +196,7 @@ [stateTimer invalidate]; SPClear(stateTimer); if(syncArrowImages) SPClear(syncArrowImages); - [self performSelectorOnMainThread:@selector(reInvokeCompletion) withObject:nil waitUntilDone:YES]; + [[self onMainThread] reInvokeCompletion]; closeMe = YES; return; } @@ -213,7 +204,6 @@ } [theTableView setNeedsDisplay:YES]; - } - (void)reInvokeCompletion @@ -227,17 +217,30 @@ [theView performSelector:@selector(refreshCompletion) withObject:nil afterDelay:0.0]; } -- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix - additionalWordCharacters:(NSString*)someAdditionalWordCharacters caseSensitive:(BOOL)isCaseSensitive - charRange:(NSRange)initRange parseRange:(NSRange)parseRange inView:(id)aView - dictMode:(BOOL)mode dbMode:(BOOL)theDbMode tabTriggerMode:(BOOL)tabTriggerMode fuzzySearch:(BOOL)fuzzySearch - backtickMode:(NSInteger)theBackTickMode withDbName:(NSString*)dbName withTableName:(NSString*)tableName - selectedDb:(NSString*)selectedDb caretMovedLeft:(BOOL)caretMovedLeft autoComplete:(BOOL)autoComplete oneColumn:(BOOL)oneColumn - alias:(NSString*)anAlias withDBStructureRetriever:(SPDatabaseStructure *)theDatabaseStructure +- (id) initWithItems:(NSArray *)someSuggestions + alreadyTyped:(NSString *)aUserString + staticPrefix:(NSString *)aStaticPrefix + additionalWordCharacters:(NSString *)someAdditionalWordCharacters + caseSensitive:(BOOL)isCaseSensitive + charRange:(NSRange)initRange + parseRange:(NSRange)parseRange + inView:(id)aView + dictMode:(BOOL)mode + dbMode:(BOOL)theDbMode + tabTriggerMode:(BOOL)tabTriggerMode + fuzzySearch:(BOOL)fuzzySearch + backtickMode:(NSInteger)theBackTickMode + withDbName:(NSString *)dbName + withTableName:(NSString *)tableName + selectedDb:(NSString *)selectedDb + caretMovedLeft:(BOOL)caretMovedLeft + autoComplete:(BOOL)autoComplete + oneColumn:(BOOL)oneColumn + alias:(NSString *)anAlias + withDBStructureRetriever:(SPDatabaseStructure *)theDatabaseStructure { if((self = [self init])) { - // Set filter string if (aUserString) { [mutablePrefix appendString:aUserString]; @@ -251,10 +254,8 @@ oneColumnMode = oneColumn; fuzzyMode = fuzzySearch; - if(fuzzyMode) - [theTableView setBackgroundColor:[NSColor colorWithCalibratedRed:0.9f green:0.9f blue:0.9f alpha:1.0f]]; - else - [theTableView setBackgroundColor:[NSColor whiteColor]]; + if(fuzzyMode) [theTableView setBackgroundColor:[NSColor colorWithCalibratedRed:0.9f green:0.9f blue:0.9f alpha:1.0f]]; + else [theTableView setBackgroundColor:[NSColor whiteColor]]; dbStructureMode = theDbMode; cursorMovedLeft = caretMovedLeft; @@ -262,8 +263,7 @@ commaInsertionMode = NO; triggerMode = tabTriggerMode; - if(aStaticPrefix) - staticPrefix = [aStaticPrefix retain]; + if(aStaticPrefix) staticPrefix = [aStaticPrefix retain]; caseSensitive = isCaseSensitive; @@ -288,8 +288,7 @@ if(len>maxLength) maxLength = len; } NSMutableString *dummy = [NSMutableString string]; - for(NSUInteger i=0; i<maxLength; i++) - [dummy appendString:@" "]; + for(NSUInteger i=0; i<maxLength; i++) [dummy appendString:@" "]; CGFloat w = NSSizeToCGSize([dummy sizeWithAttributes:@{NSFontAttributeName : tableFont}]).width + 26.0f; maxWindowWidth = (w>maxWindowWidth) ? maxWindowWidth : w; @@ -303,15 +302,16 @@ theDbName = dbName; - if(someAdditionalWordCharacters) - [textualInputCharacters addCharactersInString:someAdditionalWordCharacters]; + if(someAdditionalWordCharacters) [textualInputCharacters addCharactersInString:someAdditionalWordCharacters]; databaseStructureRetrieval = [theDatabaseStructure retain]; isQueryingDatabaseStructure = [databaseStructureRetrieval isQueryingDatabaseStructure]; - if(isQueryingDatabaseStructure) + if(isQueryingDatabaseStructure) { stateTimer = [[NSTimer scheduledTimerWithTimeInterval:0.07f target:self selector:@selector(updateSyncArrowStatus) userInfo:nil repeats:YES] retain]; + } } + return self; } @@ -323,16 +323,16 @@ NSInteger offx = (caretPos.x/screen.size.width) + 1; - if((caretPos.x + [self frame].size.width) > (screen.size.width*offx)) + if((caretPos.x + [self frame].size.width) > (screen.size.width*offx)) { caretPos.x = (screen.size.width*offx) - [self frame].size.width - 5; + } - if(caretPos.y >= 0 && caretPos.y < [self frame].size.height) - { + if(caretPos.y >= 0 && caretPos.y < [self frame].size.height) { caretPos.y += [self frame].size.height + ([tableFont pointSize]*1.5f); isAbove = YES; } - if(caretPos.y < 0 && (screen.size.height-[self frame].size.height) < (caretPos.y*-1)) - { + + if(caretPos.y < 0 && (screen.size.height-[self frame].size.height) < (caretPos.y*-1)) { caretPos.y += [self frame].size.height + ([tableFont pointSize]*1.5f); isAbove = YES; } @@ -393,7 +393,6 @@ [scrollView setDocumentView:theTableView]; [self setContentView:scrollView]; - } // ======================== @@ -407,40 +406,38 @@ - (NSString *)tableView:(NSTableView *)aTableView toolTipForCell:(id)aCell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex mouseLocation:(NSPoint)mouseLocation { if([[aTableColumn identifier] isEqualToString:@"image"]) { - if(isQueryingDatabaseStructure && rowIndex == 0) + if(isQueryingDatabaseStructure && rowIndex == 0) { return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress"); + } if(!dictMode) { NSString *imageName = [[filtered objectAtIndex:rowIndex] objectForKey:@"image"]; - if([imageName hasPrefix:@"dummy"]) - return @""; - if([imageName hasPrefix:@"table-view"]) - return @"view"; - if([imageName hasPrefix:@"table"]) - return @"table"; - if([imageName hasPrefix:@"database"]) - return @"database"; - if([imageName hasPrefix:@"func"]) - return @"function"; - if([imageName hasPrefix:@"proc"]) - return @"procedure"; - if([imageName hasPrefix:@"field"]) - return @"field"; + if([imageName hasPrefix:@"dummy"]) return @""; + if([imageName hasPrefix:@"table-view"]) return @"view"; + if([imageName hasPrefix:@"table"]) return @"table"; + if([imageName hasPrefix:@"database"]) return @"database"; + if([imageName hasPrefix:@"func"]) return @"function"; + if([imageName hasPrefix:@"proc"]) return @"procedure"; + if([imageName hasPrefix:@"field"]) return @"field"; } return @""; - } else if([[aTableColumn identifier] isEqualToString:@"name"]) { - if(isQueryingDatabaseStructure && rowIndex == 0) + } + else if([[aTableColumn identifier] isEqualToString:@"name"]) { + if(isQueryingDatabaseStructure && rowIndex == 0) { return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress"); + } return [[filtered objectAtIndex:rowIndex] objectForKey:@"display"]; - - } else if ([[aTableColumn identifier] isEqualToString:@"list"] || [[aTableColumn identifier] isEqualToString:@"type"]) { - if(isQueryingDatabaseStructure && rowIndex == 0) + } + else if ([[aTableColumn identifier] isEqualToString:@"list"] || [[aTableColumn identifier] isEqualToString:@"type"]) { + if(isQueryingDatabaseStructure && rowIndex == 0) { return NSLocalizedString(@"fetching database structure data in progress", @"fetching database structure data in progress"); + } if(dictMode) { return @""; - } else { + } + else { if([[filtered objectAtIndex:rowIndex] objectForKey:@"list"]) { NSMutableString *tt = [NSMutableString string]; [tt appendStringOrNil:[[filtered objectAtIndex:rowIndex] objectForKey:@"type"]]; @@ -449,19 +446,21 @@ [tt appendString:@"\n"]; [tt appendString:[[filtered objectAtIndex:rowIndex] objectForKey:@"list"]]; return tt; - } else { + } + else { return ([[filtered objectAtIndex:rowIndex] objectForKey:@"type"]) ? [[filtered objectAtIndex:rowIndex] objectForKey:@"type"] : @""; } - return @""; } - - } else if ([[aTableColumn identifier] isEqualToString:@"path"]) { - if(isQueryingDatabaseStructure && rowIndex == 0) + } + else if ([[aTableColumn identifier] isEqualToString:@"path"]) { + if(isQueryingDatabaseStructure && rowIndex == 0) { return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress"); + } if(dictMode) { return @""; - } else { + } + else { if([[filtered objectAtIndex:rowIndex] objectForKey:@"path"]) { NSMutableString *tt = [NSMutableString string]; [tt setString:NSLocalizedString(@"Schema path:", @"schema path header for completion tooltip")]; @@ -480,8 +479,9 @@ - (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes { - if(isQueryingDatabaseStructure && [proposedSelectionIndexes containsIndex:0]) + if(isQueryingDatabaseStructure && [proposedSelectionIndexes containsIndex:0]) { return [tableView selectedRowIndexes]; + } return proposedSelectionIndexes; } @@ -495,24 +495,25 @@ if(!dictMode) { if(isQueryingDatabaseStructure && rowIndex == 0) { return [syncArrowImages objectAtIndex:currentSyncImage]; - } else { + } + else { imageName = [[filtered objectAtIndex:rowIndex] objectForKey:@"image"]; - if(imageName) - image = [NSImage imageNamed:imageName]; + if(imageName) image = [NSImage imageNamed:imageName]; return image; } } return @""; - - } else if([[aTableColumn identifier] isEqualToString:@"name"]) { + } + else if([[aTableColumn identifier] isEqualToString:@"name"]) { [[aTableColumn dataCell] setFont:[NSFont systemFontOfSize:12]]; - if(isQueryingDatabaseStructure && rowIndex == 0) - return @"fetching structure…"; + if(isQueryingDatabaseStructure && rowIndex == 0) { + return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress"); + } return [[filtered objectAtIndex:rowIndex] objectForKey:@"display"]; - - } else if ([[aTableColumn identifier] isEqualToString:@"list"]) { + } + else if ([[aTableColumn identifier] isEqualToString:@"list"]) { if(isQueryingDatabaseStructure && rowIndex == 0) { NSPopUpButtonCell *b = [[NSPopUpButtonCell new] autorelease]; [b setPullsDown:NO]; @@ -522,10 +523,12 @@ [b setBordered:NO]; [aTableColumn setDataCell:b]; return @""; - } + } + if(dictMode) { return @""; - } else { + } + else { if([[filtered objectAtIndex:rowIndex] objectForKey:@"list"]) { NSPopUpButtonCell *b = [[NSPopUpButtonCell new] autorelease]; [b setPullsDown:NO]; @@ -543,27 +546,30 @@ [b setFont:[NSFont systemFontOfSize:11]]; [b setBordered:NO]; [aTableColumn setDataCell:b]; - } else { + } + else { [aTableColumn setDataCell:[[NSTextFieldCell new] autorelease]]; } return @""; } - - } else if([[aTableColumn identifier] isEqualToString:@"type"]) { + } + else if([[aTableColumn identifier] isEqualToString:@"type"]) { if(isQueryingDatabaseStructure && rowIndex == 0) { return @""; - } + } + if(dictMode) { return @""; - } else { + } + else { NSTokenFieldCell *b = [[[NSTokenFieldCell alloc] initTextCell:([[filtered objectAtIndex:rowIndex] objectForKey:@"type"]) ? [[filtered objectAtIndex:rowIndex] objectForKey:@"type"] : @""] autorelease]; [b setEditable:NO]; [b setAlignment:NSRightTextAlignment]; [b setFont:[NSFont systemFontOfSize:11]]; return b; } - - } else if ([[aTableColumn identifier] isEqualToString:@"path"]) { + } + else if ([[aTableColumn identifier] isEqualToString:@"path"]) { if(isQueryingDatabaseStructure && rowIndex == 0) { NSPopUpButtonCell *b = [[NSPopUpButtonCell new] autorelease]; [b setPullsDown:NO]; @@ -573,18 +579,21 @@ [b setBordered:NO]; [aTableColumn setDataCell:b]; return @""; - } + } + if(dictMode) { return @""; - } else { + } + else { if([[filtered objectAtIndex:rowIndex] objectForKey:@"path"]) { NSPopUpButtonCell *b = [[NSPopUpButtonCell new] autorelease]; [b setPullsDown:NO]; [b setAltersStateOfSelectedItem:NO]; [b setControlSize:NSMiniControlSize]; NSMenu *m = [[NSMenu alloc] init]; - for(id p in [[[[[filtered objectAtIndex:rowIndex] objectForKey:@"path"] componentsSeparatedByString:SPUniqueSchemaDelimiter] reverseObjectEnumerator] allObjects]) + for(id p in [[[[[filtered objectAtIndex:rowIndex] objectForKey:@"path"] componentsSeparatedByString:SPUniqueSchemaDelimiter] reverseObjectEnumerator] allObjects]) { [m addItemWithTitle:p action:NULL keyEquivalent:@""]; + } if([m numberOfItems]>2) { [m removeItemAtIndex:[m numberOfItems]-1]; [m removeItemAtIndex:0]; @@ -596,7 +605,8 @@ [b setFont:[NSFont systemFontOfSize:11]]; [b setBordered:NO]; [aTableColumn setDataCell:b]; - } else { + } + else { [aTableColumn setDataCell:[[NSTextFieldCell new] autorelease]]; } return @""; @@ -612,13 +622,14 @@ { [textualInputCharacters removeCharactersInString:@" "]; if(autoCompletionMode) return; - if(spaceCounter < 1) - for(id w in filtered){ + if(spaceCounter < 1) { + for(id w in filtered) { if([[w objectForKey:@"match"] ?: [w objectForKey:@"display"] rangeOfString:@" "].length && ![w objectForKey:@"noCompletion"]) { [textualInputCharacters addCharactersInString:@" "]; break; } } + } } // ==================== @@ -626,21 +637,23 @@ // ==================== - (void)filter { - NSMutableArray* newFiltered = [[NSMutableArray alloc] initWithCapacity:5]; - if([mutablePrefix length] > 0) - { + if([mutablePrefix length] > 0) { if(dictMode) { NSPredicate* predicate; - if(caseSensitive) + if(caseSensitive) { predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH %@ OR (match == NULL AND display BEGINSWITH %@)", [self filterString], [self filterString]]; - else + } + else { predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH[c] %@ OR (match == NULL AND display BEGINSWITH[c] %@)", [self filterString], [self filterString]]; + } [newFiltered addObjectsFromArray:[suggestions filteredArrayUsingPredicate:predicate]]; - for(id w in [[NSSpellChecker sharedSpellChecker] completionsForPartialWordRange:NSMakeRange(0,[[self filterString] length]) inString:[self filterString] language:nil inSpellDocumentWithTag:0]) + for(id w in [[NSSpellChecker sharedSpellChecker] completionsForPartialWordRange:NSMakeRange(0,[[self filterString] length]) inString:[self filterString] language:nil inSpellDocumentWithTag:0]) { [newFiltered addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", nil]]; - } else { + } + } + else { @try{ if(fuzzyMode) { // eg filter = "inf" this regexp search will be performed: (?i).*?i.*?n.*?f @@ -648,34 +661,39 @@ NSUInteger i; unichar c; - if (!caseSensitive) - [fuzzyRegexp setString:@"(?i)"]; + if (!caseSensitive) [fuzzyRegexp setString:@"(?i)"]; for (i=0; i<[[self filterString] length]; i++) { c = [[self filterString] characterAtIndex:i]; if(c != '`') { - if(c == '.') + if(c == '.') { [fuzzyRegexp appendFormat:@".*?%@",SPUniqueSchemaDelimiter]; - else if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') + } + else if (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}') { [fuzzyRegexp appendFormat:@".*?\\%c",c]; - else + } + else { [fuzzyRegexp appendFormat:@".*?%c",c]; + } } } - for (id s in suggestions) - if ([[s objectForKey:@"display"] isMatchedByRegex:fuzzyRegexp] || [[s objectForKey:@"path"] isMatchedByRegex:fuzzyRegexp]) + for (id s in suggestions) { + if ([[s objectForKey:@"display"] isMatchedByRegex:fuzzyRegexp] || [[s objectForKey:@"path"] isMatchedByRegex:fuzzyRegexp]) { [newFiltered addObject:s]; - + } + } [fuzzyRegexp release]; - - } else { + } + else { NSPredicate* predicate; - if(caseSensitive) + if(caseSensitive) { predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH %@ OR (match == NULL AND display BEGINSWITH %@)", [self filterString], [self filterString]]; - else + } + else { predicate = [NSPredicate predicateWithFormat:@"match BEGINSWITH[c] %@ OR (match == NULL AND display BEGINSWITH[c] %@)", [self filterString], [self filterString]]; + } [newFiltered addObjectsFromArray:[suggestions filteredArrayUsingPredicate:predicate]]; } } @@ -685,13 +703,10 @@ closeMe = YES; return; } - } } - else - { - if(!dictMode) - [newFiltered addObjectsFromArray:suggestions]; + else { + if(!dictMode) [newFiltered addObjectsFromArray:suggestions]; } if(![newFiltered count]) { @@ -699,7 +714,8 @@ [newFiltered release]; closeMe = YES; return; - } else { + } + else { if([theView completionWasReinvokedAutomatically]) return; if([[self filterString] hasSuffix:@"."]) { [theView setCompletionWasReinvokedAutomatically:YES]; @@ -707,34 +723,35 @@ [newFiltered release]; closeMe = YES; return; - } else { + } + else { [newFiltered addObject:@{@"display" : NSLocalizedString(@"No item found", @"no item found message"), @"noCompletion" : @""}]; } } } + if(autoCompletionMode && [newFiltered count] == 1 && [[[self filterString] lowercaseString] isEqualToString:[[[newFiltered objectAtIndex:0] objectForKey:@"display"] lowercaseString]]) { [newFiltered release]; closeMe = YES; return; } - // if fetching db structure add dummy row for displaying that info on top of the list - if(isQueryingDatabaseStructure) - [newFiltered insertObject:@{@"display" : @"dummy", @"noCompletion" : @""} atIndex:0]; + if(isQueryingDatabaseStructure) [newFiltered insertObject:@{@"display" : @"dummy", @"noCompletion" : @""} atIndex:0]; NSPoint old = NSMakePoint([self frame].origin.x, [self frame].origin.y + [self frame].size.height); NSInteger displayedRows = [newFiltered count] < SPNarrowDownCompletionMaxRows ? [newFiltered count] : SPNarrowDownCompletionMaxRows; - CGFloat newHeight = ([theTableView rowHeight] + [theTableView intercellSpacing].height) * ((displayedRows) ? displayedRows : 1); + CGFloat newHeight = ([theTableView rowHeight] + [theTableView intercellSpacing].height) * ((displayedRows) ? displayedRows : 1); - if(caretPos.y >= 0 && (isAbove || caretPos.y < newHeight)) - { + if(caretPos.y >= 0 && (isAbove || caretPos.y < newHeight)) { isAbove = YES; old.y = caretPos.y + newHeight + ([tableFont pointSize]*1.5f); } - if(caretPos.y < 0 && (isAbove || ([self rectOfMainScreen].size.height-newHeight) < (caretPos.y*-1))) + + if(caretPos.y < 0 && (isAbove || ([self rectOfMainScreen].size.height-newHeight) < (caretPos.y*-1))) { old.y = caretPos.y + newHeight + ([tableFont pointSize]*1.5f); + } // newHeight is currently the new height for theTableView, but we need to resize the whole window // so here we use the difference in height to find the new height for the window @@ -743,8 +760,7 @@ if (filtered) [filtered release]; filtered = [newFiltered retain]; [newFiltered release]; - if(!dictMode) - [self checkSpaceForAllowedCharacter]; + if(!dictMode) [self checkSpaceForAllowedCharacter]; [theTableView reloadData]; [theTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:(isQueryingDatabaseStructure)?1:0] byExtendingSelection:NO]; } @@ -761,8 +777,7 @@ { NSRect screen = [[NSScreen mainScreen] frame]; - for (NSScreen *candidate in [NSScreen screens]) - { + for (NSScreen *candidate in [NSScreen screens]) { if (NSMinX([candidate frame]) == 0.0f && NSMinY([candidate frame]) == 0.0f) { screen = [candidate frame]; } @@ -780,7 +795,8 @@ if (!closeMe) { [super orderFront:sender]; [self performSelector:@selector(watchUserEvents) withObject:nil afterDelay:0.05]; - } else { + } + else { [self close]; } } @@ -791,33 +807,28 @@ [theView setCompletionIsOpen:YES]; closeMe = NO; - while(!closeMe) - { + while(!closeMe) { NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantFuture] - inMode:NSDefaultRunLoopMode - dequeue:YES]; + untilDate:[NSDate distantFuture] + inMode:NSDefaultRunLoopMode + dequeue:YES]; - if(!event) - continue; + if(!event) continue; // Exit if closeMe has been set in the meantime if(closeMe) return; NSEventType t = [event type]; - if([theTableView SP_NarrowDownCompletion_canHandleEvent:event]) - { + if([theTableView SP_NarrowDownCompletion_canHandleEvent:event]) { // skip the rest } - else if(t == NSKeyDown) - { + else if(t == NSKeyDown) { NSUInteger flags = [event modifierFlags]; unichar key = [[event characters] length] == 1 ? [[event characters] characterAtIndex:0] : 0; // Check if user pressed ⌥ to allow composing of accented characters. // e.g. for US keyboard "⌥u a" to insert ä - if (([event modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)) == NSAlternateKeyMask || [[event characters] length] == 0) - { + if (([event modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)) == NSAlternateKeyMask || [[event characters] length] == 0) { if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholderUsingFastMethod:YES]; if (autoCompletionMode) { @@ -829,29 +840,27 @@ [NSApp sendEvent: event]; - if(commaInsertionMode) - break; + 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 & NSAlternateKeyMask) || (flags & NSCommandKeyMask)) - { + else if((flags & NSAlternateKeyMask) || (flags & NSCommandKeyMask)) { if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholderUsingFastMethod:YES]; [theView setCompletionIsOpen:NO]; [self close]; [NSApp sendEvent:event]; break; } - else if([event keyCode] == 53) // escape - { + else if([event keyCode] == 53) { // escape if(flags & NSControlKeyMask) { fuzzyMode = YES; [theTableView setBackgroundColor:[NSColor colorWithCalibratedRed:0.9f green:0.9f blue:0.9f alpha:1.0f]]; [self filter]; - } else { + } + else { if(autoCompletionMode) { if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholderUsingFastMethod:YES]; [theView setCompletionIsOpen:NO]; @@ -862,12 +871,10 @@ break; } } - else if(key == NSCarriageReturnCharacter || key == NSEnterCharacter || key == NSRightArrowFunctionKey || (key == NSTabCharacter && !triggerMode)) - { + else if(key == NSCarriageReturnCharacter || key == NSEnterCharacter || key == NSRightArrowFunctionKey || (key == NSTabCharacter && !triggerMode)) { [self completeAndInsertSnippet]; } - else if(key == NSBackspaceCharacter || key == NSDeleteCharacter) - { + else if(key == NSBackspaceCharacter || key == NSDeleteCharacter) { if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholderUsingFastMethod:NO]; if (autoCompletionMode) { @@ -876,8 +883,7 @@ } [NSApp sendEvent:event]; - if([mutablePrefix length] == 0 || commaInsertionMode) - break; + if([mutablePrefix length] == 0 || commaInsertionMode) break; spaceCounter = 0; [mutablePrefix deleteCharactersInRange:NSMakeRange([mutablePrefix length]-1, 1)]; @@ -886,8 +892,7 @@ theParseRange.length--; [self filter]; } - else if([textualInputCharacters characterIsMember:key]) - { + else if([textualInputCharacters characterIsMember:key]) { if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholderUsingFastMethod:YES]; if (autoCompletionMode) { @@ -899,10 +904,8 @@ [NSApp sendEvent:event]; - if(commaInsertionMode) - break; - if([event keyCode] == 49) // space - spaceCounter++; + if(commaInsertionMode) break; + if([event keyCode] == 49) spaceCounter++; // space [mutablePrefix appendString:[event characters]]; [originalFilterString appendString:[event characters]]; @@ -910,20 +913,18 @@ theParseRange.length++; [self filter]; [self insertAutocompletePlaceholder]; - } - else - { + else { [NSApp sendEvent:event]; if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; break; } } - else if(t == NSRightMouseDown || t == NSLeftMouseDown) - { + else if(t == NSRightMouseDown || t == NSLeftMouseDown) { if(([event clickCount] == 2)) { [self completeAndInsertSnippet]; - } else { + } + else { if(!NSPointInRect([NSEvent mouseLocation], [self frame])) { if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholderUsingFastMethod:YES]; if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; @@ -933,8 +934,7 @@ [NSApp sendEvent:event]; } } - else - { + else { [NSApp sendEvent:event]; } } @@ -952,8 +952,7 @@ // ================== - (void)insertAutocompletePlaceholder { - if([theTableView selectedRow] == -1 || fuzzyMode) - return; + if([theTableView selectedRow] == -1 || fuzzyMode) return; // Retrieve the current autocompletion length, if any NSUInteger currentAutocompleteLength = theCharRange.length - [originalFilterString length]; @@ -1000,8 +999,10 @@ if(backtickMode) { NSRange r = NSMakeRange(theCharRange.location+1,theCharRange.length); [theView setSelectedRange:r]; - } else + } + else { [theView setSelectedRange:theCharRange]; + } [theView insertText:originalFilterString]; } else { NSRange attributeResultRange = NSMakeRange(0, 0); @@ -1015,12 +1016,11 @@ // Perform a search for the attribute, capturing the range of the [non]match if ([[theView textStorage] attribute:kSPAutoCompletePlaceholderName atIndex:scanPosition longestEffectiveRange:&attributeResultRange inRange:NSMakeRange(scanPosition, currentLength-scanPosition)]) { - // A match was found - attributeResultRange contains the range of the attributed string [theView shouldChangeTextInRange:attributeResultRange replacementString:@""]; [[theView textStorage] deleteCharactersInRange:attributeResultRange]; - } else { - + } + else { // No match was found. attributeResultRange contains the range of the no match - this can be // checked to see whether a match is inside the full range. if (scanPosition + attributeResultRange.length == currentLength) break; @@ -1030,7 +1030,7 @@ if ([[theView textStorage] attribute:kSPAutoCompletePlaceholderName atIndex:matchStart longestEffectiveRange:&attributeResultRange inRange:NSMakeRange(matchStart, currentLength - matchStart)]) { [theView shouldChangeTextInRange:attributeResultRange replacementString:@""]; [[theView textStorage] deleteCharactersInRange:attributeResultRange]; - } + } } scanPosition = attributeResultRange.location; } @@ -1040,49 +1040,54 @@ autocompletePlaceholderWasInserted = NO; } -- (void)insert_text:(NSString* )aString +- (void)insert_text:(NSString *)aString { - // Ensure that theCharRange is valid - if(NSMaxRange(theCharRange) > [[theView string] length]) + if(NSMaxRange(theCharRange) > [[theView string] length]) { theCharRange = NSIntersectionRange(NSMakeRange(0,[[theView string] length]), theCharRange); + } [theView breakUndoCoalescing]; NSRange r = [theView selectedRange]; - if(r.length) + if(r.length) { [theView setSelectedRange:r]; + } else { if(backtickMode == 100) { NSString *replaceString = [[theView string] substringWithRange:theCharRange]; BOOL nextCharIsBacktick = ([replaceString hasSuffix:@"`"]); if(theCharRange.length == 1) nextCharIsBacktick = NO; if(!nextCharIsBacktick) { - if([replaceString hasPrefix:@"`"]) + if([replaceString hasPrefix:@"`"]) { [theView setSelectedRange:NSMakeRange(theCharRange.location, theCharRange.length+2)]; - else + } + else { [theView setSelectedRange:theCharRange]; + } } else { [theView setSelectedRange:theCharRange]; } backtickMode = 0; - } else + } + else { [theView setSelectedRange:theCharRange]; + } } [theView breakUndoCoalescing]; [theView insertText:aString]; - + // If completion string contains backticks move caret out of the backticks - if(backtickMode && !triggerMode) + if(backtickMode && !triggerMode) { [theView performSelector:@selector(moveRight:)]; - // If it's a function or procedure append () and if a argument list can be retieved insert them as snippets + } #ifndef SP_CODA + // If it's a function or procedure append () and if a argument list can be retieved insert them as snippets else if([prefs boolForKey:SPCustomQueryFunctionCompletionInsertsArguments] && ([[[filtered objectAtIndex:[theTableView selectedRow]] objectForKey:@"image"] hasPrefix:@"func"] || [[[filtered objectAtIndex:[theTableView selectedRow]] objectForKey:@"image"] hasPrefix:@"proc"]) && ![aString hasSuffix:@")"]) { NSString *functionArgumentSnippet = [NSString stringWithFormat:@"(%@)", [[SPQueryController sharedQueryController] argumentSnippetForFunction:aString]]; [theView insertAsSnippet:functionArgumentSnippet atRange:[theView selectedRange]]; - if([functionArgumentSnippet length] == 2) - [theView performSelector:@selector(moveLeft:)]; + if([functionArgumentSnippet length] == 2) [theView performSelector:@selector(moveLeft:)]; } #endif } @@ -1098,13 +1103,14 @@ return; } - if(dictMode){ + if(dictMode) { [self insert_text:[selectedItem objectForKey:@"match"] ?: [selectedItem objectForKey:@"display"]]; - } else { + } + else { NSString* candidateMatch = [selectedItem objectForKey:@"match"] ?: [selectedItem objectForKey:@"display"]; if([selectedItem objectForKey:@"isRef"] - && ([[NSApp currentEvent] modifierFlags] & (NSShiftKeyMask)) - && [(NSString*)[selectedItem objectForKey:@"path"] length] && theAliasName == nil) { + && ([[NSApp currentEvent] modifierFlags] & (NSShiftKeyMask)) + && [(NSString*)[selectedItem objectForKey:@"path"] length] && theAliasName == nil) { NSString *path = [[[selectedItem objectForKey:@"path"] componentsSeparatedByString:SPUniqueSchemaDelimiter] componentsJoinedByPeriodAndBacktickQuotedAndIgnoreFirst]; // Check if path's db name is the current selected db name @@ -1116,21 +1122,24 @@ } else { [self insert_text:path]; } - } else { + } + else { // Is completion string a schema name for current connection if([selectedItem objectForKey:@"isRef"]) { backtickMode = 100; // suppress move the caret one step rightwards - if ([prefs boolForKey:SPCustomQueryEditorCompleteWithBackticks]) { - [self insert_text:[candidateMatch backtickQuotedString]]; - } else { - [self insert_text:candidateMatch]; - } - } else { + if ([prefs boolForKey:SPCustomQueryEditorCompleteWithBackticks]) { + [self insert_text:[candidateMatch backtickQuotedString]]; + } + else { + [self insert_text:candidateMatch]; + } + } + else { [self insert_text:candidateMatch]; } } } - + // 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)) { @@ -1138,7 +1147,8 @@ theCharRange = [theView selectedRange]; theParseRange = [theView selectedRange]; commaInsertionMode = YES; - } else { + } + else { closeMe = YES; } } |