ios - 使用自定义关键字列表的语法高亮文本

标签 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
    }
}

这里的简单方法是将整个文本字符串用空格(“”)分隔成单词,并将每个单词放在一个数组(words)中。 containsElements 函数仅告知所选单词是否包含数组 (tagArray) 中的关键字之一。如果它返回 true,这个词将被放入一个带有高亮颜色的 NSMutableAttributedString 中。否则,它会被放入具有纯色的相同属性字符串中。

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

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

,只有第一个“let”会高亮显示,因为代码将 3 和下一个 let 放在一起,如“3\nlet”。如果我用快速枚举分隔任何包含\n 的单词,代码将无法很好地检测到每个新段落。我很感激任何让它变得更好的建议。仅供引用,我打算让这个话题对 macOS 和 iOS 都开放。

非常感谢

最佳答案

几个不同的选项。字符串有一个名为 componentsSeparatedByCharactersInSet 的函数,它允许您按您定义的字符集进行分隔。不幸的是,这行不通,因为你想用 \n 分隔,它不止一个字符。

您可以将单词拆分两次。

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

但是这样你就不会感觉到换行符了。你需要重新添加它们。

最后,最简单的 hack 就是:

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

所以基本上您可以添加自己的空间。

关于ios - 使用自定义关键字列表的语法高亮文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40414620/

相关文章:

ios - 如何渐进式使用健康包示例查询

swift - OS X 应用程序弹出菜单

ios - 如何开始在 mac os 的 cocoa 应用程序中处理标签?

ruby - 命令 "ruby"在我的 Mac 上什么都不做

ios - OSX是运行xCodeBuild所必需的,还是可以在Unix/Linux机器上运行

objective-c - 根据来自另一个NSArray的字符串对NSMutableArray进行排序

swift - 面试任务。我们将如何解决它?

ios - 加载联系人使 iOS 10 Swift 崩溃

ios - Swift - 处理 UICollectionViewCell Tap

ios - StrokeEnd 未绘制完整的圆