aboutsummaryrefslogtreecommitdiffstats
path: root/Source/CMTextView.m
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2010-01-24 21:39:43 +0000
committerBibiko <bibiko@eva.mpg.de>2010-01-24 21:39:43 +0000
commitcca4f8dc17e904c516dc7e3ba8193aff5b8f9e70 (patch)
tree8d837c62de411b7e939ca06a4181cefcae688eb0 /Source/CMTextView.m
parent9997d982ca4fcbacb04b41c7f7e2aa7dd44db312 (diff)
downloadsequelpro-cca4f8dc17e904c516dc7e3ba8193aff5b8f9e70.tar.gz
sequelpro-cca4f8dc17e904c516dc7e3ba8193aff5b8f9e70.tar.bz2
sequelpro-cca4f8dc17e904c516dc7e3ba8193aff5b8f9e70.zip
• added possibility to add a query favorite by user-definable alphanumeric tab trigger; eg if tab trigger is set to "sel" sel⇥ will insert the first query which has the defined the tab trigger
• preparations to insert programmable query favorites - eg "SELECT ${*} FROM ${Table}" -- after insertion "SELECT * FROM Table" the '*' is highlighted to change, press ⇥ to select the next snippet 'Table'; ⇧⇥ selects the previous snippet; the snippet selection follows the user input - Note: not yet active
Diffstat (limited to 'Source/CMTextView.m')
-rw-r--r--Source/CMTextView.m148
1 files changed, 146 insertions, 2 deletions
diff --git a/Source/CMTextView.m b/Source/CMTextView.m
index 4b42d009..26c5790d 100644
--- a/Source/CMTextView.m
+++ b/Source/CMTextView.m
@@ -30,6 +30,7 @@
#import "SPTextViewAdditions.h"
#import "SPNarrowDownCompletion.h"
#import "SPConstants.h"
+#import "SPQueryController.h"
#pragma mark -
#pragma mark lex init
@@ -86,6 +87,7 @@ YY_BUFFER_STATE yy_scan_string (const char *);
autohelpEnabled = NO;
delBackwardsWasPressed = NO;
startListeningToBoundChanges = NO;
+ snippetControlCounter = -1;
lineNumberView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
[scrollView setVerticalRulerView:lineNumberView];
@@ -796,6 +798,74 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
}
+- (void)selectCurrentSnippet
+{
+ if(snippetControlCounter > -1)
+ [self setSelectedRange:NSMakeRange(snippetControlArray[currentSnippetIndex][0], snippetControlArray[currentSnippetIndex][1])];
+}
+
+- (void)insertFavoriteAsSnippet:(NSString*)theSnippet atRange:(NSRange)targetRange
+{
+
+ if(theSnippet == nil || ![theSnippet length]) return;
+
+ NSMutableString *snip = [[NSMutableString string] autorelease];
+ // NSString *re = @"(?<!\\\\)\\$\\{([^\\{\\}]*)\\}";
+ [snip setString:theSnippet];
+
+ 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;
+ // }
+
+ [self breakUndoCoalescing];
+ [self setSelectedRange:targetRange];
+ snippetWasJustInserted = YES;
+ [self insertText:snip];
+
+ currentSnippetIndex = 0;
+ if(snippetControlCounter > -1)
+ [self selectCurrentSnippet];
+
+ snippetWasJustInserted = NO;
+}
+
+- (BOOL)checkForCaretInsideSnippet
+{
+
+ if(snippetControlCounter < 0 || currentSnippetIndex == snippetControlCounter) {
+ snippetControlCounter = -1;
+ return NO;
+ }
+
+ BOOL isCaretInsideASnippet = NO;
+ NSInteger caretPos = [self selectedRange].location;
+ NSInteger i;
+
+ for(i=0; i<snippetControlCounter; i++) {
+ if(caretPos >= snippetControlArray[i][0]
+ && caretPos <= snippetControlArray[i][0] + snippetControlArray[i][1]) {
+
+ isCaretInsideASnippet = YES;
+ break;
+ }
+ }
+ // if(!isCaretInsideASnippet)
+ // snippetControlCounter = -1;
+ return isCaretInsideASnippet;
+}
/*
* Handle some keyDown events in order to provide autopairing functionality (if enabled).
*/
@@ -839,6 +909,45 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
return;
}
+ // Check for {SHIFT}TAB to insert favorites via TAB-trigger if CMTextView belongs to CustomQuery
+ if ([theEvent keyCode] == 48 && [self isEditable] && [[self delegate] isKindOfClass:[CustomQuery class]]){
+ NSRange targetRange = [self getRangeForCurrentWord];
+ NSString *tabTrigger = [[self string] substringWithRange:targetRange];
+
+ // Is TAB trigger active change selection according to {SHIFT}TAB
+ if(snippetControlCounter > -1 && [self checkForCaretInsideSnippet]){
+ if(curFlags==(NSShiftKeyMask)) {
+ currentSnippetIndex--;
+ if(currentSnippetIndex < 0) {
+ snippetControlCounter = -1;
+ } else {
+ [self selectCurrentSnippet];
+ return;
+ }
+ } else {
+ currentSnippetIndex++;
+ if(currentSnippetIndex > snippetControlCounter) {
+ snippetControlCounter = -1;
+ } else if(currentSnippetIndex == snippetControlCounter) {
+ [self selectCurrentSnippet];
+ snippetControlCounter = -1;
+ return;
+ } else {
+ [self selectCurrentSnippet];
+ return;
+ }
+ }
+ }
+ // Check if tab-trigger is defined; if so insert it
+ if(snippetControlCounter < 0 && [[[self window] delegate] fileURL]) {
+ NSArray *snippets = [[SPQueryController sharedQueryController] queryFavoritesForFileURL:[[[self window] delegate] fileURL] andTabTrigger:tabTrigger includeGlobals:YES];
+ if([snippets count] > 0 && [(NSString*)[(NSDictionary*)[snippets objectAtIndex:0] objectForKey:@"query"] length]) {
+ [self insertFavoriteAsSnippet:[(NSDictionary*)[snippets objectAtIndex:0] objectForKey:@"query"] atRange:targetRange];
+ return;
+ }
+ }
+ }
+
// Note: switch(insertedCharacter) {} does not work instead use charactersIgnoringModifiers
if([charactersIgnMod isEqualToString:@"c"]) // ^C copy as RTF
if(curFlags==(NSControlKeyMask))
@@ -2719,9 +2828,12 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
//make sure that the notification is from the correct textStorage object
if (textStore!=[self textStorage]) return;
+ NSInteger editedMask = [textStore editedMask];
+
// Start autohelp only if the user really changed the text (not e.g. for setting a background color)
- if([prefs boolForKey:SPCustomQueryUpdateAutoHelp] && [textStore editedMask] != 1)
+ if([prefs boolForKey:SPCustomQueryUpdateAutoHelp] && editedMask != 1) {
[self performSelector:@selector(autoHelp) withObject:nil afterDelay:[[[prefs valueForKey:SPCustomQueryAutoHelpDelay] retain] doubleValue]];
+ }
if([[self string] length] > SP_TEXT_SIZE_TRIGGER_FOR_PARTLY_PARSING)
[NSObject cancelPreviousPerformRequestsWithTarget:self
@@ -2729,8 +2841,40 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
object:nil];
// Do syntax highlighting only if the user really changed the text
- if([textStore editedMask] != 1){
+ if(editedMask != 1) {
+
+ if(snippetControlCounter > -1 && !snippetWasJustInserted) {
+ NSInteger editStartPosition = [textStore editedRange].location;
+ NSInteger changeInLength = [textStore changeInLength];
+ NSInteger i;
+ BOOL isCaretInsideASnippet = NO;
+ for(i=0; i<=snippetControlCounter; i++) {
+ if(editStartPosition >= snippetControlArray[i][0]
+ && editStartPosition <= snippetControlArray[i][0] + snippetControlArray[i][1]) {
+
+ if(i!=snippetControlCounter)
+ isCaretInsideASnippet = YES;
+ snippetControlArray[i][1] += changeInLength;
+ if(snippetControlArray[i][1] < 0) {
+ snippetControlCounter = -1;
+ break;
+ }
+ // Adjust start position of snippets after caret position
+ } else if(editStartPosition < snippetControlArray[i][0]) {
+ snippetControlArray[i][0] += changeInLength;
+ if(snippetControlArray[i][1] < 0) {
+ snippetControlCounter = -1;
+ break;
+ }
+ }
+ }
+ if(!isCaretInsideASnippet)
+ snippetControlCounter = -1;
+
+ }
+
[self doSyntaxHighlighting];
+
}
startListeningToBoundChanges = YES;