aboutsummaryrefslogtreecommitdiffstats
path: root/Source/CMTextView.m
diff options
context:
space:
mode:
Diffstat (limited to 'Source/CMTextView.m')
-rw-r--r--Source/CMTextView.m219
1 files changed, 165 insertions, 54 deletions
diff --git a/Source/CMTextView.m b/Source/CMTextView.m
index 7a0cfae4..7fb6ceee 100644
--- a/Source/CMTextView.m
+++ b/Source/CMTextView.m
@@ -1081,6 +1081,159 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
}
/*
+ * Shows pre-defined completion list
+ */
+- (void)showCompletionListFor:(NSString*)kind atRange:(NSRange)aRange fuzzySearch:(BOOL)fuzzySearchMode
+{
+
+ // Cancel auto-completion timer
+ if([prefs boolForKey:SPCustomQueryAutoComplete])
+ [NSObject cancelPreviousPerformRequestsWithTarget:self
+ selector:@selector(doAutoCompletion)
+ object:nil];
+
+ NSMutableArray *possibleCompletions = [[[NSMutableArray alloc] initWithCapacity:0] autorelease];
+ NSArray *arr = nil;
+ if([kind isEqualToString:@"$SP_ASLIST_ALL_TABLES"]) {
+ NSString *currentDb = nil;
+
+ if ([[[[self window] delegate] valueForKeyPath:@"tablesListInstance"] valueForKey:@"selectedDatabase"] != nil)
+ currentDb = [[[[self window] delegate] valueForKeyPath:@"tablesListInstance"] valueForKeyPath:@"selectedDatabase"];
+
+ NSDictionary *dbs = [NSDictionary dictionaryWithDictionary:[mySQLConnection getDbStructure]];
+
+ if(currentDb != nil && dbs != nil && [dbs count] && [dbs objectForKey:currentDb]) {
+ NSArray *allTables = [[dbs objectForKey:currentDb] allKeys];
+ NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
+ NSArray *sortedTables = [allTables sortedArrayUsingDescriptors:[NSArray arrayWithObject:desc]];
+ for(id table in sortedTables) {
+ NSDictionary * theTable = [[dbs objectForKey:currentDb] objectForKey:table];
+ NSInteger structtype = [[theTable objectForKey:@" struct_type "] intValue];
+ switch(structtype) {
+ case 0:
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:table, @"display", @"table-small-square", @"image", currentDb, @"path", [NSString stringWithFormat:@"%@.%@",currentDb,table], @"isRef", nil]];
+ break;
+ case 1:
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:table, @"display", @"table-view-small-square", @"image", currentDb, @"path", [NSString stringWithFormat:@"%@.%@",currentDb,table], @"isRef", nil]];
+ break;
+ }
+ }
+ } else {
+ arr = [NSArray arrayWithArray:[[[self delegate] valueForKeyPath:@"tablesListInstance"] allTableAndViewNames]];
+ if(arr == nil) {
+ arr = [NSArray array];
+ }
+ for(id w in arr)
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"table-small-square", @"image", @"", @"isRef", nil]];
+ }
+ }
+ else if([kind isEqualToString:@"$SP_ASLIST_ALL_DATABASES"]) {
+ arr = [NSArray arrayWithArray:[[[self delegate] valueForKeyPath:@"tablesListInstance"] allDatabaseNames]];
+ if(arr == nil) {
+ arr = [NSArray array];
+ }
+ for(id w in arr)
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"database-small", @"image", @"", @"isRef", nil]];
+ arr = [NSArray arrayWithArray:[[[self delegate] valueForKeyPath:@"tablesListInstance"] allSystemDatabaseNames]];
+ if(arr == nil) {
+ arr = [NSArray array];
+ }
+ for(id w in arr)
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"database-small", @"image", @"", @"isRef", nil]];
+ }
+ else if([kind isEqualToString:@"$SP_ASLIST_ALL_FIELDS_FROM_SELECTED_TABLE"]) {
+
+ NSString *currentDb = nil;
+ NSString *currentTable = nil;
+
+ if ([[[[self window] delegate] valueForKeyPath:@"tablesListInstance"] valueForKey:@"selectedDatabase"] != nil)
+ currentDb = [[[[self window] delegate] valueForKeyPath:@"tablesListInstance"] valueForKeyPath:@"selectedDatabase"];
+ if ([[[[self window] delegate] valueForKeyPath:@"tablesListInstance"] valueForKey:@"tableName"] != nil)
+ currentTable = [[[[self window] delegate] valueForKeyPath:@"tablesListInstance"] valueForKeyPath:@"tableName"];
+
+ NSDictionary *dbs = [NSDictionary dictionaryWithDictionary:[mySQLConnection getDbStructure]];
+ if(currentDb != nil && currentTable != nil && dbs != nil && [dbs count] && [dbs objectForKey:currentDb] && [[dbs objectForKey:currentDb] objectForKey:currentTable]) {
+ NSDictionary * theTable = [[dbs objectForKey:currentDb] objectForKey:currentTable];
+ NSArray *allFields = [theTable allKeys];
+ NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:nil ascending:YES selector:@selector(localizedCompare:)];
+ NSArray *sortedFields = [allFields sortedArrayUsingDescriptors:[NSArray arrayWithObject:desc]];
+ for(id field in sortedFields) {
+ if(![field hasPrefix:@" "]) {
+ NSString *typ = [theTable objectForKey:field];
+ // 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:
+ field, @"display",
+ @"field-small-square", @"image",
+ [NSString stringWithFormat:@"%@⇠%@",currentTable,currentDb], @"path",
+ t, @"type",
+ lst, @"list",
+ [NSString stringWithFormat:@"%@.%@.%@",currentDb,currentTable,field], @"isRef",
+ nil]];
+ } else {
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ field, @"display",
+ @"field-small-square", @"image",
+ [NSString stringWithFormat:@"%@⇠%@",currentTable,currentDb], @"path",
+ typ, @"type",
+ [NSString stringWithFormat:@"%@.%@.%@",currentDb,currentTable,field], @"isRef",
+ nil]];
+ }
+ }
+ }
+ [desc release];
+ } else {
+ arr = [NSArray arrayWithArray:[[[[self window] delegate] valueForKeyPath:@"tableDataInstance"] valueForKey:@"columnNames"]];
+ if(arr == nil) {
+ arr = [NSArray array];
+ }
+ for(id w in arr)
+ [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"field-small-square", @"image", @"", @"isRef", nil]];
+ }
+ }
+ else {
+ NSLog(@"“%@” is not a valid completion list", kind);
+ NSBeep();
+ return;
+ }
+
+ SPNarrowDownCompletion* completionPopUp = [[SPNarrowDownCompletion alloc] initWithItems:possibleCompletions
+ alreadyTyped:@""
+ staticPrefix:@""
+ additionalWordCharacters:@"_."
+ caseSensitive:NO
+ charRange:aRange
+ parseRange:aRange
+ inView:self
+ dictMode:NO
+ dbMode:YES
+ tabTriggerMode:[self isSnippetMode]
+ fuzzySearch:fuzzySearchMode
+ backtickMode:NO
+ withDbName:@""
+ withTableName:@""
+ selectedDb:@""
+ caretMovedLeft:NO
+ autoComplete:NO
+ oneColumn:NO];
+
+ //Get the NSPoint of the first character of the current word
+ NSRange glyphRange = [[self layoutManager] glyphRangeForCharacterRange:NSMakeRange(aRange.location,1) actualCharacterRange:NULL];
+ NSRect boundingRect = [[self layoutManager] boundingRectForGlyphRange:glyphRange inTextContainer:[self textContainer]];
+ boundingRect = [self convertRect: boundingRect toView: NULL];
+ NSPoint pos = [[self window] convertBaseToScreen: NSMakePoint(boundingRect.origin.x + boundingRect.size.width,boundingRect.origin.y + boundingRect.size.height)];
+ // Adjust list location to be under the current word or insertion point
+ pos.y -= [[self font] pointSize]*1.25;
+ [completionPopUp setCaretPos:pos];
+ completionIsOpen = YES;
+ [completionPopUp orderFront:self];
+
+}
+
+/*
* Selects the current snippet defined by “currentSnippetIndex”
*/
- (void)selectCurrentSnippet
@@ -1116,50 +1269,8 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
SPNarrowDownCompletion* completionPopUp;
NSString *newSnip = [snip substringWithRange:NSMakeRange(1*offset,[snip length]-(2*offset))];
if([newSnip hasPrefix:@"$SP_ASLIST_"]) {
- NSMutableArray *possibleCompletions = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];
- NSArray *arr = nil;
- if([newSnip isEqualToString:@"$SP_ASLIST_ALL_TABLES"]) {
- arr = [NSArray arrayWithArray:[[[self delegate] valueForKeyPath:@"tablesListInstance"] allTableAndViewNames]];
- if(arr == nil) {
- arr = [NSArray array];
- }
- for(id w in arr)
- [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"table-small-square", @"image", @"", @"isRef", nil]];
- }
- else if([newSnip isEqualToString:@"$SP_ASLIST_ALL_DATABASES"]) {
- arr = [NSArray arrayWithArray:[[[self delegate] valueForKeyPath:@"tablesListInstance"] allDatabaseNames]];
- if(arr == nil) {
- arr = [NSArray array];
- }
- for(id w in arr)
- [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"database-small", @"image", @"", @"isRef", nil]];
- arr = [NSArray arrayWithArray:[[[self delegate] valueForKeyPath:@"tablesListInstance"] allSystemDatabaseNames]];
- if(arr == nil) {
- arr = [NSArray array];
- }
- for(id w in arr)
- [possibleCompletions addObject:[NSDictionary dictionaryWithObjectsAndKeys:w, @"display", @"database-small", @"image", @"", @"isRef", nil]];
- }
-
- completionPopUp = [[SPNarrowDownCompletion alloc] initWithItems:possibleCompletions
- alreadyTyped:@""
- staticPrefix:@""
- additionalWordCharacters:@"_."
- caseSensitive:NO
- charRange:insertRange
- parseRange:insertRange
- inView:self
- dictMode:NO
- dbMode:YES
- tabTriggerMode:[self isSnippetMode]
- fuzzySearch:fuzzySearchMode
- backtickMode:NO
- withDbName:@""
- withTableName:@""
- selectedDb:@""
- caretMovedLeft:NO
- autoComplete:NO
- oneColumn:NO];
+ [self showCompletionListFor:newSnip atRange:NSMakeRange(r2.location, 0) fuzzySearch:fuzzySearchMode];
+ return;
} else {
NSArray *list = [[snip substringWithRange:NSMakeRange(1*offset,[snip length]-(2*offset))] componentsSeparatedByString:@"¦"];
NSMutableArray *possibleCompletions = [[[NSMutableArray alloc] initWithCapacity:[list count]] autorelease];
@@ -1185,17 +1296,17 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
caretMovedLeft:NO
autoComplete:NO
oneColumn:YES];
+ //Get the NSPoint of the first character of the current word
+ NSRange glyphRange = [[self layoutManager] glyphRangeForCharacterRange:NSMakeRange(r2.location,1) actualCharacterRange:NULL];
+ NSRect boundingRect = [[self layoutManager] boundingRectForGlyphRange:glyphRange inTextContainer:[self textContainer]];
+ boundingRect = [self convertRect: boundingRect toView: NULL];
+ NSPoint pos = [[self window] convertBaseToScreen: NSMakePoint(boundingRect.origin.x + boundingRect.size.width,boundingRect.origin.y + boundingRect.size.height)];
+ // Adjust list location to be under the current word or insertion point
+ pos.y -= [[self font] pointSize]*1.25;
+ [completionPopUp setCaretPos:pos];
+ completionIsOpen = YES;
+ [completionPopUp orderFront:self];
}
- //Get the NSPoint of the first character of the current word
- NSRange glyphRange = [[self layoutManager] glyphRangeForCharacterRange:NSMakeRange(r2.location,1) actualCharacterRange:NULL];
- NSRect boundingRect = [[self layoutManager] boundingRectForGlyphRange:glyphRange inTextContainer:[self textContainer]];
- boundingRect = [self convertRect: boundingRect toView: NULL];
- NSPoint pos = [[self window] convertBaseToScreen: NSMakePoint(boundingRect.origin.x + boundingRect.size.width,boundingRect.origin.y + boundingRect.size.height)];
- // Adjust list location to be under the current word or insertion point
- pos.y -= [[self font] pointSize]*1.25;
- [completionPopUp setCaretPos:pos];
- completionIsOpen = YES;
- [completionPopUp orderFront:self];
}
} else {
[self endSnippetSession];