[Editor] Improve XML syntax highlighting

This commit is contained in:
2021-03-15 22:52:27 +01:00
parent 8230f9806d
commit 9932d0fd85
2 changed files with 33 additions and 29 deletions

View File

@@ -7,60 +7,54 @@ import org.springframework.stereotype.Component
@Component
class XmlSyntaxHighlighter : SyntaxHighlighter {
private val XML_TAG =
"""(?<ELEMENT>(?<OPEN></?\h*)(?<ELEM>[\w:]+)(?<ATTRS>[^<>]*)(?<CLOSE>\h*/?>))|(?<COMMENT><!--[^<>]+-->)|(?<PROLOG><\?[^<>?]+?\?>)""".toRegex()
private val ATTRIBUTES = """(?<ATTR>[\w:]+\h*)(?<EQ>=)(?<VALUE>\h*"[^"]+")""".toRegex()
override fun highlight(code: String) = StyleSpansBuilder<Collection<String>>().let {
var lastKwEnd = 0;
override fun highlight(code: String) = StyleSpansBuilder<Collection<String>>().apply {
var last = 0;
XML_TAG.findAll(code).forEach { matcher ->
it.add(emptyList(), matcher.start - lastKwEnd);
add(emptyList(), matcher.start - last);
when {
matcher.groups["PROLOG"] != null -> {
it.add(listOf("prolog"), matcher.end - matcher.start)
add(listOf("prolog"), matcher.end - matcher.start)
}
matcher.groups["COMMENT"] != null -> {
it.add(listOf("comment"), matcher.end - matcher.start)
add(listOf("comment"), matcher.end - matcher.start)
}
matcher.groups["ELEMENT"] != null -> {
it.add(listOf("tagmark"), matcher.end("OPEN") - matcher.start("OPEN"))
it.add(listOf("anytag"), matcher.end("ELEM") - matcher.end("OPEN"))
add(listOf("tagmark"), matcher.end("OPEN") - matcher.start("OPEN"))
add(listOf("namespace"), matcher.end("NS") - matcher.end("OPEN"))
add(listOf("anytag"), matcher.end("ELEM") - matcher.end("NS"))
val attributesString = matcher.groups["ATTRS"]?.let(MatchGroup::value)?.takeIf(String::isNotEmpty)
val attributesStringLength = attributesString?.length ?: 0
if (attributesString?.isNotEmpty() == true) {
lastKwEnd = 0
last = 0
ATTRIBUTES.findAll(attributesString).forEach { attr ->
it.add(emptyList(), attr.range.first - lastKwEnd)
it.add(listOf("attribute"), attr.end("ATTR") - attr.start("ATTR"))
it.add(listOf("tagmark"), attr.end("EQ") - attr.end("ATTR"))
it.add(listOf("avalue"), attr.end("VALUE") - attr.end("EQ"))
lastKwEnd = attr.end
add(emptyList(), attr.range.first - last)
add(listOf("attribute"), attr.end("ATTR") - attr.start("ATTR"))
add(listOf("tagmark"), attr.end("EQ") - attr.end("ATTR"))
add(listOf("avalue"), attr.end("VALUE") - attr.end("EQ"))
last = attr.end
}
if (attributesStringLength > lastKwEnd) {
it.add(emptyList(), attributesStringLength - lastKwEnd)
if (attributesStringLength > last) {
add(emptyList(), attributesStringLength - last)
}
}
lastKwEnd = matcher.end("ATTRS")
it.add(listOf("tagmark"), matcher.end("CLOSE") - lastKwEnd)
last = matcher.end("ATTRS")
add(listOf("tagmark"), matcher.end("CLOSE") - last)
}
}
lastKwEnd = matcher.end
last = matcher.end
}
it.add(emptyList(), code.length - lastKwEnd)
it.create()
}
add(emptyList(), code.length - last)
}.create()
private val MatchResult.start: Int
get() = this.range.first
@@ -68,12 +62,17 @@ class XmlSyntaxHighlighter : SyntaxHighlighter {
private val MatchResult.end: Int
get() = this.range.last + 1
private fun MatchResult.start(group: Int) = this.groups[group]?.range?.first ?: 0
private fun MatchResult.start(group: String) = this.groups[group]?.range?.first ?: 0
private fun MatchResult.end(group: Int) = (this.groups[group]?.range?.last ?: 0) + 1
private fun MatchResult.end(group: String) = (this.groups[group]?.range?.last ?: 0) + 1
override val stylesheet = XmlSyntaxHighlightingStylesheet()
companion object {
private val XML_TAG =
"""(?<ELEMENT>(?<OPEN></?\h*)(?<ELEM>(?<NS>\w+:)?\w+)(?<ATTRS>[^<>]*)(?<CLOSE>\h*/?>))|(?<COMMENT><!--[^<>]+-->)|(?<PROLOG><\?[^<>?]+?\?>)""".toRegex()
private val ATTRIBUTES = """(?<ATTR>[:\w]+\h*)(?<EQ>=)(?<VALUE>\h*"[^"]+")""".toRegex()
}
}

View File

@@ -11,6 +11,7 @@ import tornadofx.cssclass
class XmlSyntaxHighlightingStylesheet : Stylesheet() {
companion object {
val prolog by cssclass()
val namespace by cssclass()
val tagmark by cssclass()
val anytag by cssclass()
val paren by cssclass()
@@ -25,6 +26,10 @@ class XmlSyntaxHighlightingStylesheet : Stylesheet() {
fontStyle = FontPosture.ITALIC
}
namespace {
fill = Color.DARKRED
}
tagmark {
fill = Color.GRAY
}