aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPStringAdditions.h2
-rw-r--r--Source/SPStringAdditions.m104
-rw-r--r--Source/SPTextView.h2
-rw-r--r--Source/SPTextView.m101
4 files changed, 118 insertions, 91 deletions
diff --git a/Source/SPStringAdditions.h b/Source/SPStringAdditions.h
index a0b39504..15a3d9a9 100644
--- a/Source/SPStringAdditions.h
+++ b/Source/SPStringAdditions.h
@@ -75,4 +75,6 @@ static inline id NSMutableAttributedStringAttributeAtIndex (NSMutableAttributedS
- (CGFloat)levenshteinDistanceWithWord:(NSString *)stringB;
+- (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path error:(NSError**)theError;
+
@end
diff --git a/Source/SPStringAdditions.m b/Source/SPStringAdditions.m
index 847b4dbc..9d9d1779 100644
--- a/Source/SPStringAdditions.m
+++ b/Source/SPStringAdditions.m
@@ -402,6 +402,110 @@
}
/**
+ * Run self as BASH command(s) and return the result.
+ * This task can be interrupted by pressing ⌘.
+ *
+ * @param shellEnvironment A dictionary of environment variable values whose keys are the variable names.
+ *
+ * @param path The current directory for the bash command. If path is nil, the current directory is inherited from the process that created the receiver (normally /).
+ *
+ * @param theError If not nil and the bash command failed it contains the returned error message as NSLocalizedDescriptionKey
+ *
+ */
+- (NSString *)runBashCommandWithEnvironment:(NSDictionary*)shellEnvironment atCurrentDirectoryPath:(NSString*)path error:(NSError**)theError
+{
+ BOOL userTerminated = NO;
+
+ NSTask *bashTask = [[NSTask alloc] init];
+ [bashTask setLaunchPath: @"/bin/bash"];
+
+ if(shellEnvironment != nil && [shellEnvironment isKindOfClass:[NSDictionary class]] && [shellEnvironment count])
+ [bashTask setEnvironment:shellEnvironment];
+
+ if(path != nil)
+ [bashTask setCurrentDirectoryPath:path];
+
+ [bashTask setArguments:[NSArray arrayWithObjects: @"-c", self, nil]];
+
+ NSPipe *stdout_pipe = [NSPipe pipe];
+ [bashTask setStandardOutput:stdout_pipe];
+ NSFileHandle *stdout_file = [stdout_pipe fileHandleForReading];
+
+ NSPipe *stderr_pipe = [NSPipe pipe];
+ [bashTask setStandardError:stderr_pipe];
+ NSFileHandle *stderr_file = [stderr_pipe fileHandleForReading];
+ [bashTask launch];
+
+ // Listen to ⌘. to terminate
+ while(1) {
+ if(![bashTask isRunning] || [bashTask processIdentifier] == 0) break;
+ NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ usleep(10000);
+ if(!event) continue;
+ if ([event type] == NSKeyDown) {
+ unichar key = [[event characters] length] == 1 ? [[event characters] characterAtIndex:0] : 0;
+ if (([event modifierFlags] & NSCommandKeyMask) && key == '.') {
+ [bashTask terminate];
+ userTerminated = YES;
+ break;
+ }
+ } else {
+ [NSApp sendEvent:event];
+ }
+ }
+
+ [bashTask waitUntilExit];
+
+ if(userTerminated) {
+ if(bashTask) [bashTask release];
+ NSBeep();
+ NSLog(@"“%@” was terminated by user.", self);
+ return @"";
+ }
+
+ // If return from bash re-activate Sequel Pro
+ [NSApp activateIgnoringOtherApps:YES];
+
+ NSInteger status = [bashTask terminationStatus];
+ NSData *outdata = [stdout_file readDataToEndOfFile];
+ NSData *errdata = [stderr_file readDataToEndOfFile];
+
+ if(outdata != nil) {
+ NSString *stdout = [[[NSString alloc] initWithData:outdata encoding:NSUTF8StringEncoding] autorelease];
+ if(bashTask) [bashTask release];
+ if(stdout != nil) {
+ if (status == 0) {
+ return [stdout description];
+ } else {
+ if(theError != NULL) {
+ *theError = [[[NSError alloc] initWithDomain:NSPOSIXErrorDomain
+ code:status
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [[[NSString alloc] initWithData:errdata encoding:NSUTF8StringEncoding] autorelease],
+ NSLocalizedDescriptionKey,
+ nil]] autorelease];
+ } else {
+ NSBeep();
+ }
+ return @"";
+ }
+ } else {
+ NSLog(@"Couldn't read return string from “%@” by using UTF-8 encoding.", self);
+ NSBeep();
+ }
+ } else {
+ if(bashTask) [bashTask release];
+ NSLog(@"Couldn't read data from command “%@”.", self);
+ NSBeep();
+ return @"";
+ }
+
+}
+
+/**
* Returns the minimum of a, b and c.
*/
- (NSInteger)smallestOf:(NSInteger)a andOf:(NSInteger)b andOf:(NSInteger)c
diff --git a/Source/SPTextView.h b/Source/SPTextView.h
index 9730151c..69be86d3 100644
--- a/Source/SPTextView.h
+++ b/Source/SPTextView.h
@@ -143,6 +143,4 @@
- (BOOL)isSnippetMode;
-- (NSString *)runBashCommand:(NSString *)command;
-
@end
diff --git a/Source/SPTextView.m b/Source/SPTextView.m
index 08feffe4..0686fbb2 100644
--- a/Source/SPTextView.m
+++ b/Source/SPTextView.m
@@ -1711,10 +1711,19 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
if(tagRange.length) {
[theHintString flushCachedRegexData];
NSRange cmdRange = [theHintString rangeOfRegex:@"(?s)(?<!\\\\)\\$\\(\\s*(.*)\\s*\\)" capture:1L];
- if(cmdRange.length)
- [theHintString replaceCharactersInRange:tagRange withString:[self runBashCommand:[theHintString substringWithRange:cmdRange]]];
- else
+ if(cmdRange.length) {
+ NSError *err = nil;
+ NSString *cmdResult = [[theHintString substringWithRange:cmdRange] runBashCommandWithEnvironment:nil atCurrentDirectoryPath:nil error:&err];
+ if(err == nil) {
+ [theHintString replaceCharactersInRange:tagRange withString:cmdResult];
+ } 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"), [theHintString substringWithRange:cmdRange], errorMessage]);
+ }
+ } else {
[theHintString replaceCharactersInRange:tagRange withString:@""];
+ }
}
[theHintString flushCachedRegexData];
@@ -1848,92 +1857,6 @@ NSInteger alphabeticSort(id string1, id string2, void *reverse)
}
/**
- * Run 'command' as BASH command(s) and return the result.
- * This task can be interrupted by pressing ⌘.
- */
-- (NSString *)runBashCommand:(NSString *)command
-{
- BOOL userTerminated = NO;
-
- NSTask *bashTask = [[NSTask alloc] init];
- [bashTask setLaunchPath: @"/bin/bash"];
- [bashTask setArguments:[NSArray arrayWithObjects: @"-c", command, nil]];
-
- NSPipe *stdout_pipe = [NSPipe pipe];
- [bashTask setStandardOutput:stdout_pipe];
- NSFileHandle *stdout_file = [stdout_pipe fileHandleForReading];
-
- NSPipe *stderr_pipe = [NSPipe pipe];
- [bashTask setStandardError:stderr_pipe];
- NSFileHandle *stderr_file = [stderr_pipe fileHandleForReading];
- [bashTask launch];
-
- // Listen to ⌘. to terminate
- while(1) {
- if(![bashTask isRunning] || [bashTask processIdentifier] == 0) break;
- NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
- untilDate:[NSDate distantPast]
- inMode:NSDefaultRunLoopMode
- dequeue:YES];
- usleep(10000);
- if(!event) continue;
- if ([event type] == NSKeyDown) {
- unichar key = [[event characters] length] == 1 ? [[event characters] characterAtIndex:0] : 0;
- if (([event modifierFlags] & NSCommandKeyMask) && key == '.') {
- [bashTask terminate];
- userTerminated = YES;
- break;
- }
- } else {
- [NSApp sendEvent:event];
- }
- }
-
- [bashTask waitUntilExit];
-
- if(userTerminated) {
- if(bashTask) [bashTask release];
- NSBeep();
- NSLog(@"“%@” was terminated by user.", command);
- return @"";
- }
-
- // If return from bash re-activate Sequel Pro
- [NSApp activateIgnoringOtherApps:YES];
-
- NSInteger status = [bashTask terminationStatus];
- NSData *outdata = [stdout_file readDataToEndOfFile];
- NSData *errdata = [stderr_file readDataToEndOfFile];
-
- if(outdata != nil) {
- NSString *stdout = [[NSString alloc] initWithData:outdata encoding:NSUTF8StringEncoding];
- NSString *error = [[[NSString alloc] initWithData:errdata encoding:NSUTF8StringEncoding] autorelease];
- if(bashTask) [bashTask release];
- if(stdout != nil) {
- if (status == 0) {
- return [stdout autorelease];
- } else {
- NSString *error = [[[NSString alloc] initWithData:errdata encoding:NSUTF8StringEncoding] autorelease];
- 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"), command, [error description]]);
- [stdout release];
- NSBeep();
- return @"";
- }
- } else {
- NSLog(@"Couldn't read return string from “%@” by using UTF-8 encoding.", command);
- NSBeep();
- }
- } else {
- if(bashTask) [bashTask release];
- NSLog(@"Couldn't read data from command “%@”.", command);
- NSBeep();
- return @"";
- }
-
-}
-
-/**
* Checks whether the current caret position in inside of a defined snippet range
*/
- (BOOL)checkForCaretInsideSnippet