【问题标题】:NSTextView syntax highlightingNSTextView 语法高亮
【发布时间】:2010-02-07 21:27:29
【问题描述】:

我正在开发一个使用 NSTextView 的 Cocoa 文本编辑器。是否可以更改文本某些部分的颜色?

【问题讨论】:

    标签: objective-c cocoa syntax-highlighting nstextview


    【解决方案1】:

    您应该将您的控制器添加为NSTextView ([textView textStorage]) 的NSTextStorage 对象的委托,然后实现委托方法‑textStorageDidProcessEditing:。每当文本更改时都会调用它。

    在委托方法中,您需要使用NSTextView-textStorage 方法从文本视图中获取当前的NSTextStorage 对象。 NSTextStorageNSAttributedString 的子类,包含视图的属性内容。

    然后,您的代码必须解析字符串并将颜色应用于您感兴趣的任何文本范围。您可以使用类似这样的方法将颜色应用于范围,这会将黄色应用于整个字符串:

    //get the range of the entire run of text
    NSRange area = NSMakeRange(0, [textStorage length]);
    
    //remove existing coloring
    [textStorage removeAttribute:NSForegroundColorAttributeName range:area];
    
    //add new coloring
    [textStorage addAttribute:NSForegroundColorAttributeName 
                        value:[NSColor yellowColor] 
                        range:area];
    

    如何解析文本取决于您。 NSScanner 是解析文本时有用的类。

    请注意,此方法绝不是处理语法着色的最有效方法。如果您正在编辑的文档非常大,您很可能需要考虑将解析任务转移到单独的线程和/或巧妙地考虑重新解析哪些文本部分。

    【讨论】:

    • 这有点老了,但我将如何在委托中实现-textStorageDidProcessEditing:
    • 就像任何其他委托方法一样。在文档中查找signature of the method 并将其放在您的委托对象的实现中。确保您的委托对象设置为NSTextStorage 的委托。
    • @RobKeniger,我认为控制器需要是 NSTextStorage 的代表,而不是 NSTextView 的代表。是对的吗?这是我的经验和评论所暗示的,但它与答案的前两段相矛盾并混淆了。
    • 正如下面答案的 cmets 中所述,在我的情况下,将委托分配给 NSTextStorage 似乎破坏了我的 UITextView 的 contentSize 属性。有没有其他人经历过这种行为? (Xcode 6.3.1 / iOS 8.3)
    【解决方案2】:

    Rob Keniger's answer 很好,但对于寻找更具体示例的人来说,这是我写的一个简短的语法高亮器,它应该突出显示 RegEx 模板语法。我希望\ 为灰色,紧随其后的字符为黑色。我希望$ 是红色的,紧跟在$ 之后的数字字符也是红色的。其他一切都应该是黑色的。这是我的解决方案:

    我制作了一个模板荧光笔类,其标题如下所示:

    @interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate>
    
    @end
    

    我在 nib 文件中将它初始化为一个对象,并通过一个插座将它连接到我的视图控制器。在视图控制器的awakeFromNib 中,我有这个(其中replacer 是我的NSTextView 出口,templateHighlighter 是上述类的出口):

    self.replacer.textStorage.delegate = self.templateHighlighter;
    

    我的实现如下所示:

    - (void)textStorageDidProcessEditing:(NSNotification *)notification {
        NSTextStorage *textStorage = notification.object;
        NSString *string = textStorage.string;
        NSUInteger n = string.length;
        [textStorage removeAttribute:NSForegroundColorAttributeName range:NSMakeRange(0, n)];
        for (NSUInteger i = 0; i < n; i++) {
            unichar c = [string characterAtIndex:i];
            if (c == '\\') {
                [textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor lightGrayColor] range:NSMakeRange(i, 1)];
                i++;
            } else if (c == '$') {
                NSUInteger l = ((i < n - 1) && isdigit([string characterAtIndex:i+1])) ? 2 : 1;
                [textStorage addAttribute:NSForegroundColorAttributeName value:[NSColor redColor] range:NSMakeRange(i, l)];
                i++;
            }
        }
    }
    

    所以你去,一个完整的工作示例。有一些细节让我困惑了大约 10 分钟,例如您必须从 textStorage 中取出字符串才能访问各个字符……也许这可以节省其他人几分钟的时间。

    【讨论】:

    • 这非常适合语法高亮,但在我的情况下,它似乎也破坏了我的 UITextView 的contentSize。更具体地说,contentSize 似乎总是 UITextView 的宽度 x 单行的高度。
    • @carloe:这是一个 OS X 解决方案......你提到了 UITextView(不是 NS TextView)所以我假设你正在使用 iOS . API 之间可能存在细微差别……在 OS X 上最好的可能在 iOS 上不是最好的。
    • @ArtOfWarfare 你是对的,我的错!我应该学会读标题。对于它的价值,我通过在布局管理器上设置 allowsNonContiguousLayout = NO; 解决了我的 UITextView 问题。
    【解决方案3】:

    我建议您先阅读有关语法高亮的CocoaDev page。很多人都针对不同的目标提出了解决方案。

    如果你想进行源代码语法高亮,我建议你看看Uli Kusterer中的UKSyntaxColoredTextDocument

    【讨论】:

    • 哈哈,从来没有从 1 个站点下载过这么多样本,太棒了!
    • 提到的工具现在在github上:UKSyntaxColoredTextDocument
    【解决方案4】:

    当然。您可以给NSTextView 一个NSAttributedString,您可以对属性字符串执行的一些操作是将颜色应用于字符串的某些子范围。

    或者你可以search on Google 看到很多人以前都做过这个。

    我可能会推荐使用OkudaKit

    【讨论】:

    • OkudaKit 似乎不再处于开发阶段
    【解决方案5】:

    如果你对 WebView 没问题,你可以使用https://github.com/ACENative/ACEView

    它在 WebView 中加载 ACE editor

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-16
      • 2010-10-15
      • 1970-01-01
      • 2012-08-12
      • 2018-05-19
      • 2012-08-16
      • 2010-11-17
      相关资源
      最近更新 更多