Question

Is there a way that lets me run a shell script, and display the output in an NSTextView? I do not want any input from the user to the shell script at all, since is is just called to compile a buch of files. The shell script part works fine so far, but I just can't figure out how to run it and show the output in an NSTextView. I know a shell script can be run using system() and NSTask, but how do I get it's output into an NSTextView?

Was it helpful?

Solution

If you want wildcard expansion then pass your unix command to /bin/sh

- (NSString *)unixSinglePathCommandWithReturn:(NSString *) command {
    // performs a unix command by sending it to /bin/sh and returns stdout.
    // trims trailing carriage return
    // not as efficient as running command directly, but provides wildcard expansion

    NSPipe *newPipe = [NSPipe pipe];
    NSFileHandle *readHandle = [newPipe fileHandleForReading];
    NSData *inData = nil;
    NSString* returnValue = nil;

    NSTask * unixTask = [[NSTask alloc] init];
    [unixTask setStandardOutput:newPipe];
    [unixTask setLaunchPath:@"/bin/csh"];
    [unixTask setArguments:[NSArray arrayWithObjects:@"-c", command , nil]]; 
    [unixTask launch];
    [unixTask waitUntilExit];
    int status = [unixTask terminationStatus];

    while ((inData = [readHandle availableData]) && [inData length]) {

        returnValue= [[NSString alloc] 
                      initWithData:inData encoding:[NSString defaultCStringEncoding]];

        returnValue = [returnValue substringToIndex:[returnValue length]-1];

        NSLog(@"%@",returnValue);
    }

    return returnValue;

}

OTHER TIPS

NSTask has setStandardOutput method that accepts either NSFileHandle or NSPipe object. So if you create NSPipe object and set it as NSTask's standardOutput then you could use NSPipe's fileHandleForReading to get NSFileHandle from which, in turn, you'll be able to readDataToEndOfFile or readDataOfLength: you want. So something like this would do (code untested):

- (void)setupTask {
  // assume it's an ivar
  standardOutputPipe = [[NSPipe alloc] init];
  [myTask setStandardOutput:standardOutputPipe];
  // other setup code goes below
}

// reading data to NSTextField
- (void)updateOutputField {
  NSFileHandle *readingFileHandle = [standardOutputPipe fileHandleForReading];
  NSData *newData;
  while ((newData = [readingFileHandle availableData])) {
    NSString *newString = [[[NSString alloc] initWithData:newData encoding: NSASCIIStringEncoding] autorelease];
    NSString *wholeString = [[myTextField stringValue] stringByAppendingString:newString];
    [myTextField setStringValue:wholeString];
  }
  [standardOutputPipe release];
  standardOutputPipe = nil;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top