Cocoa NSTask输出格式
我正在使用NSTask从/usr/bin/man获取输出。我正在获取输出,但没有设置粗体和下划线格式。应该是这样的: 带下划线的粗体文本 注意斜体文本实际上是带下划线的,这里没有格式 而是像这样返回: b带“u u_n_d_e_r_l_i_n_e”的oolldd文本 我有一个最小的测试项目,你可以下载并运行;注意,窗口什么也不做;输出被记录到控制台Cocoa NSTask输出格式,cocoa,nsdata,nstask,Cocoa,Nsdata,Nstask,我正在使用NSTask从/usr/bin/man获取输出。我正在获取输出,但没有设置粗体和下划线格式。应该是这样的: 带下划线的粗体文本 注意斜体文本实际上是带下划线的,这里没有格式 而是像这样返回: b带“u u_n_d_e_r_l_i_n_e”的oolldd文本 我有一个最小的测试项目,你可以下载并运行;注意,窗口什么也不做;输出被记录到控制台 我假设我需要手动解释NSData对象,但我不知道从哪里开始。理想情况下,我希望将其转换为NSAttributed字符串,但第一个任务实际上是消除重复
我假设我需要手动解释NSData对象,但我不知道从哪里开始。理想情况下,我希望将其转换为NSAttributed字符串,但第一个任务实际上是消除重复项和下划线。有什么想法吗?好的,这是我的解决方案的开始,尽管我对其他更简单的解决方案感兴趣?如何做到这一点 终端返回的输出是UTF-8编码,但NSUTF8StringEncoding不能正确解释字符串。原因是NSTask输出的格式化方式 在UTF-8中,字母N是0x4e。但与之对应的NSData是0x4e 0x08 0x4e。0x08对应于退格。所以对于粗体字母,终端打印字母退格字母 对于斜体c,它是UTF-8中的0x63。NSData包含0x5f 0x08 0x63,0x5f对应一个下划线。所以对于斜体,终端打印下划线退格字母 在这一点上,除了扫描原始数据中的这些序列外,我真的看不到任何解决方法。完成后,我可能会将源代码发布到我的解析器中,除非任何人有任何现有代码。正如常见的编程短语所说,永远不要写自己可以复制的东西 后续行动: 我有一个好的、快速的解析器,用于获取man输出,并用NSMutableAttributeString中的粗体/下划线格式替换粗体/下划线输出。如果其他任何人需要解决相同的问题,下面是代码:
NSMutableIndexSet *boldChars = [[NSMutableIndexSet alloc] init];
NSMutableIndexSet *underlineChars = [[NSMutableIndexSet alloc] init];
char* bBytes = malloc(1);
bBytes[0] = (char)0x08;
NSData *bData = [NSData dataWithBytes:bBytes length:1];
free(bBytes); bBytes = nil;
NSRange testRange = NSMakeRange(1, [inputData length] - 1);
NSRange bRange = NSMakeRange(0, 0);
do {
bRange = [inputData rangeOfData:bData options:(NSDataSearchOptions)NULL range:testRange];
if (bRange.location == NSNotFound || bRange.location > [inputData length] - 2) break;
const char * buff = [inputData bytes];
if (buff[bRange.location - 1] == 0x5f) {
// it's an underline
//NSLog(@"Undr %c\n", buff[bRange.location + 1]);
[inputData replaceBytesInRange:NSMakeRange(bRange.location - 1, 2) withBytes:NULL length:0];
[underlineChars addIndex:bRange.location - 1];
testRange = NSMakeRange(bRange.location, [inputData length] - (bRange.location));
} else if (buff[bRange.location - 1] == buff[bRange.location + 1]) {
// It's a bold
//NSLog(@"Bold %c\n", buff[bRange.location + 1]);
[inputData replaceBytesInRange:NSMakeRange(bRange.location - 1, 2) withBytes:NULL length:0];
[boldChars addIndex:bRange.location - 1];
testRange = NSMakeRange(bRange.location, [inputData length] - (bRange.location));
} else {
testRange.location = bRange.location + 1;
testRange.length = [inputData length] - testRange.location;
}
} while (testRange.location <= [inputData length] - 3);
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding]];
NSFont *font = [NSFont fontWithDescriptor:[NSFontDescriptor fontDescriptorWithName:@"Menlo" size:12] size:12];
NSFont *boldFont = [[NSFontManager sharedFontManager] convertFont:font toHaveTrait:NSBoldFontMask];
[str addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, [str length])];
__block NSUInteger begin = [underlineChars firstIndex];
__block NSUInteger end = begin;
[underlineChars enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
if (idx - end < 2) {
// it's the next item to the previous one
end = idx;
} else {
// it's a split, so drop in the accumulated range and reset
[str addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSSingleUnderlineStyle] range:NSMakeRange(begin, (end-begin)+1)];
begin = idx;
end = begin;
}
if (idx == [underlineChars lastIndex]) {
[str addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSSingleUnderlineStyle] range:NSMakeRange(begin, (end-begin)+1)];
}
}];
begin = [boldChars firstIndex];
end = begin;
[boldChars enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
if (idx - end < 2) {
// it's the next item to the previous one
end = idx;
} else {
// it's a split, so drop in the accumulated range and reset
[str addAttribute:NSFontAttributeName value:boldFont range:NSMakeRange(begin, (end-begin)+1)];
begin = idx;
end = begin;
}
if (idx == [underlineChars lastIndex]) {
[str addAttribute:NSFontAttributeName value:boldFont range:NSMakeRange(begin, (end-begin)+1)];
}
}];
好的,这是我的解决方案的开始,尽管我对其他更简单的方法感兴趣?如何做到这一点 终端返回的输出是UTF-8编码,但NSUTF8StringEncoding不能正确解释字符串。原因是NSTask输出的格式化方式 在UTF-8中,字母N是0x4e。但与之对应的NSData是0x4e 0x08 0x4e。0x08对应于退格。所以对于粗体字母,终端打印字母退格字母 对于斜体c,它是UTF-8中的0x63。NSData包含0x5f 0x08 0x63,0x5f对应一个下划线。所以对于斜体,终端打印下划线退格字母 在这一点上,除了扫描原始数据中的这些序列外,我真的看不到任何解决方法。完成后,我可能会将源代码发布到我的解析器中,除非任何人有任何现有代码。正如常见的编程短语所说,永远不要写自己可以复制的东西 后续行动: 我有一个好的、快速的解析器,用于获取man输出,并用NSMutableAttributeString中的粗体/下划线格式替换粗体/下划线输出。如果其他任何人需要解决相同的问题,下面是代码:
NSMutableIndexSet *boldChars = [[NSMutableIndexSet alloc] init];
NSMutableIndexSet *underlineChars = [[NSMutableIndexSet alloc] init];
char* bBytes = malloc(1);
bBytes[0] = (char)0x08;
NSData *bData = [NSData dataWithBytes:bBytes length:1];
free(bBytes); bBytes = nil;
NSRange testRange = NSMakeRange(1, [inputData length] - 1);
NSRange bRange = NSMakeRange(0, 0);
do {
bRange = [inputData rangeOfData:bData options:(NSDataSearchOptions)NULL range:testRange];
if (bRange.location == NSNotFound || bRange.location > [inputData length] - 2) break;
const char * buff = [inputData bytes];
if (buff[bRange.location - 1] == 0x5f) {
// it's an underline
//NSLog(@"Undr %c\n", buff[bRange.location + 1]);
[inputData replaceBytesInRange:NSMakeRange(bRange.location - 1, 2) withBytes:NULL length:0];
[underlineChars addIndex:bRange.location - 1];
testRange = NSMakeRange(bRange.location, [inputData length] - (bRange.location));
} else if (buff[bRange.location - 1] == buff[bRange.location + 1]) {
// It's a bold
//NSLog(@"Bold %c\n", buff[bRange.location + 1]);
[inputData replaceBytesInRange:NSMakeRange(bRange.location - 1, 2) withBytes:NULL length:0];
[boldChars addIndex:bRange.location - 1];
testRange = NSMakeRange(bRange.location, [inputData length] - (bRange.location));
} else {
testRange.location = bRange.location + 1;
testRange.length = [inputData length] - testRange.location;
}
} while (testRange.location <= [inputData length] - 3);
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:[[NSString alloc] initWithData:inputData encoding:NSUTF8StringEncoding]];
NSFont *font = [NSFont fontWithDescriptor:[NSFontDescriptor fontDescriptorWithName:@"Menlo" size:12] size:12];
NSFont *boldFont = [[NSFontManager sharedFontManager] convertFont:font toHaveTrait:NSBoldFontMask];
[str addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, [str length])];
__block NSUInteger begin = [underlineChars firstIndex];
__block NSUInteger end = begin;
[underlineChars enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
if (idx - end < 2) {
// it's the next item to the previous one
end = idx;
} else {
// it's a split, so drop in the accumulated range and reset
[str addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSSingleUnderlineStyle] range:NSMakeRange(begin, (end-begin)+1)];
begin = idx;
end = begin;
}
if (idx == [underlineChars lastIndex]) {
[str addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSSingleUnderlineStyle] range:NSMakeRange(begin, (end-begin)+1)];
}
}];
begin = [boldChars firstIndex];
end = begin;
[boldChars enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
if (idx - end < 2) {
// it's the next item to the previous one
end = idx;
} else {
// it's a split, so drop in the accumulated range and reset
[str addAttribute:NSFontAttributeName value:boldFont range:NSMakeRange(begin, (end-begin)+1)];
begin = idx;
end = begin;
}
if (idx == [underlineChars lastIndex]) {
[str addAttribute:NSFontAttributeName value:boldFont range:NSMakeRange(begin, (end-begin)+1)];
}
}];
你的实际目的是什么?如果要显示手册页,一个选项是将其转换为HTML并使用Web视图呈现 解析man的输出可能很棘手,因为默认情况下groff使用终端处理器处理它。这意味着输出被定制为显示在终端设备上 另一种解决方案是确定手册页源文件的实际位置,例如
$ man -w bash
/usr/share/man/man1/bash.1.gz
并使用-a ASCII近似值和-c禁用颜色输出手动调用groff
$ gunzip -c /usr/share/man/man1/bash.1.gz | groff -c -a -Tascii -man
这将导致ASCII文件没有大部分格式。要生成HTML输出
$ gunzip -c /usr/share/man/man1/bash.1.gz | groff -Thtml -man
您还可以在man的自定义配置文件(例如parseman.conf)中指定这些选项,并告诉man将该配置文件与-C选项一起使用,而不是调用man-w、gunzip和groff。默认配置文件是/private/etc/man.conf
此外,您还可以通过将适当的选项传递给grotty来定制终端设备处理器的输出。您的实际目的是什么?如果要显示手册页,一个选项是将其转换为HTML并使用Web视图呈现 解析man的输出可能很棘手,因为默认情况下groff使用终端处理器处理它。这意味着输出被定制为显示在终端设备上 另一种解决方案是确定手册页源文件的实际位置,例如
$ man -w bash
/usr/share/man/man1/bash.1.gz
并使用-a ASCII近似值和-c禁用颜色输出手动调用groff
$ gunzip -c /usr/share/man/man1/bash.1.gz | groff -c -a -Tascii -man
这将导致ASCII文件没有大部分格式。要生成HTML输出
$ gunzip -c /usr/share/man/man1/bash.1.gz | groff -Thtml -man
您还可以在自定义配置中指定这些选项
并告诉man使用带有-C选项的配置文件,而不是调用man-w、gunzip和groff。默认配置文件是/private/etc/man.conf
此外,您还可以通过向grotty传递适当的选项来定制终端设备处理器的输出。另一种方法是将手册页转换为PostScript源代码,通过PostScript到PDF转换器运行,然后将其放入PDFView 该实现类似于Bavaries的答案,只是groff-Tps而不是-Thtml的参数不同
这将是最慢的解决方案,但也可能是最好的打印方法。另一种方法是将手册页转换为PostScript源代码,通过PostScript到PDF转换器运行,然后将其放入PDFView 该实现类似于Bavaries的答案,只是groff-Tps而不是-Thtml的参数不同
这将是最慢的解决方案,但也可能是最好的打印解决方案。谢谢,这是一个很好的答案。我最终设计了一个比HTML文件生成速度更快的解析器,所以我可能会坚持我的解决方案。我还将发布解析器源代码的基础知识以及我的自我回答。谢谢,这是一个很好的回答。我最终设计了一个比HTML文件生成速度更快的解析器,所以我可能会坚持我的解决方案。我还将发布解析器源代码的基础知识以及我的自我回答。