Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cocoa NSTask输出格式_Cocoa_Nsdata_Nstask - Fatal编程技术网

Cocoa NSTask输出格式

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字符串,但第一个任务实际上是消除重复

我正在使用NSTask从/usr/bin/man获取输出。我正在获取输出,但没有设置粗体和下划线格式。应该是这样的:

带下划线的粗体文本

注意斜体文本实际上是带下划线的,这里没有格式

而是像这样返回:

b带“u u_n_d_e_r_l_i_n_e”的oolldd文本

我有一个最小的测试项目,你可以下载并运行;注意,窗口什么也不做;输出被记录到控制台


我假设我需要手动解释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文件生成速度更快的解析器,所以我可能会坚持我的解决方案。我还将发布解析器源代码的基础知识以及我的自我回答。