#import "ConsoleCtrl.h" @implementation ConsoleCtrl - (void) awakeFromNib { readConsoleLock=[[NSConditionLock alloc] initWithCondition: CL_EMPTY]; NSLog(@"ConCtrl: awake: starting R thread"); [NSThread detachNewThreadSelector:@selector(startRthread:) toTarget:self withObject:nil]; NSLog(@"ConCtrl: awake: done"); } - (void) startRthread: (id) arg { NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; NSLog(@"ConCtrl: startRthread - starting R"); rEng = [[REngine alloc] initWithHandler:self]; NSLog(@"ConCtrl: startRthread - R init done"); NSLog(@"ConCtrl: startRthread - running REPL"); [rEng runREPL]; [localPool release]; } //==== most of the following code was taken from the RCocoaBundle ==== - (void) commitInput { unsigned textLength = [[ConsText string] length]; if (textLength == committedLength) { [self writeUserInput: @""]; } else if (textLength > committedLength) { NSRange tRange=NSMakeRange(committedLength, textLength - committedLength); [ConsText setSelectedRange:NSMakeRange(textLength, 0)]; //NSLog(@"commited:\"%@\"\n", [[ConsText attributedSubstringFromRange:tRange] string]); { NSString *cmd = [NSString stringWithString: [[ConsText attributedSubstringFromRange:tRange] string]]; [ConsText replaceCharactersInRange: tRange withString:@""]; [self writeUserInput: [cmd stringByAppendingString:@"\n"]]; //[hist commit: cmd]; //[dataSource reloadData]; } } } - (void) commitOutput: (NSString*) txt { [ConsText insertText:txt]; unsigned textLength = [[ConsText string] length]; if (textLength > committedLength) { NSRange tRange=NSMakeRange(committedLength, textLength - committedLength); [ConsText setSelectedRange:NSMakeRange(textLength, 0)]; [ConsText setTextColor:[NSColor blackColor] range:tRange]; //NSLog(@"before output commit:\"%@\"\n", [[ConsText attributedSubstringFromRange:tRange] string]); committedLength = textLength; } } - (void)writePrompt: (NSString*) text { unsigned textLength = [[ConsText string] length]; int promptLength=[text length]; [self commitOutput:@""]; promptPosition=committedLength; if (promptLength>0) { [ConsText setSelectedRange:NSMakeRange(textLength, 0)]; [ConsText insertText:text]; [ConsText setTextColor:[NSColor blueColor] range:NSMakeRange(textLength, promptLength)]; committedLength+=promptLength; } } - (void)writeUserInput: (NSString*) text { [self commitOutput:@""]; [ConsText insertText:text]; unsigned textLength = [[ConsText string] length]; if (textLength > committedLength) { NSRange tRange=NSMakeRange(committedLength, textLength - committedLength); [ConsText setSelectedRange:NSMakeRange(textLength, 0)]; [ConsText insertText:@""]; [ConsText setTextColor:[NSColor redColor] range:tRange]; //NSLog(@"writeUserInput:\"%@\"\n", [[ConsText attributedSubstringFromRange:tRange] string]); committedLength = textLength; } // dispatch the result to the R thread NSLog(@"Cocoa thread: writeUserInput: sending \"%@\" to R - attempting to obtain lock", text); [readConsoleLock lockWhenCondition:CL_EMPTY]; if (text==nil) readConsoleResult=nil; else readConsoleResult=[[NSString alloc] initWithString:text]; [readConsoleLock unlockWithCondition:CL_FULL]; NSLog(@"Cocoa thread: writeUserInput: ok, sent"); } - (BOOL)textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector { BOOL retval = NO; NSLog(@"textView commandSelector: %@\n", NSStringFromSelector(commandSelector)); if (@selector(insertNewline:) == commandSelector) { [self commitInput]; retval = YES; } // fake for now - sometime we could move the code from RCocoaBundle here (we need History etc.) if (@selector(moveUp:) == commandSelector) { retval = YES; } if (@selector(moveDown:) == commandSelector) { retval = YES; } return retval; } - (BOOL)textView:(NSTextView *)textViewX shouldChangeTextInRange:(NSRange)affectedCharRange replacementString:(NSString *)replacementString { // Allow changes only for uncommitted text return affectedCharRange.location >= committedLength; } // ==== here go the REPL callback messages ==== - (void) handleWriteConsole: (NSString*) msg { // BAD IDEA! we should actually dispatch this to the Cocoa thread (sometime :P) [self commitOutput: msg]; } - (NSString*) handleReadConsole: (NSString*) prompt { NSString *res=nil; [self writePrompt:prompt]; NSLog(@"R thread: handleReadConsole waiting for content"); [readConsoleLock lockWhenCondition:CL_FULL]; if (readConsoleResult!=nil) { res=[NSString stringWithString:readConsoleResult]; [readConsoleResult release]; } [readConsoleLock unlockWithCondition:CL_EMPTY]; NSLog(@"R thread: handleReadConsole got \"%@\", unlocking",res); return res; } - (void) handleBusy: (int) which { printf("BUSY: %d\n", which); } @end