语法高亮文本与关键字的自定义列表



我正在做一个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
    }
}
这里的简单方法是将整个文本字符串用空格(" ")分隔成单词,并将每个单词放入数组(words)中。containsElements函数只是告诉所选单词是否包含数组(tagArray)中的一个关键字。如果它返回true,这个单词就会被放入一个带有高亮颜色的NSMutableAttributedString中。否则,它将被放置在具有纯色的相同属性字符串中。

这个简单方法的问题是,一个分开的单词会把最后一个单词和/n以及下一个单词放在一起。例如,如果有一个像

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

,只有第一个'let'会被突出显示,因为代码将3和下一个let放在一起,如'3nlet '。如果我用快速枚举分隔任何包含n的单词,代码将无法很好地检测每个新段落。我很感激任何能让它变得更好的建议。仅供参考,我将把这个话题留给macOS和iOS。

mucho thankos

两个不同的选项。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(" ")

你可以添加自己的空格

最新更新