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