好的,假设我正在创建一个(Bash)终端模拟器-实际上我并没有,但在描述方面相当接近。
我已经成功地得到了(几乎)所有东西的工作,然而我面临一个简单的问题:如何保持当前目录。
我的意思是……假设用户运行 pwd
命令,我们通过 NSTask
和 /usr/bin/env bash
执行该命令。这将输出当前应用程序所在的目录。没问题。
现在,假设用户输入 cd ..
命令。路径是否改变了?(好吧,即使只是对于特定的会话,它也发生了改变,是吗?)
因此,我想在任务终止时存储任务的 currentDirectoryPath
,然后在启动另一个与 Bash 相关的任务时重新设置它。
然而,它一直得到非常相同的路径(应用程序包所在的路径)。
我错过了什么?
有任何想法可以让它工作吗?
代码
- (NSString*)exec:(NSArray *)args environment:(NSDictionary*)env action:(void (^)(NSString*))action completed:(void (^)(NSString*))completed
{
_task = [NSTask new];
_output = [NSPipe new];
_error = [NSPipe new];
_input = [NSPipe new];
NSFileHandle* outputF = [_output fileHandleForReading];
NSFileHandle* errorF = [_error fileHandleForReading];
__block NSString* fullOutput = @"";
NSMutableDictionary* envs = [NSMutableDictionary dictionary];
envs[@"PATH"] = [[APP environment] envPath];
[_task setLaunchPath:@"/usr/bin/env"];
if (env)
{
for (NSString* key in env)
{
envs[key] = env[key];
}
}
[_task setEnvironment:envs];
[_task setArguments:args];
[_task setStandardOutput:_output];
[_task setStandardError:_error];
[_task setStandardInput:_input];
void (^outputter)(NSFileHandle*) = ^(NSFileHandle *file){
NSData *data = [file availableData];
NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
action(str);
fullOutput = [fullOutput stringByAppendingString:str];
};
[outputF setReadabilityHandler:outputter];
[errorF setReadabilityHandler:outputter];
[_task setTerminationHandler:^(NSTask* task){
completed(fullOutput);
dispatch_async(dispatch_get_main_queue(), ^{
[[APP environment] setPwd:[task currentDirectoryPath]];
});
[task.standardOutput fileHandleForReading].readabilityHandler = nil;
[task.standardError fileHandleForReading].readabilityHandler = nil;
[task.standardInput fileHandleForWriting].writeabilityHandler = nil;
[task terminate];
task = nil;
}];
if (![[[APP environment] pwd] isEqualToString:@""])
[_task setCurrentDirectoryPath:[[APP environment] pwd]];
[_task launch];
return @"";
}