From d51530a48813b08d9694fed3a7a24998d495d5b5 Mon Sep 17 00:00:00 2001 From: Bibiko Date: Wed, 8 Dec 2010 11:05:28 +0000 Subject: =?UTF-8?q?=E2=80=A2=20Bundle=20commands=20-=20reworked=20invocati?= =?UTF-8?q?on=20via=20keyboard=20short-cut=20to=20allow=20to=20fall=20back?= =?UTF-8?q?=20to=20General=20scope=20-=20added=20chance=20to=20redirect=20?= =?UTF-8?q?the=20output=20action=20via=20command=20exit=20codes;=20useful?= =?UTF-8?q?=20if=20the=20normal=20output=20is=20an=20HTML=20window=20but?= =?UTF-8?q?=20an=20error=20occurred,=20now=20one=20can=20display=20the=20e?= =?UTF-8?q?rror=20as=20tooltip=20for=20instance=20-=20unified=20file=20han?= =?UTF-8?q?d-shake=20file=20names=20by=20one=20uuid=20-=20made=20usage=20o?= =?UTF-8?q?f=20more=20constants=20and=20renamed=20some=20shell=20vars?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Interfaces/English.lproj/BundleEditor.xib | 2 +- Source/SPAppController.m | 140 ++++++++++++++++++++---------- Source/SPConstants.h | 23 +++++ Source/SPConstants.m | 31 ++++++- Source/SPCopyTable.m | 49 +++++++++-- Source/SPStringAdditions.m | 79 ++++++++++------- Source/SPTextViewAdditions.m | 48 +++++++++- 7 files changed, 283 insertions(+), 89 deletions(-) diff --git a/Interfaces/English.lproj/BundleEditor.xib b/Interfaces/English.lproj/BundleEditor.xib index 96c6df70..8bcfbdd1 100644 --- a/Interfaces/English.lproj/BundleEditor.xib +++ b/Interfaces/English.lproj/BundleEditor.xib @@ -3441,7 +3441,7 @@ ToolTip - Choose the input source for the command. The desired data will be available as UTF-8 encoded file whose name will be passed as shell variable SP_BUNDLE_INPUT_FILE + Choose the input source for the command. The desired data will be available as UTF-8 encoded file whose name will be passed as shell variable SP_BUNDLE_INPUT which will be piped to the script (STDIN) com.apple.InterfaceBuilder.CocoaPlugin diff --git a/Source/SPAppController.m b/Source/SPAppController.m index 7d6c11ed..63011789 100644 --- a/Source/SPAppController.m +++ b/Source/SPAppController.m @@ -640,7 +640,7 @@ // Try to find the SPDatabaseDocument which sent the the url scheme command // For speed check the front most first otherwise iterate through all - if(passedProcessID) { + if(passedProcessID && [passedProcessID length]) { if([activeProcessID isEqualToString:passedProcessID]) { processDocument = [[[self frontDocumentWindow] delegate] selectedTableDocument]; } else { @@ -691,18 +691,26 @@ return; } - // If command failed notify the file handle hand shake mechanism - NSString *out = @"1"; - [out writeToFile:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, passedProcessID] - atomically:YES - encoding:NSUTF8StringEncoding - error:nil]; - out = @"Scheme Error"; - [out writeToFile:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, passedProcessID] - atomically:YES - encoding:NSUTF8StringEncoding - error:nil]; + if(processDocument != nil) { + // If command failed notify the file handle hand shake mechanism + NSString *out = @"1"; + [out writeToFile:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, passedProcessID] + atomically:YES + encoding:NSUTF8StringEncoding + error:nil]; + out = @"Scheme Error"; + [out writeToFile:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, passedProcessID] + atomically:YES + encoding:NSUTF8StringEncoding + error:nil]; + } + if(passedProcessID == nil || ![passedProcessID length]) { + SPBeginAlertSheet(NSLocalizedString(@"sequelpro URL Scheme Error", @"sequelpro url Scheme Error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil, + [NSString stringWithFormat:@"%@ “%@”:\n%@", NSLocalizedString(@"Error for", @"error for message"), [command description], NSLocalizedString(@"An error occur while executing a scheme command. If the scheme command was invoked by a Bundle command, it could be that the command still runs. You can try to terminate it by pressing ⌘+. or via the Activities pane.", @"an error occur while executing a scheme command. if the scheme command was invoked by a bundle command, it could be that the command still runs. you can try to terminate it by pressing ⌘+. or via the activities pane.")]); + } else { + NSBeep(); + } if(processDocument) NSLog(@"process doc ID: %@\n%@", [processDocument processID], [processDocument tabTitleForTooltip]); @@ -753,40 +761,18 @@ NSString *inputAction = @""; NSString *inputFallBackAction = @""; NSError *err = nil; - NSString *bundleInputFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskInputFilePath, [NSString stringWithNewUUID]]; + NSString *uuid = [NSString stringWithNewUUID]; + NSString *bundleInputFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskInputFilePath, uuid]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; - if([cmdData objectForKey:SPBundleFileInputSourceKey]) - inputAction = [[cmdData objectForKey:SPBundleFileInputSourceKey] lowercaseString]; - if([cmdData objectForKey:SPBundleFileInputSourceFallBackKey]) - inputFallBackAction = [[cmdData objectForKey:SPBundleFileInputSourceFallBackKey] lowercaseString]; - NSMutableDictionary *env = [NSMutableDictionary dictionary]; - [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:@"SP_BUNDLE_PATH"]; - [env setObject:bundleInputFilePath forKey:@"SP_BUNDLE_INPUT_FILE"]; + [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:SPBundleShellVariableBundlePath]; + [env setObject:bundleInputFilePath forKey:SPBundleShellVariableInputFilePath]; + [env setObject:SPBundleScopeGeneral forKey:SPBundleShellVariableScope]; - NSError *inputFileError = nil; NSString *input = @""; - if([inputAction isEqualToString:SPBundleInputSourceSelectedTableRowsAsTab]) { - input = [self rowsAsTabStringWithHeaders:YES onlySelectedRows:YES]; - } - else if([inputAction isEqualToString:SPBundleInputSourceSelectedTableRowsAsCsv]) { - input = [self rowsAsCsvStringWithHeaders:YES onlySelectedRows:YES]; - } - else if([inputAction isEqualToString:SPBundleInputSourceSelectedTableRowsAsSqlInsert]) { - input = [self rowsAsSqlInsertsOnlySelectedRows:YES]; - } - else if([inputAction isEqualToString:SPBundleInputSourceTableRowsAsTab]) { - input = [self rowsAsTabStringWithHeaders:YES onlySelectedRows:NO]; - } - else if([inputAction isEqualToString:SPBundleInputSourceTableRowsAsCsv]) { - input = [self rowsAsCsvStringWithHeaders:YES onlySelectedRows:NO]; - } - else if([inputAction isEqualToString:SPBundleInputSourceTableRowsAsSqlInsert]) { - input = [self rowsAsSqlInsertsOnlySelectedRows:NO]; - } - + NSError *inputFileError = nil; if(input == nil) input = @""; [input writeToFile:bundleInputFilePath atomically:YES @@ -795,7 +781,7 @@ if(inputFileError != nil) { NSString *errorMessage = [inputFileError localizedDescription]; - SPBeginAlertSheet(NSLocalizedString(@"Bundle Error", @"bundle error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, [NSApp mainWindow], self, nil, nil, + 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; @@ -807,15 +793,53 @@ contextInfo:[NSDictionary dictionaryWithObjectsAndKeys: ([cmdData objectForKey:SPBundleFileNameKey])?:@"-", @"name", NSLocalizedString(@"General", @"general menu item label"), @"scope", + uuid, SPBundleFileInternalexecutionUUID, nil] error:&err]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; + NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; + + // Redirect due exit code + if(err != nil) { + if([err code] == SPBundleRedirectActionNone) { + action = SPBundleOutputActionNone; + err = nil; + } + else if([err code] == SPBundleRedirectActionReplaceSection) { + action = SPBundleOutputActionReplaceSelection; + err = nil; + } + else if([err code] == SPBundleRedirectActionReplaceContent) { + action = SPBundleOutputActionReplaceContent; + err = nil; + } + else if([err code] == SPBundleRedirectActionInsertAsText) { + action = SPBundleOutputActionInsertAsText; + err = nil; + } + else if([err code] == SPBundleRedirectActionInsertAsSnippet) { + action = SPBundleOutputActionInsertAsSnippet; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsHTML) { + action = SPBundleOutputActionShowAsHTML; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsTextTooltip) { + action = SPBundleOutputActionShowAsTextTooltip; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsHTMLTooltip) { + action = SPBundleOutputActionShowAsHTMLTooltip; + err = nil; + } + } + if(err == nil && output) { if([cmdData objectForKey:SPBundleFileOutputActionKey] && [[cmdData objectForKey:SPBundleFileOutputActionKey] length] && ![[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionNone]) { - NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; NSPoint pos = [NSEvent mouseLocation]; pos.y -= 16; @@ -1411,7 +1435,7 @@ [mItem setTag:1000000 + i++]; [mItem setRepresentedObject:[NSDictionary dictionaryWithObjectsAndKeys: scope, @"scope", - [item objectForKey:@"key"], @"key", nil]]; + ([item objectForKey:@"key"])?:@"", @"key", nil]]; if([item objectForKey:SPBundleFileCategoryKey]) { [[categoryMenus objectAtIndex:[bundleCategories indexOfObject:[item objectForKey:SPBundleFileCategoryKey]]] addItem:mItem]; @@ -1433,16 +1457,42 @@ - (IBAction)bundleCommandDispatcher:(id)sender { - BOOL checkForKeyEquivalents = ([[NSApp currentEvent] type] == NSKeyDown) ? YES : NO; + NSEvent *event = [NSApp currentEvent]; + BOOL checkForKeyEquivalents = ([event type] == NSKeyDown) ? YES : NO; + + id firstResponder = [[NSApp mainWindow] firstResponder]; NSString *scope = [[sender representedObject] objectForKey:@"scope"]; NSString *keyEqKey = nil; NSMutableArray *assignedKeyEquivalents = nil; if(checkForKeyEquivalents) { + + // Get the current scope in order to find out which command with a specific key + // should run + if([firstResponder respondsToSelector:@selector(executeBundleItemForInputField:)]) + scope = SPBundleScopeInputField; + else if([firstResponder respondsToSelector:@selector(executeBundleItemForDataTable:)]) + scope = SPBundleScopeDataTable; + else + scope = SPBundleScopeGeneral; + keyEqKey = [[sender representedObject] objectForKey:@"key"]; + assignedKeyEquivalents = [NSMutableArray array]; [assignedKeyEquivalents setArray:[[bundleKeyEquivalents objectForKey:scope] objectForKey:keyEqKey]]; + // Fall back to general scope and check for key + if(![assignedKeyEquivalents count]) { + scope = SPBundleScopeGeneral; + [assignedKeyEquivalents setArray:[[bundleKeyEquivalents objectForKey:scope] objectForKey:keyEqKey]]; + } + // Nothing found thus bail + if(![assignedKeyEquivalents count]) { + NSBeep(); + return; + } + + // Sort if more than one found if([assignedKeyEquivalents count] > 1) { NSSortDescriptor *aSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease]; NSArray *sorted = [assignedKeyEquivalents sortedArrayUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]]; @@ -1450,8 +1500,6 @@ } } - id firstResponder = [[NSApp mainWindow] firstResponder]; - if([scope isEqualToString:SPBundleScopeInputField] && [firstResponder respondsToSelector:@selector(executeBundleItemForInputField:)]) { if(checkForKeyEquivalents && [assignedKeyEquivalents count]) { NSInteger idx = 0; diff --git a/Source/SPConstants.h b/Source/SPConstants.h index c219a381..1e48f2c2 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -473,6 +473,7 @@ extern NSString *SPBundleFileInputSourceFallBackKey; extern NSString *SPBundleFileOutputActionKey; extern NSString *SPBundleFileKeyEquivalentKey; extern NSString *SPBundleFileInternalKeyEquivalentKey; +extern NSString *SPBundleFileInternalexecutionUUID; extern NSString *SPBundleFileTooltipKey; extern NSString *SPBundleFileDisabledKey; extern NSString *SPBundleFileAuthorKey; @@ -486,10 +487,32 @@ extern NSString *SPBundleInternPathToFileKey; extern NSString *SPBundleInternKeyEquivalentKey; extern NSString *SPBundleFileName; extern NSString *SPBundleTaskInputFilePath; +extern NSString *SPBundleTaskOutputFilePath; extern NSString *SPBundleTaskScriptCommandFilePath; extern NSString *SPBundleTaskCopyBlobFileDirectory; extern NSString *SPBundleTaskTableMetaDataFilePath; +extern NSString *SPBundleShellVariableInputFilePath; +extern NSString *SPBundleShellVariableOutputFilePath; +extern NSString *SPBundleShellVariableBundlePath; +extern NSString *SPBundleShellVariableBlobFileDirectory; +extern NSString *SPBundleShellVariableQueryFile; +extern NSString *SPBundleShellVariableQueryResultFile; +extern NSString *SPBundleShellVariableQueryResultStatusFile; +extern NSString *SPBundleShellVariableQueryResultMetaFile; +extern NSString *SPBundleShellVariableInputTableMetaData; +extern NSString *SPBundleShellVariableScope; + +extern const NSInteger SPBundleRedirectActionNone; +extern const NSInteger SPBundleRedirectActionReplaceSection; +extern const NSInteger SPBundleRedirectActionReplaceContent; +extern const NSInteger SPBundleRedirectActionInsertAsText; +extern const NSInteger SPBundleRedirectActionInsertAsSnippet; +extern const NSInteger SPBundleRedirectActionShowAsHTML; +extern const NSInteger SPBundleRedirectActionShowAsTextTooltip; +extern const NSInteger SPBundleRedirectActionShowAsHTMLTooltip; +extern const NSInteger SPBundleRedirectActionLastCode; + // sequel URL scheme extern NSString *SPURLSchemeQueryInputPathHeader; extern NSString *SPURLSchemeQueryResultPathHeader; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index 607f2420..cd683a5b 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -285,6 +285,7 @@ NSString *SPBundleFileInputSourceFallBackKey = @"input_fallback"; NSString *SPBundleFileOutputActionKey = @"output"; NSString *SPBundleFileKeyEquivalentKey = @"keyEquivalent"; NSString *SPBundleFileInternalKeyEquivalentKey = @"internalKeyEquivalent"; +NSString *SPBundleFileInternalexecutionUUID = @"exeUUID"; NSString *SPBundleFileTooltipKey = @"tooltip"; NSString *SPBundleFileDisabledKey = @"disabled"; NSString *SPBundleFileAuthorKey = @"author"; @@ -298,10 +299,32 @@ NSString *SPBundleInternPathToFileKey = @"path"; NSString *SPBundleInternKeyEquivalentKey = @"keyEquivalent"; NSString *SPBundleFileName = @"command.plist"; -NSString *SPBundleTaskInputFilePath = @"/tmp/SP_BUNDLE_TASK_INPUT"; -NSString *SPBundleTaskScriptCommandFilePath = @"/tmp/SP_SCRIPT_COMMAND"; -NSString *SPBundleTaskCopyBlobFileDirectory = @"/tmp/SP_COPY_BLOB_FILES"; -NSString *SPBundleTaskTableMetaDataFilePath = @"/tmp/SP_TABLE_META_DATA"; +NSString *SPBundleTaskInputFilePath = @"/tmp/SP_BUNDLE_INPUT"; +NSString *SPBundleTaskOutputFilePath = @"/tmp/SP_BUNDLE_OUTPUT"; +NSString *SPBundleTaskScriptCommandFilePath = @"/tmp/SP_BUNDLE_SCRIPT_COMMAND"; +NSString *SPBundleTaskCopyBlobFileDirectory = @"/tmp/SP_BUNDLE_COPY_BLOB_FILES"; +NSString *SPBundleTaskTableMetaDataFilePath = @"/tmp/SP_BUNDLE_TABLE_META_DATA"; + +NSString *SPBundleShellVariableInputFilePath = @"SP_BUNDLE_INPUT"; +NSString *SPBundleShellVariableOutputFilePath = @"SP_BUNDLE_OUTPUT"; +NSString *SPBundleShellVariableBundlePath = @"SP_BUNDLE_PATH"; +NSString *SPBundleShellVariableBlobFileDirectory = @"SP_BUNDLE_BLOB_FILES_DIRECTORY"; +NSString *SPBundleShellVariableQueryFile = @"SP_QUERY_FILE"; +NSString *SPBundleShellVariableQueryResultFile = @"SP_QUERY_RESULT_FILE"; +NSString *SPBundleShellVariableQueryResultStatusFile = @"SP_QUERY_RESULT_STATUS_FILE"; +NSString *SPBundleShellVariableQueryResultMetaFile = @"SP_QUERY_RESULT_META_FILE"; +NSString *SPBundleShellVariableInputTableMetaData = @"SP_BUNDLE_INPUT_TABLE_METADATA"; +NSString *SPBundleShellVariableScope = @"SP_BUNDLE_SCOPE"; + +const NSInteger SPBundleRedirectActionNone = 200; +const NSInteger SPBundleRedirectActionReplaceSection = 201; +const NSInteger SPBundleRedirectActionReplaceContent = 202; +const NSInteger SPBundleRedirectActionInsertAsText = 203; +const NSInteger SPBundleRedirectActionInsertAsSnippet = 204; +const NSInteger SPBundleRedirectActionShowAsHTML = 205; +const NSInteger SPBundleRedirectActionShowAsTextTooltip = 207; +const NSInteger SPBundleRedirectActionShowAsHTMLTooltip = 208; +const NSInteger SPBundleRedirectActionLastCode = 208; // sequel URL scheme NSString *SPURLSchemeQueryInputPathHeader = @"/tmp/SP_QUERY_"; diff --git a/Source/SPCopyTable.m b/Source/SPCopyTable.m index 8c627e1d..58339976 100644 --- a/Source/SPCopyTable.m +++ b/Source/SPCopyTable.m @@ -1146,13 +1146,14 @@ NSInteger kBlobAsImageFile = 4; inputFallBackAction = [[cmdData objectForKey:SPBundleFileInputSourceFallBackKey] lowercaseString]; NSMutableDictionary *env = [NSMutableDictionary dictionary]; - [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:@"SP_BUNDLE_PATH"]; - [env setObject:bundleInputFilePath forKey:@"SP_BUNDLE_INPUT_FILE"]; + [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:SPBundleShellVariableBundlePath]; + [env setObject:bundleInputFilePath forKey:SPBundleShellVariableInputFilePath]; if([[self delegate] respondsToSelector:@selector(usedQuery)] && [[self delegate] usedQuery]) [env setObject:[[self delegate] usedQuery] forKey:@"SP_USED_QUERY_FOR_TABLE"]; - [env setObject:bundleInputTableMetaDataFilePath forKey:@"SP_BUNDLE_INPUT_TABLE_METADATA"]; + [env setObject:bundleInputTableMetaDataFilePath forKey:SPBundleShellVariableInputTableMetaData]; + [env setObject:SPBundleScopeDataTable forKey:SPBundleShellVariableScope]; if([self numberOfSelectedRows]) { NSMutableArray *sel = [NSMutableArray array]; @@ -1181,7 +1182,7 @@ NSInteger kBlobAsImageFile = 4; if(blobHandling != kBlobExclude) { NSString *bundleBlobFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskCopyBlobFileDirectory, uuid]; - [env setObject:bundleBlobFilePath forKey:@"SP_BUNDLE_BLOB_FILES_DIRECTORY"]; + [env setObject:bundleBlobFilePath forKey:SPBundleShellVariableBlobFileDirectory]; [self setCopyBlobFileDirectory:bundleBlobFilePath]; } else { [self setCopyBlobFileDirectory:@""]; @@ -1267,15 +1268,53 @@ NSInteger kBlobAsImageFile = 4; contextInfo:[NSDictionary dictionaryWithObjectsAndKeys: ([cmdData objectForKey:SPBundleFileNameKey])?:@"-", @"name", NSLocalizedString(@"Data Table", @"data table menu item label"), @"scope", + uuid, SPBundleFileInternalexecutionUUID, nil] error:&err]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; + NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; + + // Redirect due exit code + if(err != nil) { + if([err code] == SPBundleRedirectActionNone) { + action = SPBundleOutputActionNone; + err = nil; + } + else if([err code] == SPBundleRedirectActionReplaceSection) { + action = SPBundleOutputActionReplaceSelection; + err = nil; + } + else if([err code] == SPBundleRedirectActionReplaceContent) { + action = SPBundleOutputActionReplaceContent; + err = nil; + } + else if([err code] == SPBundleRedirectActionInsertAsText) { + action = SPBundleOutputActionInsertAsText; + err = nil; + } + else if([err code] == SPBundleRedirectActionInsertAsSnippet) { + action = SPBundleOutputActionInsertAsSnippet; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsHTML) { + action = SPBundleOutputActionShowAsHTML; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsTextTooltip) { + action = SPBundleOutputActionShowAsTextTooltip; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsHTMLTooltip) { + action = SPBundleOutputActionShowAsHTMLTooltip; + err = nil; + } + } + if(err == nil && output) { if([cmdData objectForKey:SPBundleFileOutputActionKey] && [[cmdData objectForKey:SPBundleFileOutputActionKey] length] && ![[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionNone]) { - NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; NSPoint pos = [NSEvent mouseLocation]; pos.y -= 16; diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m index 0aafffa4..3c875c77 100644 --- a/Source/SPStringAdditions.m +++ b/Source/SPStringAdditions.m @@ -462,20 +462,21 @@ NSMutableArray *scriptHeaderArguments = [NSMutableArray array]; NSString *scriptPath = @""; - NSString *stdoutFilePath = [NSString stringWithFormat:@"/tmp/SP_BUNDLE_OUTPUT_FILE_%@", [NSString stringWithNewUUID]]; - NSString *scriptFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskScriptCommandFilePath, [NSString stringWithNewUUID]]; + NSString *uuid = (contextInfo && [contextInfo objectForKey:SPBundleFileInternalexecutionUUID]) ? [contextInfo objectForKey:@"exeUUID"] : [NSString stringWithNewUUID]; + NSString *stdoutFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskOutputFilePath, uuid]; + NSString *scriptFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskScriptCommandFilePath, uuid]; [fm removeItemAtPath:scriptFilePath error:nil]; [fm removeItemAtPath:stdoutFilePath error:nil]; if([[NSApp delegate] lastBundleBlobFilesDirectory] != nil) [fm removeItemAtPath:[[NSApp delegate] lastBundleBlobFilesDirectory] error:nil]; - if([shellEnvironment objectForKey:@"SP_BUNDLE_BLOB_FILES_DIRECTORY"]) - [[NSApp delegate] setLastBundleBlobFilesDirectory:[shellEnvironment objectForKey:@"SP_BUNDLE_BLOB_FILES_DIRECTORY"]]; + if([shellEnvironment objectForKey:SPBundleShellVariableBlobFileDirectory]) + [[NSApp delegate] setLastBundleBlobFilesDirectory:[shellEnvironment objectForKey:SPBundleShellVariableBlobFileDirectory]]; // Parse first line for magic header #! ; if found save the script content and run the command after #! with that file. // This allows to write perl, ruby, osascript scripts natively. - if([self length] > 3 && [self hasPrefix:@"#!"] && [shellEnvironment objectForKey:@"SP_BUNDLE_PATH"]) { + if([self length] > 3 && [self hasPrefix:@"#!"] && [shellEnvironment objectForKey:SPBundleShellVariableBundlePath]) { NSRange firstLineRange = NSMakeRange(2, [self rangeOfString:@"\n"].location - 2); @@ -520,22 +521,39 @@ [theEnv setObject:[[NSBundle mainBundle] pathForResource:@"appicon" ofType:@"icns"] forKey:@"SP_ICON_FILE"]; [theEnv setObject:[NSString stringWithFormat:@"%@/Contents/Resources", [[NSBundle mainBundle] bundlePath]] forKey:@"SP_APP_RESOURCES_DIRECTORY"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionNone] forKey:@"SP_BUNDLE_EXIT_NONE"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionReplaceSection] forKey:@"SP_BUNDLE_EXIT_REPLACE_SELECTION"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionReplaceContent] forKey:@"SP_BUNDLE_EXIT_REPLACE_CONTENT"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionInsertAsText] forKey:@"SP_BUNDLE_EXIT_INSERT_AS_TEXT"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionInsertAsSnippet] forKey:@"SP_BUNDLE_EXIT_INSERT_AS_SNIPPET"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionShowAsHTML] forKey:@"SP_BUNDLE_EXIT_SHOW_AS_HTML"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionShowAsTextTooltip] forKey:@"SP_BUNDLE_EXIT_SHOW_AS_TEXT_TOOLTIP"]; + [theEnv setObject:[NSNumber numberWithInteger:SPBundleRedirectActionShowAsHTMLTooltip] forKey:@"SP_BUNDLE_EXIT_SHOW_AS_HTML_TOOLTIP"]; // Create and set an unique process ID for each SPDatabaseDocument which has to passed // for each sequelpro:// scheme command as user to be able to identify the url scheme command. // Furthermore this id is used to communicate with the called command as file name. - NSString *processID = [NSString stringWithNewUUID]; - [theEnv setObject:processID forKey:@"SP_PROCESS_ID"]; + [theEnv setObject:uuid forKey:@"SP_PROCESS_ID"]; id doc = nil; if([[[NSApp mainWindow] delegate] respondsToSelector:@selector(selectedTableDocument)]) doc = [[[NSApp mainWindow] delegate] selectedTableDocument]; + else { + for (NSWindow *aWindow in [NSApp orderedWindows]) { + if([[[[aWindow windowController] class] description] isEqualToString:@"SPWindowController"]) { + if([[[aWindow windowController] documents] count] && [[[[[[aWindow windowController] documents] objectAtIndex:0] class] description] isEqualToString:@"SPDatabaseDocument"]) { + doc = [[[aWindow windowController] documents] objectAtIndex:0]; + } + } + if(doc) break; + } + } if(doc != nil) { - [doc setProcessID:processID]; + [doc setProcessID:uuid]; - [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryInputPathHeader, processID] forKey:@"SP_QUERY_FILE"]; - [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, processID] forKey:@"SP_QUERY_RESULT_FILE"]; - [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, processID] forKey:@"SP_QUERY_RESULT_STATUS_FILE"]; - [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultMetaPathHeader, processID] forKey:@"SP_QUERY_RESULT_META_FILE"]; + [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryInputPathHeader, uuid] forKey:SPBundleShellVariableQueryFile]; + [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultPathHeader, uuid] forKey:SPBundleShellVariableQueryResultFile]; + [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultStatusPathHeader, uuid] forKey:SPBundleShellVariableQueryResultStatusFile]; + [theEnv setObject:[NSString stringWithFormat:@"%@%@", SPURLSchemeQueryResultMetaPathHeader, uuid] forKey:SPBundleShellVariableQueryResultMetaFile]; if([doc shellVariables]) [theEnv addEntriesFromDictionary:[doc shellVariables]]; @@ -546,12 +564,12 @@ if(path != nil) [bashTask setCurrentDirectoryPath:path]; - else if([shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] && [fm fileExistsAtPath:[shellEnvironment objectForKey:@"SP_BUNDLE_PATH"] isDirectory:&isDir] && isDir) - [bashTask setCurrentDirectoryPath:[shellEnvironment objectForKey:@"SP_BUNDLE_PATH"]]; + else if([shellEnvironment objectForKey:SPBundleShellVariableBundlePath] && [fm fileExistsAtPath:[shellEnvironment objectForKey:SPBundleShellVariableBundlePath] isDirectory:&isDir] && isDir) + [bashTask setCurrentDirectoryPath:[shellEnvironment objectForKey:SPBundleShellVariableBundlePath]]; - // STDOUT will be redirected to /tmp/SP_BUNDLE_OUTPUT_FILE in order to avoid nasty pipe programming due to block size reading - if([shellEnvironment objectForKey:@"SP_BUNDLE_INPUT_FILE"]) - [bashTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"%@ > %@ < %@", [scriptHeaderArguments componentsJoinedByString:@" "], stdoutFilePath, [shellEnvironment objectForKey:@"SP_BUNDLE_INPUT_FILE"]], nil]]; + // STDOUT will be redirected to SPBundleTaskOutputFilePath in order to avoid nasty pipe programming due to block size reading + if([shellEnvironment objectForKey:SPBundleShellVariableInputFilePath]) + [bashTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"%@ > %@ < %@", [scriptHeaderArguments componentsJoinedByString:@" "], stdoutFilePath, [shellEnvironment objectForKey:SPBundleShellVariableInputFilePath]], nil]]; else [bashTask setArguments:[NSArray arrayWithObjects:@"-c", [NSString stringWithFormat:@"%@ > %@", [scriptHeaderArguments componentsJoinedByString:@" "], stdoutFilePath], nil]]; @@ -602,16 +620,16 @@ // Remove files [fm removeItemAtPath:scriptFilePath error:nil]; - if([theEnv objectForKey:@"SP_QUERY_FILE"]) - [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_FILE"] error:nil]; - if([theEnv objectForKey:@"SP_QUERY_RESULT_FILE"]) - [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_FILE"] error:nil]; - if([theEnv objectForKey:@"SP_QUERY_RESULT_STATUS_FILE"]) - [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_STATUS_FILE"] error:nil]; - if([theEnv objectForKey:@"SP_QUERY_RESULT_META_FILE"]) - [fm removeItemAtPath:[theEnv objectForKey:@"SP_QUERY_RESULT_META_FILE"] error:nil]; - if([theEnv objectForKey:@"SP_BUNDLE_INPUT_TABLE_METADATA"]) - [fm removeItemAtPath:[theEnv objectForKey:@"SP_BUNDLE_INPUT_TABLE_METADATA"] error:nil]; + if([theEnv objectForKey:SPBundleShellVariableQueryFile]) + [fm removeItemAtPath:[theEnv objectForKey:SPBundleShellVariableQueryFile] error:nil]; + if([theEnv objectForKey:SPBundleShellVariableQueryResultFile]) + [fm removeItemAtPath:[theEnv objectForKey:SPBundleShellVariableQueryResultFile] error:nil]; + if([theEnv objectForKey:SPBundleShellVariableQueryResultStatusFile]) + [fm removeItemAtPath:[theEnv objectForKey:SPBundleShellVariableQueryResultStatusFile] error:nil]; + if([theEnv objectForKey:SPBundleShellVariableQueryResultMetaFile]) + [fm removeItemAtPath:[theEnv objectForKey:SPBundleShellVariableQueryResultMetaFile] error:nil]; + if([theEnv objectForKey:SPBundleShellVariableInputTableMetaData]) + [fm removeItemAtPath:[theEnv objectForKey:SPBundleShellVariableInputTableMetaData] error:nil]; // If return from bash re-activate Sequel Pro [NSApp activateIgnoringOtherApps:YES]; @@ -620,7 +638,7 @@ NSData *errdata = [stderr_file readDataToEndOfFile]; // Check STDERR - if([errdata length]) { + if([errdata length] && (status < SPBundleRedirectActionNone || status > SPBundleRedirectActionLastCode)) { [fm removeItemAtPath:stdoutFilePath error:nil]; if(status == 9 || userTerminated) return @""; @@ -661,7 +679,10 @@ } else { NSBeep(); } - return @""; + if(status > SPBundleRedirectActionNone && status <= SPBundleRedirectActionLastCode) + return stdout; + else + return @""; } } else { NSLog(@"Couldn't read return string from “%@” by using UTF-8 encoding.", self); diff --git a/Source/SPTextViewAdditions.m b/Source/SPTextViewAdditions.m index 10f3f2e5..6ca111b5 100644 --- a/Source/SPTextViewAdditions.m +++ b/Source/SPTextViewAdditions.m @@ -527,7 +527,8 @@ NSString *inputAction = @""; NSString *inputFallBackAction = @""; NSError *err = nil; - NSString *bundleInputFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskInputFilePath, [NSString stringWithNewUUID]]; + NSString *uuid = [NSString stringWithNewUUID]; + NSString *bundleInputFilePath = [NSString stringWithFormat:@"%@_%@", SPBundleTaskInputFilePath, uuid]; NSRange currentWordRange, currentSelectionRange, currentLineRange, currentQueryRange; @@ -573,8 +574,9 @@ } NSMutableDictionary *env = [NSMutableDictionary dictionary]; - [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:@"SP_BUNDLE_PATH"]; - [env setObject:bundleInputFilePath forKey:@"SP_BUNDLE_INPUT_FILE"]; + [env setObject:[infoPath stringByDeletingLastPathComponent] forKey:SPBundleShellVariableBundlePath]; + [env setObject:bundleInputFilePath forKey:SPBundleShellVariableInputFilePath]; + [env setObject:SPBundleScopeInputField forKey:SPBundleShellVariableScope]; if(selfIsQueryEditor && [[self delegate] currentQueryRange].length) [env setObject:[[self string] substringWithRange:[[self delegate] currentQueryRange]] forKey:@"SP_CURRENT_QUERY"]; @@ -609,15 +611,53 @@ contextInfo:[NSDictionary dictionaryWithObjectsAndKeys: ([cmdData objectForKey:SPBundleFileNameKey])?:@"-", @"name", NSLocalizedString(@"Input Field", @"input field menu item label"), @"scope", + uuid, SPBundleFileInternalexecutionUUID, nil] error:&err]; [[NSFileManager defaultManager] removeItemAtPath:bundleInputFilePath error:nil]; + NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; + + // Redirect due exit code + if(err != nil) { + if([err code] == SPBundleRedirectActionNone) { + action = SPBundleOutputActionNone; + err = nil; + } + else if([err code] == SPBundleRedirectActionReplaceSection) { + action = SPBundleOutputActionReplaceSelection; + err = nil; + } + else if([err code] == SPBundleRedirectActionReplaceContent) { + action = SPBundleOutputActionReplaceContent; + err = nil; + } + else if([err code] == SPBundleRedirectActionInsertAsText) { + action = SPBundleOutputActionInsertAsText; + err = nil; + } + else if([err code] == SPBundleRedirectActionInsertAsSnippet) { + action = SPBundleOutputActionInsertAsSnippet; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsHTML) { + action = SPBundleOutputActionShowAsHTML; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsTextTooltip) { + action = SPBundleOutputActionShowAsTextTooltip; + err = nil; + } + else if([err code] == SPBundleRedirectActionShowAsHTMLTooltip) { + action = SPBundleOutputActionShowAsHTMLTooltip; + err = nil; + } + } + if(err == nil && output) { if([cmdData objectForKey:SPBundleFileOutputActionKey] && [[cmdData objectForKey:SPBundleFileOutputActionKey] length] && ![[cmdData objectForKey:SPBundleFileOutputActionKey] isEqualToString:SPBundleOutputActionNone]) { - NSString *action = [[cmdData objectForKey:SPBundleFileOutputActionKey] lowercaseString]; if([action isEqualToString:SPBundleOutputActionShowAsTextTooltip]) { [SPTooltip showWithObject:output]; -- cgit v1.2.3