diff options
-rw-r--r-- | Source/CMTextView.h | 3 | ||||
-rw-r--r-- | Source/CMTextView.m | 186 | ||||
-rw-r--r-- | Source/SPNarrowDownCompletion.h | 3 | ||||
-rw-r--r-- | Source/SPNarrowDownCompletion.m | 12 |
4 files changed, 153 insertions, 51 deletions
diff --git a/Source/CMTextView.h b/Source/CMTextView.h index 137c5348..ab7ed1af 100644 --- a/Source/CMTextView.h +++ b/Source/CMTextView.h @@ -59,8 +59,9 @@ static inline void NSMutableAttributedStringAddAttributeValueRange (NSMutableAtt MCPConnection *mySQLConnection; NSInteger mySQLmajorVersion; - NSInteger snippetControlArray[20][2]; + NSInteger snippetControlArray[20][3]; NSInteger snippetControlCounter; + NSInteger snippetControlMax; NSInteger currentSnippetIndex; BOOL snippetWasJustInserted; diff --git a/Source/CMTextView.m b/Source/CMTextView.m index 26c5790d..c8016451 100644 --- a/Source/CMTextView.m +++ b/Source/CMTextView.m @@ -394,16 +394,14 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) - (void) doCompletionByUsingSpellChecker:(BOOL)isDictMode fuzzyMode:(BOOL)fuzzySearch { - // No completion for a selection (yet?) and if caret positiopn == 0 - if([self selectedRange].length > 0 || ![self selectedRange].location) return; - [self breakUndoCoalescing]; - NSInteger caretPos = [self selectedRange].location; + NSInteger caretPos = NSMaxRange([self selectedRange]); + // [self setSelectedRange:NSMakeRange(caretPos, 0)]; BOOL caretMovedLeft = NO; // Check if caret is located after a ` - if so move caret inside - if([[self string] characterAtIndex:caretPos-1] == '`') { + if([[self string] length] && [[self string] characterAtIndex:caretPos-1] == '`') { if([[self string] length] > caretPos && [[self string] characterAtIndex:caretPos] == '`') { ; } else { @@ -437,6 +435,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) if(![self selectedRange].length && [self selectedRange].location) [[self textStorage] removeAttribute:kSQLkeyword range:completionRange]; + [self setSelectedRange:NSMakeRange(caretPos, 0)]; if(!isDictMode) { @@ -578,6 +577,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) inView:self dictMode:isDictMode dbMode:dbBrowseMode + tabTriggerMode:((snippetControlCounter > -1) ? YES : NO) fuzzySearch:fuzzySearch backtickMode:backtickMode withDbName:dbName @@ -800,52 +800,119 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) - (void)selectCurrentSnippet { - if(snippetControlCounter > -1) - [self setSelectedRange:NSMakeRange(snippetControlArray[currentSnippetIndex][0], snippetControlArray[currentSnippetIndex][1])]; + if( snippetControlCounter > -1 + && currentSnippetIndex >= 0 + && currentSnippetIndex <= snippetControlMax + ) + { + if(currentSnippetIndex == snippetControlMax) { + [self setSelectedRange:NSMakeRange(snippetControlArray[snippetControlMax][0] + snippetControlArray[snippetControlMax][1], 0)]; + snippetControlCounter = -1; + currentSnippetIndex = -1; + snippetControlMax = -1; + return; + } + while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex < 20) { + currentSnippetIndex++; + } + if(currentSnippetIndex >= 0 && currentSnippetIndex < 20) + [self setSelectedRange:NSMakeRange(snippetControlArray[currentSnippetIndex][0], snippetControlArray[currentSnippetIndex][1])]; + else + snippetControlCounter = -1; + } else { + snippetControlCounter = -1; + } } - (void)insertFavoriteAsSnippet:(NSString*)theSnippet atRange:(NSRange)targetRange { + NSInteger i; + for(i=0; i<20; i++) { + snippetControlArray[i][0] = -1; + snippetControlArray[i][1] = -1; + snippetControlArray[i][2] = -1; + } if(theSnippet == nil || ![theSnippet length]) return; - NSMutableString *snip = [[NSMutableString string] autorelease]; - // NSString *re = @"(?<!\\\\)\\$\\{([^\\{\\}]*)\\}"; - [snip setString:theSnippet]; + NSMutableString *snip = [[NSMutableString alloc] initWithCapacity:[theSnippet length]]; + @try{ + NSString *re = @"(?<!\\\\)\\$\\{(1?\\d):([^\\{\\}]*)\\}"; + targetRange = NSIntersectionRange(NSMakeRange(0,[[self string] length]), targetRange); + [snip setString:theSnippet]; + if(snip == nil || ![snip length]) return; - snippetControlCounter = -1; - // while([snip isMatchedByRegex:re]) { - // snippetControlCounter++; - // NSRange hintRange = [snip rangeOfRegex:re capture:1L]; - // NSRange snipRange = [snip rangeOfRegex:re capture:0L]; - // [snip replaceCharactersInRange:snipRange withString:[snip substringWithRange:hintRange]]; - // snippetControlArray[snippetControlCounter][0] = snipRange.location + targetRange.location; - // snippetControlArray[snippetControlCounter][1] = snipRange.length-3; - // } - // - // if(snippetControlCounter > -1) { - // // Store the end for eventually tab out - // snippetControlCounter++; - // snippetControlArray[snippetControlCounter][0] = targetRange.location + [snip length]; - // snippetControlArray[snippetControlCounter][1] = 0; - // } + // Replace `${x:…}` by ${x:`…`} for convience + [snip replaceOccurrencesOfRegex:@"`\\$\\{(1?\\d):([^\\{\\}]*)\\}`" withString:@"${$1:`$2`}"]; + [snip flushCachedRegexData]; - [self breakUndoCoalescing]; - [self setSelectedRange:targetRange]; - snippetWasJustInserted = YES; - [self insertText:snip]; + snippetControlCounter = -1; + snippetControlMax = -1; + while([snip isMatchedByRegex:re]) { + [snip flushCachedRegexData]; + snippetControlCounter++; + NSRange snipRange = [snip rangeOfRegex:re capture:0L]; + NSInteger snipCnt = [[snip substringWithRange:[snip rangeOfRegex:re capture:1L]] intValue]; + NSRange hintRange = [snip rangeOfRegex:re capture:2L]; + + if(snipCnt>18 || snipCnt<0) { + NSLog(@"Only snippets in the range of 0…18 allowed."); + NSBeep(); + snippetControlCounter = -1; + break; + } - currentSnippetIndex = 0; - if(snippetControlCounter > -1) - [self selectCurrentSnippet]; + if(snipCnt>snippetControlMax) + snippetControlMax = snipCnt; + + [snip replaceCharactersInRange:snipRange withString:[snip substringWithRange:hintRange]]; + [snip flushCachedRegexData]; + snippetControlArray[snipCnt][0] = snipRange.location + targetRange.location; + snippetControlArray[snipCnt][1] = snipRange.length-4-((snipCnt>9)?2:1); + snippetControlArray[snipCnt][2] = 0; + // Adjust nested snippets + for(i=0; i<snipCnt; i++) { + if(snippetControlArray[i][0] > -1 + && snippetControlArray[i][0] >= snippetControlArray[snipCnt][0] + && snippetControlArray[i][1] <= snippetControlArray[snipCnt][1] + ) { + snippetControlArray[i][0] -= 3+((snipCnt>9)?2:1); + snippetControlArray[i][1] += 3+((snipCnt>9)?2:1); + } + } + } + + if(snippetControlCounter > -1) { + // Store the end for eventually tab out + snippetControlMax++; + snippetControlArray[snippetControlMax][0] = targetRange.location + [snip length]; + snippetControlArray[snippetControlMax][1] = 0; + snippetControlArray[snippetControlMax][2] = 0; + } + + [self breakUndoCoalescing]; + [self setSelectedRange:targetRange]; + snippetWasJustInserted = YES; + [self insertText:snip]; - snippetWasJustInserted = NO; + currentSnippetIndex = 0; + if(snippetControlCounter > -1) + [self selectCurrentSnippet]; + + snippetWasJustInserted = NO; + } + @catch(id ae) { + NSLog(@"Snippet Error: %@", [ae description]); + snippetControlCounter = -1; + snippetWasJustInserted = NO; + } + if(snip)[snip release]; } - (BOOL)checkForCaretInsideSnippet { - if(snippetControlCounter < 0 || currentSnippetIndex == snippetControlCounter) { + if(snippetControlCounter < 0 || currentSnippetIndex == snippetControlMax) { snippetControlCounter = -1; return NO; } @@ -854,8 +921,9 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) NSInteger caretPos = [self selectedRange].location; NSInteger i; - for(i=0; i<snippetControlCounter; i++) { - if(caretPos >= snippetControlArray[i][0] + for(i=0; i<snippetControlMax; i++) { + if(snippetControlArray[i][0] != -1 + && caretPos >= snippetControlArray[i][0] && caretPos <= snippetControlArray[i][0] + snippetControlArray[i][1]) { isCaretInsideASnippet = YES; @@ -915,9 +983,14 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) NSString *tabTrigger = [[self string] substringWithRange:targetRange]; // Is TAB trigger active change selection according to {SHIFT}TAB - if(snippetControlCounter > -1 && [self checkForCaretInsideSnippet]){ + if([self checkForCaretInsideSnippet] && snippetControlCounter > -1){ if(curFlags==(NSShiftKeyMask)) { + currentSnippetIndex--; + + while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex > -2) + currentSnippetIndex--; + if(currentSnippetIndex < 0) { snippetControlCounter = -1; } else { @@ -925,10 +998,15 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) return; } } else { + currentSnippetIndex++; - if(currentSnippetIndex > snippetControlCounter) { + + while(snippetControlArray[currentSnippetIndex][0] == -1 && currentSnippetIndex < 20) + currentSnippetIndex++; + + if(currentSnippetIndex > snippetControlMax) { snippetControlCounter = -1; - } else if(currentSnippetIndex == snippetControlCounter) { + } else if(currentSnippetIndex == snippetControlMax) { [self selectCurrentSnippet]; snippetControlCounter = -1; return; @@ -2846,13 +2924,14 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) if(snippetControlCounter > -1 && !snippetWasJustInserted) { NSInteger editStartPosition = [textStore editedRange].location; NSInteger changeInLength = [textStore changeInLength]; - NSInteger i; + NSInteger i, j, k; BOOL isCaretInsideASnippet = NO; - for(i=0; i<=snippetControlCounter; i++) { - if(editStartPosition >= snippetControlArray[i][0] + for(i=0; i<=snippetControlMax; i++) { + if(snippetControlArray[i][0] > -1 + && editStartPosition >= snippetControlArray[i][0] && editStartPosition <= snippetControlArray[i][0] + snippetControlArray[i][1]) { - if(i!=snippetControlCounter) + if(i!=snippetControlMax) isCaretInsideASnippet = YES; snippetControlArray[i][1] += changeInLength; if(snippetControlArray[i][1] < 0) { @@ -2860,7 +2939,7 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) break; } // Adjust start position of snippets after caret position - } else if(editStartPosition < snippetControlArray[i][0]) { + } else if(snippetControlArray[i][0] > -1 && editStartPosition < snippetControlArray[i][0]) { snippetControlArray[i][0] += changeInLength; if(snippetControlArray[i][1] < 0) { snippetControlCounter = -1; @@ -2868,6 +2947,23 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse) } } } + // If current snippet contains nested snippets then + // delete nested snippet definitions + // if(snippetControlArray[currentSnippetIndex][0] > -1 && currentSnippetIndex != snippetControlMax) + // for(j=0; j<snippetControlMax; j++) { + // if(snippetControlArray[j][0] > -1 + // && currentSnippetIndex != j + // && snippetControlArray[j][0] >= snippetControlArray[currentSnippetIndex][0] + // && snippetControlArray[j][0] <= snippetControlArray[currentSnippetIndex][0] + snippetControlArray[currentSnippetIndex][1] + // && snippetControlArray[j][0] + snippetControlArray[j][1] >= snippetControlArray[currentSnippetIndex][0] + // && snippetControlArray[j][0] + snippetControlArray[j][1] <= snippetControlArray[currentSnippetIndex][0] + snippetControlArray[currentSnippetIndex][1] + // ) { + // NSLog(@"%ld-%ld", currentSnippetIndex,j); + // snippetControlArray[j][0] = -1; + // snippetControlArray[j][1] = -1; + // snippetControlArray[j][2] = -1; + // } + // } if(!isCaretInsideASnippet) snippetControlCounter = -1; diff --git a/Source/SPNarrowDownCompletion.h b/Source/SPNarrowDownCompletion.h index 1927b671..de4e7a06 100644 --- a/Source/SPNarrowDownCompletion.h +++ b/Source/SPNarrowDownCompletion.h @@ -43,6 +43,7 @@ BOOL closeMe; BOOL caseSensitive; BOOL dictMode; + BOOL triggerMode; BOOL dbStructureMode; BOOL fuzzyMode; BOOL noFilterString; @@ -64,7 +65,7 @@ - (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 fuzzySearch:(BOOL)fuzzySearch + 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; - (void)setCaretPos:(NSPoint)aPos; diff --git a/Source/SPNarrowDownCompletion.m b/Source/SPNarrowDownCompletion.m index cc941924..a48aa204 100644 --- a/Source/SPNarrowDownCompletion.m +++ b/Source/SPNarrowDownCompletion.m @@ -132,7 +132,7 @@ - (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 fuzzySearch:(BOOL)fuzzySearch + 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 { @@ -153,6 +153,7 @@ cursorMovedLeft = caretMovedLeft; backtickMode = theBackTickMode; commaInsertionMode = NO; + triggerMode = tabTriggerMode; if(aStaticPrefix) staticPrefix = [aStaticPrefix retain]; @@ -546,6 +547,7 @@ [theTableView setBackgroundColor:[NSColor colorWithCalibratedRed:0.9f green:0.9f blue:0.9f alpha:1.0f]]; [self filter]; } else { + if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; break; } } @@ -580,6 +582,7 @@ else { [NSApp sendEvent:event]; + if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; break; } } @@ -589,8 +592,10 @@ [self completeAndInsertSnippet]; } else { [NSApp sendEvent:event]; - if(!NSPointInRect([NSEvent mouseLocation], [self frame])) + if(!NSPointInRect([NSEvent mouseLocation], [self frame])) { + if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; break; + } } } else @@ -598,7 +603,6 @@ [NSApp sendEvent:event]; } } - if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; [self close]; usleep(70); // tiny delay to suppress while continously pressing of ESC overlapping } @@ -647,7 +651,7 @@ [theView setSelectedRange:theCharRange]; [theView insertText:aString]; // If completion string contains backticks move caret out of the backticks - if(backtickMode) + if(backtickMode && !triggerMode) [theView performSelector:@selector(moveRight:)]; } |