2019-01-07 12:47:27 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2019-01-18 05:49:38 +00:00
|
|
|
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
|
2019-01-07 12:47:27 +00:00
|
|
|
|
|
|
|
import Cocoa
|
|
|
|
|
2019-01-08 10:35:06 +00:00
|
|
|
private let fontSize: CGFloat = 15
|
|
|
|
|
2019-01-07 12:47:27 +00:00
|
|
|
class ConfTextStorage: NSTextStorage {
|
|
|
|
|
|
|
|
struct TextColorTheme {
|
2019-01-08 10:35:06 +00:00
|
|
|
let plainText: NSColor
|
|
|
|
let sections: NSColor
|
2019-01-09 09:24:26 +00:00
|
|
|
let keyType: NSColor
|
2019-01-08 10:35:06 +00:00
|
|
|
let key: NSColor
|
|
|
|
let url: NSColor
|
|
|
|
let urlAttribute: NSColor
|
|
|
|
let comments: NSColor
|
|
|
|
let number: NSColor
|
|
|
|
let error: NSColor
|
2019-01-07 12:47:27 +00:00
|
|
|
}
|
|
|
|
|
2019-01-08 10:35:06 +00:00
|
|
|
let defaultFont = NSFontManager.shared.convertWeight(true, of: NSFont.systemFont(ofSize: fontSize))
|
|
|
|
private let boldFont = NSFont.boldSystemFont(ofSize: fontSize)
|
|
|
|
private lazy var italicFont = NSFontManager.shared.convert(defaultFont, toHaveTrait: .italicFontMask)
|
2019-01-07 12:47:27 +00:00
|
|
|
|
|
|
|
private var defaultAttributes: [NSAttributedString.Key: Any]! //swiftlint:disable:this implicitly_unwrapped_optional
|
|
|
|
private var highlightAttributes: [UInt32: [NSAttributedString.Key: Any]]! //swiftlint:disable:this implicitly_unwrapped_optional
|
|
|
|
|
|
|
|
private let backingStore: NSMutableAttributedString
|
|
|
|
private(set) var hasError = false
|
2019-01-08 19:11:36 +00:00
|
|
|
private(set) var privateKeyString: String?
|
2019-01-07 12:47:27 +00:00
|
|
|
|
|
|
|
override init() {
|
|
|
|
backingStore = NSMutableAttributedString(string: "")
|
|
|
|
super.init()
|
|
|
|
}
|
|
|
|
|
|
|
|
required init?(coder aDecoder: NSCoder) {
|
|
|
|
fatalError("init(coder:) has not been implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) {
|
|
|
|
fatalError("init(pasteboardPropertyList:ofType:) has not been implemented")
|
|
|
|
}
|
|
|
|
|
2019-01-10 09:21:20 +00:00
|
|
|
//swiftlint:disable:next function_body_length
|
2019-01-07 12:47:27 +00:00
|
|
|
func updateAttributes(for theme: TextColorTheme) {
|
|
|
|
self.defaultAttributes = [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.plainText,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
]
|
|
|
|
|
|
|
|
self.highlightAttributes = [
|
|
|
|
HighlightSection.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.sections,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: boldFont
|
|
|
|
],
|
2019-01-09 19:59:43 +00:00
|
|
|
HighlightField.rawValue: [
|
2019-01-09 09:24:26 +00:00
|
|
|
.foregroundColor: theme.keyType,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: boldFont
|
|
|
|
],
|
2019-01-09 09:24:26 +00:00
|
|
|
HighlightPublicKey.rawValue: [
|
|
|
|
.foregroundColor: theme.key,
|
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightPrivateKey.rawValue: [
|
|
|
|
.foregroundColor: theme.key,
|
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightPresharedKey.rawValue: [
|
|
|
|
.foregroundColor: theme.key,
|
|
|
|
.font: defaultFont
|
|
|
|
],
|
2019-01-07 12:47:27 +00:00
|
|
|
HighlightIP.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.url,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightCidr.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.urlAttribute,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightHost.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.url,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
2019-01-08 10:35:06 +00:00
|
|
|
HighlightPort.rawValue: [
|
|
|
|
.foregroundColor: theme.urlAttribute,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightMTU.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.number,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightKeepalive.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.number,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightComment.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.comments,
|
|
|
|
.font: italicFont
|
2019-01-07 12:47:27 +00:00
|
|
|
],
|
|
|
|
HighlightDelimiter.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.plainText,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont
|
|
|
|
],
|
|
|
|
HighlightError.rawValue: [
|
2019-01-08 10:35:06 +00:00
|
|
|
.foregroundColor: theme.error,
|
2019-01-07 12:47:27 +00:00
|
|
|
.font: defaultFont,
|
|
|
|
.underlineStyle: 1
|
|
|
|
]
|
|
|
|
]
|
|
|
|
|
|
|
|
highlightSyntax()
|
|
|
|
}
|
|
|
|
|
|
|
|
override var string: String {
|
|
|
|
return backingStore.string
|
|
|
|
}
|
|
|
|
|
|
|
|
override func attributes(at location: Int, effectiveRange range: NSRangePointer?) -> [NSAttributedString.Key: Any] {
|
|
|
|
return backingStore.attributes(at: location, effectiveRange: range)
|
|
|
|
}
|
|
|
|
|
|
|
|
override func replaceCharacters(in range: NSRange, with str: String) {
|
|
|
|
beginEditing()
|
|
|
|
backingStore.replaceCharacters(in: range, with: str)
|
|
|
|
edited(.editedCharacters, range: range, changeInLength: str.count - range.length)
|
|
|
|
endEditing()
|
|
|
|
}
|
|
|
|
|
|
|
|
override func replaceCharacters(in range: NSRange, with attrString: NSAttributedString) {
|
|
|
|
beginEditing()
|
|
|
|
backingStore.replaceCharacters(in: range, with: attrString)
|
|
|
|
edited(.editedCharacters, range: range, changeInLength: attrString.length - range.length)
|
|
|
|
endEditing()
|
|
|
|
}
|
|
|
|
|
|
|
|
override func setAttributes(_ attrs: [NSAttributedString.Key: Any]?, range: NSRange) {
|
|
|
|
beginEditing()
|
|
|
|
backingStore.setAttributes(attrs, range: range)
|
|
|
|
edited(.editedAttributes, range: range, changeInLength: 0)
|
|
|
|
endEditing()
|
|
|
|
}
|
|
|
|
|
|
|
|
func highlightSyntax() {
|
|
|
|
hasError = false
|
2019-01-08 19:11:36 +00:00
|
|
|
privateKeyString = nil
|
2019-01-07 12:47:27 +00:00
|
|
|
|
|
|
|
backingStore.beginEditing()
|
|
|
|
var spans = highlight_config(backingStore.string.cString(using: String.Encoding.utf8))!
|
|
|
|
|
|
|
|
while spans.pointee.type != HighlightEnd {
|
|
|
|
let span = spans.pointee
|
|
|
|
|
|
|
|
let attributes = self.highlightAttributes[span.type.rawValue] ?? defaultAttributes
|
|
|
|
backingStore.setAttributes(attributes, range: NSRange(location: span.start, length: span.len))
|
|
|
|
|
|
|
|
if span.type == HighlightError {
|
|
|
|
hasError = true
|
|
|
|
}
|
|
|
|
|
2019-01-08 19:11:36 +00:00
|
|
|
if span.type == HighlightPrivateKey {
|
|
|
|
privateKeyString = backingStore.attributedSubstring(from: NSRange(location: span.start, length: span.len)).string
|
|
|
|
}
|
|
|
|
|
2019-01-07 12:47:27 +00:00
|
|
|
spans = spans.successor()
|
|
|
|
}
|
|
|
|
backingStore.endEditing()
|
|
|
|
|
|
|
|
beginEditing()
|
|
|
|
edited(.editedAttributes, range: NSRange(location: 0, length: (backingStore.string as NSString).length), changeInLength: 0)
|
|
|
|
endEditing()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|