语法 - 使用自定义关键字列表突出显示文本

时间:2016-11-04 03:01:07

标签: ios swift macos syntax-highlighting

我正在处理macOS应用程序。我需要使用所选单词列表语法高亮显示放在TextView(NSTextView)上的文本。为简单起见,我实际上是在iPhone模拟器上测试相同的功能。无论如何,要突出显示的单词列表是一个数组的形式。以下是我所拥有的。

func HighlightText {
    let tagArray = ["let","var","case"]
    let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
    style.alignment = NSTextAlignment.Left
    let words = textView.string!.componentsSeparatedByString(" ") // textView.text (UITextView) or textView.string (NSTextView)
    let attStr = NSMutableAttributedString()
    for i in 0..<words.count {
        let word = words[i]
        if HasElements.containsElements(tagArray,text: word,ignore: true) {
            let attr = [
                NSForegroundColorAttributeName: syntaxcolor,
                NSParagraphStyleAttributeName: style,
                ]
            let str = (i != words.count-1) ? NSAttributedString(string: word.stringByAppendingString(" "), attributes: attr) : NSAttributedString(string: word, attributes: attr)
            attStr.appendAttributedString(str)
        } else {
            let attr = [
                NSForegroundColorAttributeName: NSColor.blackColor(),
                NSParagraphStyleAttributeName: style,
                ]
            let str = (i != words.count-1) ? NSAttributedString(string: word.stringByAppendingString(" "), attributes: attr) : NSAttributedString(string: word, attributes: attr)
            attStr.appendAttributedString(str)
        }
    }
    textView.textStorage?.setAttributedString(attStr)
}

class HasElements {
    static func containsElements(array:Array<String>,text:String,ignore:Bool) -> Bool {
        var has = false
        for str in array {
            if str == text {
                    has = true
                }
        }
        return has
    }
}

这里简单的方法是将整个文本字符串分隔成带有空格的单词(&#34;&#34;),并将每个单词放在一个数组(单词)中。 containsElements函数只是告诉所选单词是否包含数组中的一个关键字(tagArray)。如果返回true,则将单词放入带有突出显示颜色的NSMutableAttributedString中。否则,它会使用纯色放入相同的属性字符串。

这种简单方法的问题在于,一个单独的单词将最后一个单词和/ n以及下一个单词放在一起。例如,如果我有一个像

这样的字符串
let base = 3
let power = 10
var answer = 1

,只有第一个&#39; let&#39;将突出显示为代码将3和下一个放在一起,如&#39; 3 \ nlet。&#39;如果我将包含\ n的任何单词与快速枚举分开,则代码不会很好地检测每个新段落。我感谢任何建议让它变得更好。仅供参考,我将把这个主题留给macOS和iOS。

Muchos thankos

1 个答案:

答案 0 :(得分:1)

结合不同的选择。 String有一个名为componentsSeparatedByCharactersInSet的函数,允许您按您定义的字符集分隔。不幸的是,由于您希望将\n分隔为多个字符,因此无法正常工作。

你可以将这两个词分开两次。

let firstSplit = textView.text!.componentsSeparatedByString(" ")
var words = [String]()
for word in firstSplit {
    let secondSplit = word.componentsSeparatedByString("\n")
    words.appendContentsOf(secondSplit)
}

但是你不会对换行符有任何意义..你需要重新加入它们。

最后,最简单的黑客只是:

let newString = textView.text!.stringByReplacingOccurrencesOfString("\n", withString: "\n ")
let words = newString.componentsSeparatedByString(" ")

所以基本上你要添加自己的空格。