From 99e4d0223293aee1acd6b4196263385a9e6a7ecc Mon Sep 17 00:00:00 2001 From: Bibiko Date: Sun, 24 May 2009 13:47:57 +0000 Subject: =?UTF-8?q?=E2=80=A2=20activate=20Preference=20setting=20for=20car?= =?UTF-8?q?et=20color=20=E2=80=A2=20added=20prototype=20for=20new=20comple?= =?UTF-8?q?tion=20(ESC=20->=20Cocoa,=20F5=20->=20new=20completion)=20-=20n?= =?UTF-8?q?ot=20yet=20finished=20-=20TODO:=20--=20support=20for=20NSSpellC?= =?UTF-8?q?hecker=20items=20--=20images=20for=20different=20types=20of=20s?= =?UTF-8?q?uggestions=20like=20proc/func/tabkle/view/sql=20statement,=20db?= =?UTF-8?q?=20name,=20etc.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Source/CMTextView.h | 2 + Source/CMTextView.m | 158 +++++++++++++++++++++++++++++++++++++++- Source/CustomQuery.m | 3 +- Source/SPNarrowDownCompletion.h | 3 +- Source/SPNarrowDownCompletion.m | 3 +- Source/SPPreferenceController.m | 1 + 6 files changed, 166 insertions(+), 4 deletions(-) (limited to 'Source') diff --git a/Source/CMTextView.h b/Source/CMTextView.h index fad867e2..723bde8f 100644 --- a/Source/CMTextView.h +++ b/Source/CMTextView.h @@ -81,5 +81,7 @@ - (void) makeTextSizeLarger; - (void) makeTextSizeSmaller; - (void) setConnection:(CMMCPConnection *)theConnection withVersion:(int)majorVersion; +- (void) doCompletion; +- (NSArray *)suggestionsForSQLCompletionWith:(NSString *)currentWord; @end diff --git a/Source/CMTextView.m b/Source/CMTextView.m index 3b06fcff..7ab696db 100644 --- a/Source/CMTextView.m +++ b/Source/CMTextView.m @@ -27,6 +27,8 @@ #import "TableDocument.h" #import "SPStringAdditions.h" #import "SPTextViewAdditions.h" +#import "SPNarrowDownCompletion.h" + #pragma mark - @@ -106,6 +108,141 @@ YY_BUFFER_STATE yy_scan_string (const char *); mySQLmajorVersion = majorVersion; } +- (NSArray *)suggestionsForSQLCompletionWith:(NSString *)currentWord +{ + NSMutableArray *compl = [[NSMutableArray alloc] initWithCapacity:32]; + NSMutableArray *possibleCompletions = [[NSMutableArray alloc] initWithCapacity:32]; + + unsigned i, insindex; + insindex = 0; + + if([mySQLConnection isConnected]) + { + // Add table names to completions list + MCPResult *queryResult = [mySQLConnection listTables]; + if ([queryResult numOfRows]) + [queryResult dataSeek:0]; + for (i = 0 ; i < [queryResult numOfRows] ; i++) + { + [possibleCompletions addObject:[[queryResult fetchRowAsArray] objectAtIndex:0]]; + } + + // Add field names to completions list for currently selected table + if ([[[self window] delegate] table] != nil) { + id columnNames = [[[[self window] delegate] valueForKeyPath:@"tableDataInstance"] valueForKey:@"columnNames"]; + [possibleCompletions addObjectsFromArray:columnNames]; + } + + // Add all database names to completions list + queryResult = [mySQLConnection listDBs]; + if ([queryResult numOfRows]) + [queryResult dataSeek:0]; + for (i = 0 ; i < [queryResult numOfRows] ; i++) + { + [possibleCompletions addObject:[[queryResult fetchRowAsArray] objectAtIndex:0]]; + } + + // Add proc/func only for MySQL version 5 or higher + if(mySQLmajorVersion > 4) { + // Add all procedures to completions list for currently selected table + queryResult = [mySQLConnection queryString:@"SHOW PROCEDURE STATUS"]; + if ([queryResult numOfRows]) + [queryResult dataSeek:0]; + for (i = 0 ; i < [queryResult numOfRows] ; i++) + { + [possibleCompletions addObject:[[queryResult fetchRowAsArray] objectAtIndex:1]]; + } + + // Add all function to completions list for currently selected table + queryResult = [mySQLConnection queryString:@"SHOW FUNCTION STATUS"]; + if ([queryResult numOfRows]) + [queryResult dataSeek:0]; + for (i = 0 ; i < [queryResult numOfRows] ; i++) + { + [possibleCompletions addObject:[[queryResult fetchRowAsArray] objectAtIndex:1]]; + } + } + + } + // If caret is not inside backticks add keywords and all words coming from the view. + if([[self string] length] && ![[[self textStorage] attribute:kBTQuote atIndex:[self selectedRange].location-1 effectiveRange:nil] isEqualToString:kBTQuoteValue] ) + { + // Only parse for words if text size is less than 6MB + if([[self string] length]<6000000) + { + NSCharacterSet *separators = [NSCharacterSet characterSetWithCharactersInString:@" \t\r\n,()\"'`-!;=+|?:~@"]; + NSArray *textViewWords = [[self string] componentsSeparatedByCharactersInSet:separators]; + [possibleCompletions addObjectsFromArray:textViewWords]; + } + [possibleCompletions addObjectsFromArray:[self keywords]]; + } + + // Remove the current word + [possibleCompletions removeObject:currentWord]; + + // Build array of dictionaries as in: + // as in: [NSDictionary dictionaryWithObjectsAndKeys:@"foo", @"display", @"`foo`", @"insert", @"func-small", @"image", nil] + NSString* candidate; + enumerate(possibleCompletions, candidate) + { + if(![compl containsObject:candidate]) + [compl addObject:[NSDictionary dictionaryWithObjectsAndKeys:candidate, @"display", nil]]; + } + + [possibleCompletions release]; + return [compl autorelease]; + +} + +- (void)doCompletion +{ + + // No completion for a selection + if ([self selectedRange].length > 0) return; + + // Refresh quote attributes + [[self textStorage] removeAttribute:kQuote range:NSMakeRange(0,[[self string] length])]; + [self insertText:@""]; + + // Check if the caret is inside quotes "" or ''; if so + // return the normal word suggestion due to the spelling's settings + // if([[[self textStorage] attribute:kQuote atIndex:charRange.location effectiveRange:nil] isEqualToString:kQuoteValue] ) + // return [[NSSpellChecker sharedSpellChecker] completionsForPartialWordRange:NSMakeRange(0,charRange.length) inString:[[self string] substringWithRange:charRange] language:nil inSpellDocumentWithTag:0]; + + NSString* filter = [[self string] substringWithRange:[self getRangeForCurrentWord]]; + NSString* prefix = @""; + NSString* allow = @" "; + BOOL caseInsensitive = YES; + + SPNarrowDownCompletion* completionPopUp = [[SPNarrowDownCompletion alloc] initWithItems:[self suggestionsForSQLCompletionWith:filter] + alreadyTyped:filter + staticPrefix:prefix + additionalWordCharacters:allow + caseSensitive:!caseInsensitive + charRange:[self getRangeForCurrentWord] + inView:self + dictMode:NO]; + + //Get the NSPoint of the first character of the current word + NSRange range = NSMakeRange([self getRangeForCurrentWord].location,0); + NSRange glyphRange = [[self layoutManager] glyphRangeForCharacterRange:range 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)]; + NSFont* font = [self font]; + + // if(filter) + // pos.x -= [filter sizeWithAttributes:[NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]].width; + + // Adjust list location to be under the current word + pos.y -= [font pointSize]*1.25; + + [completionPopUp setCaretPos:pos]; + [completionPopUp orderFront:self]; + +} + + /* * Returns the associated line number for a character position inside of the CMTextView */ @@ -321,13 +458,20 @@ YY_BUFFER_STATE yy_scan_string (const char *); unichar insertedCharacter = [characters characterAtIndex:0]; long curFlags = ([theEvent modifierFlags] & allFlags); - if ([theEvent keyCode] == 53 || insertedCharacter == NSF5FunctionKey){ // ESC key or F5 for completion + if ([theEvent keyCode] == 53){ // ESC key for internal completion [super keyDown: theEvent]; // Remove that attribute to suppress auto-uppercasing of certain keyword combinations if(![self selectedRange].length && [self selectedRange].location) [[self textStorage] removeAttribute:kSQLkeyword range:NSMakeRange([self selectedRange].location-1,1)]; return; } + if (insertedCharacter == NSF5FunctionKey){ // F5 for cocoa completion + [self doCompletion]; + // 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]]; + return; + } // Note: switch(insertedCharacter) {} does not work instead use charactersIgnoringModifiers if([charactersIgnMod isEqualToString:@"c"]) // ^C copy as RTF @@ -2143,6 +2287,18 @@ YY_BUFFER_STATE yy_scan_string (const char *); #pragma mark - #pragma mark delegates +/* + * Update colors by setting them in the Preference pane. + */ +- (void)changeColor:(id)sender +{ + [self setInsertionPointColor:[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorCaretColor"]]]; + NSRange oldRange = [self selectedRange]; + [self setSelectedRange:NSMakeRange(oldRange.location,0)]; + [self insertText:@""]; + [self setSelectedRange:oldRange]; +} + /* * Scrollview delegate after the textView's view port was changed. * Manily used to update the syntax highlighting for a large text size. diff --git a/Source/CustomQuery.m b/Source/CustomQuery.m index 32069bb8..7fa6ac00 100644 --- a/Source/CustomQuery.m +++ b/Source/CustomQuery.m @@ -934,7 +934,8 @@ [textView setFont:[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorFont"]]]; [textView setBackgroundColor:[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorBackgroundColor"]]]; [textView setTextColor:[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorTextColor"]]]; - + [textView setInsertionPointColor:[NSUnarchiver unarchiveObjectWithData:[prefs dataForKey:@"CustomQueryEditorCaretColor"]]]; + [customQueryView setVerticalMotionCanBeginDrag:NO]; [textView setContinuousSpellCheckingEnabled:NO]; [autoindentMenuItem setState:([prefs boolForKey:@"CustomQueryAutoIndent"]?NSOnState:NSOffState)]; diff --git a/Source/SPNarrowDownCompletion.h b/Source/SPNarrowDownCompletion.h index baabb240..15176cf6 100644 --- a/Source/SPNarrowDownCompletion.h +++ b/Source/SPNarrowDownCompletion.h @@ -50,6 +50,7 @@ BOOL isAbove; BOOL closeMe; BOOL caseSensitive; + BOOL dictMode; NSFont *tableFont; NSRange theCharRange; id theView; @@ -58,7 +59,7 @@ } -- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix additionalWordCharacters:(NSString*)someAdditionalWordCharacters caseSensitive:(BOOL)isCaseSensitive charRange:(NSRange)initRange inView:(id)aView; +- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix additionalWordCharacters:(NSString*)someAdditionalWordCharacters caseSensitive:(BOOL)isCaseSensitive charRange:(NSRange)initRange inView:(id)aView dictMode:(BOOL)mode; - (void)setCaretPos:(NSPoint)aPos; - (void)insert_text:(NSString* )aString; diff --git a/Source/SPNarrowDownCompletion.m b/Source/SPNarrowDownCompletion.m index 19d20ead..10988241 100644 --- a/Source/SPNarrowDownCompletion.m +++ b/Source/SPNarrowDownCompletion.m @@ -115,7 +115,7 @@ [super dealloc]; } -- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix additionalWordCharacters:(NSString*)someAdditionalWordCharacters caseSensitive:(BOOL)isCaseSensitive charRange:(NSRange)initRange inView:(id)aView +- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix additionalWordCharacters:(NSString*)someAdditionalWordCharacters caseSensitive:(BOOL)isCaseSensitive charRange:(NSRange)initRange inView:(id)aView dictMode:(BOOL)mode { if(self = [self init]) { @@ -133,6 +133,7 @@ caseSensitive = isCaseSensitive; theCharRange = initRange; theView = aView; + dictMode = mode; } return self; } diff --git a/Source/SPPreferenceController.m b/Source/SPPreferenceController.m index 1f10eede..64f29004 100644 --- a/Source/SPPreferenceController.m +++ b/Source/SPPreferenceController.m @@ -797,6 +797,7 @@ [prefs setObject:[NSArchiver archivedDataWithRootObject:[NSColor colorWithDeviceRed:0.506 green:0.263 blue:0.000 alpha:1.000]] forKey:@"CustomQueryEditorNumericColor"]; [prefs setObject:[NSArchiver archivedDataWithRootObject:[NSColor colorWithDeviceRed:0.500 green:0.500 blue:0.500 alpha:1.000]] forKey:@"CustomQueryEditorVariableColor"]; [prefs setObject:[NSArchiver archivedDataWithRootObject:[NSColor blackColor]] forKey:@"CustomQueryEditorTextColor"]; + [prefs setObject:[NSArchiver archivedDataWithRootObject:[NSColor blackColor]] forKey:@"CustomQueryEditorCaretColor"]; [prefs setObject:[NSArchiver archivedDataWithRootObject:[NSColor whiteColor]] forKey:@"CustomQueryEditorBackgroundColor"]; } -- cgit v1.2.3