aboutsummaryrefslogtreecommitdiffstats
path: root/Source
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
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')
-rw-r--r--Source/CMTextView.h8
-rw-r--r--Source/CMTextView.m148
-rw-r--r--Source/CustomQuery.m24
-rw-r--r--Source/SPQueryController.m4
-rw-r--r--Source/SPQueryFavoriteManager.h1
-rw-r--r--Source/SPQueryFavoriteManager.m20
6 files changed, 196 insertions, 9 deletions
diff --git a/Source/CMTextView.h b/Source/CMTextView.h
index 868e7093..137c5348 100644
--- a/Source/CMTextView.h
+++ b/Source/CMTextView.h
@@ -59,6 +59,11 @@ static inline void NSMutableAttributedStringAddAttributeValueRange (NSMutableAtt
MCPConnection *mySQLConnection;
NSInteger mySQLmajorVersion;
+ NSInteger snippetControlArray[20][2];
+ NSInteger snippetControlCounter;
+ NSInteger currentSnippetIndex;
+ BOOL snippetWasJustInserted;
+
}
- (IBAction)showMySQLHelpForCurrentWord:(id)sender;
@@ -91,6 +96,9 @@ static inline void NSMutableAttributedStringAddAttributeValueRange (NSMutableAtt
- (NSArray *)suggestionsForSQLCompletionWith:(NSString *)currentWord dictMode:(BOOL)isDictMode browseMode:(BOOL)dbBrowseMode withTableName:(NSString*)aTableName withDbName:(NSString*)aDbName;
- (void) selectCurrentQuery;
+- (BOOL)checkForCaretInsideSnippet;
+- (void)insertFavoriteAsSnippet:(NSString*)theSnippet atRange:(NSRange)targetRange;
+
- (NSUInteger)characterIndexOfPoint:(NSPoint)aPoint;
- (void)insertFileContentOfFile:(NSString *)aPath;
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;
diff --git a/Source/CustomQuery.m b/Source/CustomQuery.m
index b536491b..2e3b16c4 100644
--- a/Source/CustomQuery.m
+++ b/Source/CustomQuery.m
@@ -215,7 +215,7 @@
[textView setSelectedRange:NSMakeRange(0,[[textView string] length])];
// The actual query strings have been already stored as tooltip
- [textView insertText:[[queryFavoritesButton selectedItem] toolTip]];
+ [textView insertFavoriteAsSnippet:[[queryFavoritesButton selectedItem] toolTip] atRange:[textView selectedRange]];
}
}
@@ -2020,6 +2020,7 @@
// Ensure that the notification is from the custom query text view
if ( [aNotification object] != textView ) return;
+ [textView checkForCaretInsideSnippet];
// Remove all background color attributes used by highlighting the current query
if([prefs boolForKey:SPCustomQueryHighlightCurrentQuery]) {
// Remove only the background attribute for the current range if still valid
@@ -2701,8 +2702,17 @@
[menu addItem:headerMenuItem];
[headerMenuItem release];
for (NSDictionary *favorite in [[SPQueryController sharedQueryController] favoritesForFileURL:[tableDocumentInstance fileURL]]) {
- NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithString:[favorite objectForKey:@"name"]] action:NULL keyEquivalent:@""];
+ if (![favorite isKindOfClass:[NSDictionary class]] || ![favorite objectForKey:@"name"]) continue;
+ NSMutableParagraphStyle *paraStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
+ [paraStyle setTabStops:[NSArray array]];
+ [paraStyle addTabStop:[[[NSTextTab alloc] initWithType:NSRightTabStopType location:190.0] autorelease]];
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:paraStyle, [NSFont systemFontOfSize:11], nil] forKeys:[NSArray arrayWithObjects:NSParagraphStyleAttributeName, NSFontAttributeName, nil]];
+ NSAttributedString *titleString = [[[NSAttributedString alloc]
+ initWithString:([favorite objectForKey:@"tabtrigger"] && [(NSString*)[favorite objectForKey:@"tabtrigger"] length]) ? [NSString stringWithFormat:@"%@\t%@⇥", [favorite objectForKey:@"name"], [favorite objectForKey:@"tabtrigger"]] : [favorite objectForKey:@"name"]
+ attributes:attributes] autorelease];
+ NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:@""];
[item setToolTip:[NSString stringWithString:[favorite objectForKey:@"query"]]];
+ [item setAttributedTitle:titleString];
[item setIndentationLevel:1];
[menu addItem:item];
[item release];
@@ -2717,8 +2727,16 @@
[headerMenuItem release];
for (NSDictionary *favorite in [prefs objectForKey:SPQueryFavorites]) {
if (![favorite isKindOfClass:[NSDictionary class]] || ![favorite objectForKey:@"name"]) continue;
- NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[NSString stringWithString:[favorite objectForKey:@"name"]] action:NULL keyEquivalent:@""];
+ NSMutableParagraphStyle *paraStyle = [[[NSMutableParagraphStyle alloc] init] autorelease];
+ [paraStyle setTabStops:[NSArray array]];
+ [paraStyle addTabStop:[[[NSTextTab alloc] initWithType:NSRightTabStopType location:190.0] autorelease]];
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:paraStyle, [NSFont systemFontOfSize:11], nil] forKeys:[NSArray arrayWithObjects:NSParagraphStyleAttributeName, NSFontAttributeName, nil]];
+ NSAttributedString *titleString = [[[NSAttributedString alloc]
+ initWithString:([favorite objectForKey:@"tabtrigger"] && [(NSString*)[favorite objectForKey:@"tabtrigger"] length]) ? [NSString stringWithFormat:@"%@\t%@⇥", [favorite objectForKey:@"name"], [favorite objectForKey:@"tabtrigger"]] : [favorite objectForKey:@"name"]
+ attributes:attributes] autorelease];
+ NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"" action:NULL keyEquivalent:@""];
[item setToolTip:[NSString stringWithString:[favorite objectForKey:@"query"]]];
+ [item setAttributedTitle:titleString];
[item setIndentationLevel:1];
[menu addItem:item];
[item release];
diff --git a/Source/SPQueryController.m b/Source/SPQueryController.m
index 37b4aa97..9f28c226 100644
--- a/Source/SPQueryController.m
+++ b/Source/SPQueryController.m
@@ -664,8 +664,10 @@ static SPQueryController *sharedQueryController = nil;
if(includeGlobals && [prefs objectForKey:SPQueryFavorites]) {
for(id fav in [prefs objectForKey:SPQueryFavorites]) {
- if([fav objectForKey:@"tabtrigger"] && [[fav objectForKey:@"tabtrigger"] isEqualToString:tabTrigger])
+ if([fav objectForKey:@"tabtrigger"] && [[fav objectForKey:@"tabtrigger"] isEqualToString:tabTrigger]) {
[result addObject:fav];
+ break;
+ }
}
}
diff --git a/Source/SPQueryFavoriteManager.h b/Source/SPQueryFavoriteManager.h
index 9318ed22..2a9c3c56 100644
--- a/Source/SPQueryFavoriteManager.h
+++ b/Source/SPQueryFavoriteManager.h
@@ -41,6 +41,7 @@
IBOutlet NSPopUpButton *encodingPopUp;
IBOutlet NSTableView *favoritesTableView;
IBOutlet NSTextField *favoriteNameTextField;
+ IBOutlet NSTextField *favoriteTabTriggerTextField;
IBOutlet NSTextView *favoriteQueryTextView;
IBOutlet NSButton *removeButton;
IBOutlet BWAnchoredButtonBar *splitViewButtonBar;
diff --git a/Source/SPQueryFavoriteManager.m b/Source/SPQueryFavoriteManager.m
index 2745f83c..a6f8941b 100644
--- a/Source/SPQueryFavoriteManager.m
+++ b/Source/SPQueryFavoriteManager.m
@@ -29,6 +29,7 @@
#import "SPQueryController.h"
#import "SPConstants.h"
#import "SPConnectionController.h"
+#import "RegexKitLite.h"
#define SP_MULTIPLE_SELECTION_PLACEHOLDER_STRING NSLocalizedString(@"[multiple selection]", @"[multiple selection]")
#define SP_NO_SELECTION_PLACEHOLDER_STRING NSLocalizedString(@"[no selection]", @"[no selection]")
@@ -415,9 +416,15 @@
*/
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
- if(![[favorites objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]]) return @"";
- return [[favorites objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]];
+ if([[aTableColumn identifier] isEqualToString:@"name"]) {
+ if(![[favorites objectAtIndex:rowIndex] objectForKey:@"name"]) return @"";
+ return [[favorites objectAtIndex:rowIndex] objectForKey:@"name"];
+ } else if([[aTableColumn identifier] isEqualToString:@"tabtrigger"]) {
+ if(![[favorites objectAtIndex:rowIndex] objectForKey:@"tabtrigger"] || ![(NSString*)[[favorites objectAtIndex:rowIndex] objectForKey:@"tabtrigger"] length]) return @"";
+ return [NSString stringWithFormat:@"%@⇥", [[favorites objectAtIndex:rowIndex] objectForKey:@"tabtrigger"]];
+ }
+ return @"";
}
/*
@@ -511,7 +518,7 @@
}
/*
- * Changes in the name text field will be saved in data source directly
+ * Changes in the name/tabtrigger text field will be saved in data source directly
* to update the table view accordingly
*/
- (void)controlTextDidChange:(NSNotification *)notification
@@ -525,6 +532,13 @@
if(object == favoriteNameTextField) {
[[favorites objectAtIndex:[favoritesTableView selectedRow]] setObject:[favoriteNameTextField stringValue] forKey:@"name"];
[favoritesTableView reloadData];
+ }
+ else if(object == favoriteTabTriggerTextField){
+ //Validate trigger - it only may contain alphnumeric characters
+ NSString *tabTrigger = [NSString stringWithString:[[favoriteTabTriggerTextField stringValue] stringByReplacingOccurrencesOfRegex:@"[^\\w0-9]" withString:@""]];
+ [favoriteTabTriggerTextField setStringValue:tabTrigger];
+ [[favorites objectAtIndex:[favoritesTableView selectedRow]] setObject:tabTrigger forKey:@"tabtrigger"];
+ [favoritesTableView reloadData];
}
}