简体   繁体   English

NSTextView 语法高亮

[英]NSTextView syntax highlighting

I'm working on a Cocoa text editor which uses an NSTextView.我正在开发一个使用 NSTextView 的 Cocoa 文本编辑器。 Is it possible to change the color of certain portions of the text?是否可以更改文本某些部分的颜色?

You should add your controller as the delegate of the NSTextStorage object of the NSTextView ( [textView textStorage] ) and then implement the delegate method ‑textStorageDidProcessEditing: .您应该将您的控制器添加为NSTextView ( [textView textStorage] ) 的NSTextStorage对象的委托,然后实现委托方法‑textStorageDidProcessEditing: This is called whenever the text changes.每当文本更改时都会调用它。

In the delegate method you need to get the current NSTextStorage object from the text view using the -textStorage method of NSTextView .在委托方法,你需要获得当前NSTextStorage使用从文本视图对象-textStorage的方法NSTextView NSTextStorage is a subclass of NSAttributedString and contains the attributed contents of the view. NSTextStorage是的子类NSAttributedString和包含视图的归因内容。

Your code must then parse the string and apply coloring to whatever ranges of text are interesting to you.然后,您的代码必须解析字符串并对您感兴趣的任何文本范围应用着色。 You apply color to a range using something like this, which will apply a yellow color to the whole string:您可以使用类似的方法将颜色应用于范围,这会将黄色应用于整个字符串:

//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];

How you parse the text is up to you.您如何解析文本取决于您。 NSScanner is a useful class to use when parsing text. NSScanner是解析文本时使用的有用类。

Note that this method is by no means the most efficient way of handling syntax coloring.请注意,此方法绝不是处理语法着色的最有效方法。 If the documents you are editing are very large you will most likely want to consider offloading the parsing to a separate thread and/or being clever about which sections of text are reparsed.如果您正在编辑的文档非常大,您很可能需要考虑将解析卸载到单独的线程和/或聪明地重新解析文本的哪些部分。

Rob Keniger's answer is good, but for someone looking for a more concrete example, here's a short syntax highlighter I wrote that should highlight RegEx template syntax. Rob Keniger 的回答很好,但是对于寻找更具体示例的人来说,这是我编写的一个简短的语法高亮器,它应该突出显示 RegEx 模板语法。 I want \\ to be gray, with the character immediately following them to be black.我希望\\为灰色,紧随其后的字符为黑色。 I want $ to be red, with a digit character immediately following the $ to also be red.我希望$是红色的,紧跟在$后面的数字字符也是红色的。 Everything else should be black.其他一切都应该是黑色的。 Here's my solution:这是我的解决方案:

I made a template highlighter class, with a header that looks like this:我制作了一个模板荧光笔类,其标题如下所示:

@interface RMETemplateHighlighter : NSObject <NSTextStorageDelegate>

@end

I initialize it in the nib file as an object and hook it up to my view controller with an outlet.我在 nib 文件中将它初始化为一个对象,并使用插座将其连接到我的视图控制器。 In awakeFromNib of the view controller, I have this (where replacer is my NSTextView outlet and templateHighlighter is the outlet for the class above):在视图控制器的awakeFromNib中,我有这个(其中replacer是我的NSTextView插座, templateHighlighter是上面类的插座):

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

And my implementation looks like this:我的实现如下所示:

- (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++;
        }
    }
}

So there you go, a fully working example.所以你去了,一个完整的例子。 There were a few details that had me tripped up for ~10 minutes, like the fact that you have to take the string out of textStorage to access the individual characters... maybe this save other people a few minutes.有一些细节让我迷惑了大约 10 分钟,例如您必须从 textStorage 中取出字符串才能访问单个字符……也许这可以为其他人节省几分钟。

I recommend you to start by reading the CocoaDev page about Syntax Highlighing.我建议您首先阅读有关语法高亮的CocoaDev 页面 A lot of people have come with solutions for various goals.很多人都为各种目标提出了解决方案。

If you want to perform source code syntax highlighting, I suggest you to take a look at the UKSyntaxColoredTextDocument from Uli Kusterer .如果要执行源代码的语法高亮,我建议你看一看的UKSyntaxColoredTextDocument乌利Kusterer

Sure.当然。 You can give the NSTextView an NSAttributedString , and some of the stuff you can do with the attributed string is apply colors to certain subranges of the string.你可以给NSTextView一个NSAttributedString ,你可以用属性字符串做的一些事情是将颜色应用于字符串的某些子范围。

Or you can search on Google and see that a lot of people have done stuff with this before.或者你可以在谷歌上搜索,看到很多人以前做过这件事。

I'd probably recommend using OkudaKit .我可能会推荐使用OkudaKit

If you are ok with WebView you can use https://github.com/ACENative/ACEView如果你对 WebView 没问题,你可以使用https://github.com/ACENative/ACEView

It loads ACE editor in WebView它在 WebView 中加载ACE 编辑器

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM