aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPTextViewAdditions.m
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2010-11-15 21:25:26 +0000
committerBibiko <bibiko@eva.mpg.de>2010-11-15 21:25:26 +0000
commitcd4ae516d0db053c1bb818e617cf5b5bbebdaafc (patch)
tree98a6fbddc09798a67d7d207e5417c41af940745d /Source/SPTextViewAdditions.m
parent1fddbf3316c6d9b61952426f285d8ed4765cee45 (diff)
downloadsequelpro-cd4ae516d0db053c1bb818e617cf5b5bbebdaafc.tar.gz
sequelpro-cd4ae516d0db053c1bb818e617cf5b5bbebdaafc.tar.bz2
sequelpro-cd4ae516d0db053c1bb818e617cf5b5bbebdaafc.zip
• Bundle support
- outsourced code to SPAppController to centralise Bundle support and make it available for different scopes (query editor, input text fields, data tables etc.) - store bundle info scope-based - added input text field support - made usage of constants
Diffstat (limited to 'Source/SPTextViewAdditions.m')
-rw-r--r--Source/SPTextViewAdditions.m261
1 files changed, 261 insertions, 0 deletions
diff --git a/Source/SPTextViewAdditions.m b/Source/SPTextViewAdditions.m
index 262fa47c..381f8f0a 100644
--- a/Source/SPTextViewAdditions.m
+++ b/Source/SPTextViewAdditions.m
@@ -22,6 +22,9 @@
//
// More info at <http://code.google.com/p/sequel-pro/>
+#import "SPAlertSheets.h"
+#import "SPTooltip.h"
+
@implementation NSTextView (SPTextViewAdditions)
/*
@@ -482,6 +485,264 @@
[self setEditable:editableStatus];
}
+- (IBAction)executeBundleItemForInputField:(id)sender
+{
+
+ NSInteger idx = [sender tag] - 1000000;
+ NSString *infoPath = nil;
+ NSArray *bundleItems = [[NSApp delegate] bundleItemsForScope:SPBundleScopeInputField];
+ if(idx >=0 && idx < [bundleItems count]) {
+ infoPath = [[bundleItems objectAtIndex:idx] objectForKey:SPBundleInternPathToFileKey];
+ } else {
+ if([sender tag] == 0 && [[sender toolTip] length]) {
+ infoPath = [sender toolTip];
+ }
+ }
+
+ if(!infoPath) {
+ NSBeep();
+ return;
+ }
+
+ NSError *readError = nil;
+ NSString *convError = nil;
+ NSPropertyListFormat format;
+ NSDictionary *cmdData = nil;
+ NSData *pData = [NSData dataWithContentsOfFile:infoPath options:NSUncachedRead error:&readError];
+
+ cmdData = [[NSPropertyListSerialization propertyListFromData:pData
+ mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain];
+
+ if(!cmdData || readError != nil || [convError length] || !(format == NSPropertyListXMLFormat_v1_0 || format == NSPropertyListBinaryFormat_v1_0)) {
+ NSLog(@"“%@” file couldn't be read.", infoPath);
+ NSBeep();
+ if (cmdData) [cmdData release];
+ return;
+ } else {
+ if([cmdData objectForKey:SPBundleFileCommandKey] && [[cmdData objectForKey:SPBundleFileCommandKey] length]) {
+
+ NSString *cmd = [cmdData objectForKey:SPBundleFileCommandKey];
+ NSString *inputAction = @"";
+ NSString *inputFallBackAction = @"";
+ NSError *err = nil;
+
+ NSRange currentWordRange, currentSelectionRange, currentLineRange;
+
+ [[NSFileManager defaultManager] removeItemAtPath:SPBundleTaskInputFilePath error:nil];
+
+ if([cmdData objectForKey:SPBundleFileInputSourceKey])
+ inputAction = [[cmdData objectForKey:SPBundleFileInputSourceKey] lowercaseString];
+ if([cmdData objectForKey:SPBundleFileInputSourceFallBackKey])
+ inputFallBackAction = [[cmdData objectForKey:SPBundleFileInputSourceFallBackKey] lowercaseString];
+
+ currentSelectionRange = [self selectedRange];
+ currentWordRange = [self getRangeForCurrentWord];
+ currentLineRange = [[self string] lineRangeForRange:NSMakeRange([self selectedRange].location, 0)];
+
+ NSRange replaceRange = NSMakeRange(currentSelectionRange.location, 0);
+ if([inputAction isEqualToString:SPBundleInputSourceSelectedText]) {
+ if(!currentSelectionRange.length) {
+ if([inputFallBackAction isEqualToString:SPBundleInputSourceCurrentWord])
+ replaceRange = currentWordRange;
+ else if([inputFallBackAction isEqualToString:SPBundleInputSourceCurrentLine])
+ replaceRange = currentLineRange;
+ else if([inputAction isEqualToString:SPBundleInputSourceEntireContent])
+ replaceRange = NSMakeRange(0,[[self string] length]);
+ } else {
+ replaceRange = currentSelectionRange;
+ }
+
+ }
+ else if([inputAction isEqualToString:SPBundleInputSourceEntireContent]) {
+ replaceRange = NSMakeRange(0, [[self string] length]);
+ }
+
+ NSMutableDictionary *env = [NSMutableDictionary dictionary];
+ [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:@"SP_BUNDLE_PATH"];
+ [env setObject:SPBundleTaskInputFilePath forKey:@"SP_BUNDLE_INPUT_FILE"];
+
+ if(currentSelectionRange.length)
+ [env setObject:[[self string] substringWithRange:currentSelectionRange] forKey:@"SP_SELECTED_TEXT"];
+
+ if(![[[[[[NSApp delegate] frontDocumentWindow] delegate] selectedTableDocument] connectionID] isEqualToString:@"_"]) {
+
+ id tablesListInstance = [[[[[NSApp delegate] frontDocumentWindow] delegate] selectedTableDocument] valueForKeyPath:@"tablesListInstance"];
+
+ if (tablesListInstance && [tablesListInstance selectedDatabase])
+ [env setObject:[tablesListInstance selectedDatabase] forKey:@"SP_SELECTED_DATABASE"];
+
+ if (tablesListInstance && [tablesListInstance allDatabaseNames])
+ [env setObject:[[tablesListInstance allDatabaseNames] componentsJoinedBySpacesAndQuoted] forKey:@"SP_ALL_DATABASES"];
+
+ if (tablesListInstance && [tablesListInstance allTableNames])
+ [env setObject:[[tablesListInstance allTableNames] componentsJoinedBySpacesAndQuoted] forKey:@"SP_ALL_TABLES"];
+
+ if (tablesListInstance && [tablesListInstance allViewNames])
+ [env setObject:[[tablesListInstance allViewNames] componentsJoinedBySpacesAndQuoted] forKey:@"SP_ALL_VIEWS"];
+
+ if (tablesListInstance && [tablesListInstance allFunctionNames])
+ [env setObject:[[tablesListInstance allFunctionNames] componentsJoinedBySpacesAndQuoted] forKey:@"SP_ALL_FUNCTIONS"];
+
+ if (tablesListInstance && [tablesListInstance allProcedureNames])
+ [env setObject:[[tablesListInstance allProcedureNames] componentsJoinedBySpacesAndQuoted] forKey:@"SP_ALL_PROCEDURES"];
+
+ if (tablesListInstance && [tablesListInstance tableName])
+ [env setObject:[tablesListInstance tableName] forKey:@"SP_SELECTED_TABLE"];
+
+ if([[[[NSApp delegate] frontDocumentWindow] delegate] selectedTableDocument] && [[[[[NSApp delegate] frontDocumentWindow] delegate] selectedTableDocument] mySQLVersion])
+ [env setObject:[[[[[NSApp delegate] frontDocumentWindow] delegate] selectedTableDocument] mySQLVersion] forKey:@"SP_RDBMS_VERSION"];
+
+ }
+
+ if(1)
+ [env setObject:@"mysql" forKey:@"SP_RDBMS_TYPE"];
+
+ if(currentWordRange.length)
+ [env setObject:[[self string] substringWithRange:currentWordRange] forKey:@"SP_CURRENT_WORD"];
+
+ if(currentLineRange.length)
+ [env setObject:[[self string] substringWithRange:currentLineRange] forKey:@"SP_CURRENT_LINE"];
+
+ NSError *inputFileError = nil;
+ NSString *input = [NSString stringWithString:[[self string] substringWithRange:replaceRange]];
+ [input writeToFile:SPBundleTaskInputFilePath
+ atomically:YES
+ encoding:NSUTF8StringEncoding
+ error:&inputFileError];
+
+ if(inputFileError != nil) {
+ NSString *errorMessage = [inputFileError localizedDescription];
+ SPBeginAlertSheet(NSLocalizedString(@"Bundle Error", @"bundle error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [self window], self, nil, nil,
+ [NSString stringWithFormat:@"%@ “%@”:\n%@", NSLocalizedString(@"Error for", @"error for message"), [cmdData objectForKey:@"name"], errorMessage]);
+ if (cmdData) [cmdData release];
+ return;
+ }
+
+ NSString *output = [cmd runBashCommandWithEnvironment:env atCurrentDirectoryPath:nil error:&err];
+
+ [[NSFileManager defaultManager] removeItemAtPath:SPBundleTaskInputFilePath error:nil];
+
+ if(err == nil && [cmdData objectForKey:SPBundleFileOutputActionKey]) {
+ if([[cmdData objectForKey:SPBundleFileOutputActionKey] length]
+ && ![[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionNone]) {
+ NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString];
+
+ if([action isEqualToString:SPBundleOutputActionInsertAsText]) {
+ [self insertText:output];
+ }
+
+ else if([action isEqualToString:SPBundleOutputActionInsertAsSnippet]) {
+ [self insertAsSnippet:output atRange:replaceRange];
+ }
+
+ else if([action isEqualToString:SPBundleOutputActionReplaceContent]) {
+ if([[self string] length])
+ [self setSelectedRange:NSMakeRange(0, [[self string] length])];
+ [self insertText:output];
+ }
+
+ else if([action isEqualToString:SPBundleOutputActionReplaceSelection]) {
+ [self shouldChangeTextInRange:replaceRange replacementString:output];
+ [self replaceCharactersInRange:replaceRange withString:output];
+ }
+
+ else if([action isEqualToString:SPBundleOutputActionShowAsTextTooltip]) {
+ [SPTooltip showWithObject:output];
+ }
+
+ else if([action isEqualToString:SPBundleOutputActionShowAsHTMLTooltip]) {
+ [SPTooltip showWithObject:output ofType:@"html"];
+ }
+ }
+ } else {
+ NSString *errorMessage = [err localizedDescription];
+ SPBeginAlertSheet(NSLocalizedString(@"BASH Error", @"bash error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [self window], self, nil, nil,
+ [NSString stringWithFormat:@"%@ “%@”:\n%@", NSLocalizedString(@"Error for", @"error for message"), [cmdData objectForKey:@"name"], errorMessage]);
+ }
+
+ }
+
+ if (cmdData) [cmdData release];
+
+ }
+
+}
+
+/**
+ * Add Bundle menu items.
+ */
+- (NSMenu *)menuForEvent:(NSEvent *)event
+{
+
+ NSMenu *menu = [[self class] defaultMenu];
+
+ // Remove 'Bundles' sub menu and separator
+ NSMenuItem *bItem = [menu itemWithTag:10000000];
+ if(bItem) {
+ NSInteger sepIndex = [menu indexOfItem:bItem]-1;
+ [menu removeItemAtIndex:sepIndex];
+ [menu removeItem:bItem];
+ }
+
+ if([[[[[[NSApp delegate] frontDocumentWindow] delegate] selectedTableDocument] connectionID] isEqualToString:@"_"]) return menu;
+
+ [[NSApp delegate] reloadBundles:self];
+
+ NSArray *bundleCategories = [[NSApp delegate] bundleCategoriesForScope:SPBundleScopeInputField];
+ NSArray *bundleItems = [[NSApp delegate] bundleItemsForScope:SPBundleScopeInputField];
+
+ // Add 'Bundles' sub menu
+ [menu addItem:[NSMenuItem separatorItem]];
+
+ NSMenu *bundleMenu = [[[NSMenu alloc] init] autorelease];
+ NSMenuItem *bundleSubMenuItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Bundles", @"bundles menu item label") action:nil keyEquivalent:@""];
+ [bundleSubMenuItem setTag:10000000];
+
+ [menu addItem:bundleSubMenuItem];
+ [menu setSubmenu:bundleMenu forItem:bundleSubMenuItem];
+
+ NSMutableArray *categorySubMenus = [NSMutableArray array];
+ NSMutableArray *categoryMenus = [NSMutableArray array];
+ if([bundleCategories count]) {
+ for(NSString* title in bundleCategories) {
+ [categorySubMenus addObject:[[[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""] autorelease]];
+ [categoryMenus addObject:[[[NSMenu alloc] init] autorelease]];
+ [bundleMenu addItem:[categorySubMenus lastObject]];
+ [bundleMenu setSubmenu:[categoryMenus lastObject] forItem:[categorySubMenus lastObject]];
+ }
+ }
+
+ NSInteger i = 0;
+ for(NSDictionary *item in bundleItems) {
+
+ NSString *keyEq = @"";
+ // if([item objectForKey:SPBundleFileKeyEquivalentKey])
+ // keyEq = [[item objectForKey:SPBundleFileKeyEquivalentKey] objectAtIndex:0];
+ // else
+ // keyEq = @"";
+
+ NSMenuItem *mItem = [[[NSMenuItem alloc] initWithTitle:[item objectForKey:SPBundleInternLabelKey] action:@selector(executeBundleItemForInputField:) keyEquivalent:keyEq] autorelease];
+
+ if([keyEq length])
+ [mItem setKeyEquivalentModifierMask:[[[item objectForKey:SPBundleFileKeyEquivalentKey] objectAtIndex:1] intValue]];
+
+ if([item objectForKey:SPBundleFileTooltipKey])
+ [mItem setToolTip:[item objectForKey:SPBundleFileTooltipKey]];
+
+ [mItem setTag:1000000 + i++];
+
+ if([item objectForKey:SPBundleFileCategoryKey]) {
+ [[categoryMenus objectAtIndex:[bundleCategories indexOfObject:[item objectForKey:SPBundleFileCategoryKey]]] addItem:mItem];
+ } else {
+ [bundleMenu addItem:mItem];
+ }
+ }
+
+ [bundleSubMenuItem release];
+
+ return menu;
+
+}
#pragma mark -
#pragma mark multi-touch trackpad support