From ceaa143c621630b72401f2afd80ba80befc6f7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6ran=20Karl?= <3951388+JoeKar@users.noreply.github.com> Date: Tue, 11 Jul 2023 22:49:12 +0200 Subject: [PATCH] highlighter: Fix regions and patterns inside regions (#2840) * highlighter: Fix regions and patterns inside regions * highlighting: Remove 2nd recursive highlightRegion() call ...and add limitGroup checks to pattern search. * yaml: Add TODO type highlighting * highlighting: Don't stop in highlightRegion() at empty lines ...because possible region line end pattern must be detected. * syntax/sh: Correct string handling due to additional pattern handling * syntax/sh: Remove slash in variables * highlighter: Accept nested region only in case it's within the current reagion * highlighter: Accept nested patterns only in case it's within the current reagion * highlighter: Don't search for nesting in case the region end was found at start --- pkg/highlight/highlighter.go | 115 +++++++++++++++++++---------------- runtime/syntax/sh.yaml | 6 +- runtime/syntax/yaml.yaml | 5 +- 3 files changed, 66 insertions(+), 60 deletions(-) diff --git a/pkg/highlight/highlighter.go b/pkg/highlight/highlighter.go index bee7e9e4..7552671c 100644 --- a/pkg/highlight/highlighter.go +++ b/pkg/highlight/highlighter.go @@ -134,7 +134,65 @@ func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchE } } - loc := findIndex(curRegion.end, curRegion.skip, line) + var firstRegion *region + firstLoc := []int{lineLen, 0} + searchNesting := true + endLoc := findIndex(curRegion.end, curRegion.skip, line) + if endLoc != nil { + if start == endLoc[0] { + searchNesting = false + } else { + firstLoc = endLoc + } + } + if searchNesting { + for _, r := range curRegion.rules.regions { + loc := findIndex(r.start, r.skip, line) + if loc != nil { + if loc[0] < firstLoc[0] { + firstLoc = loc + firstRegion = r + } + } + } + } + if firstRegion != nil && firstLoc[0] != lineLen { + if !statesOnly { + highlights[start+firstLoc[0]] = firstRegion.limitGroup + } + h.highlightEmptyRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, sliceStart(line, firstLoc[1]), statesOnly) + h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, sliceStart(line, firstLoc[1]), firstRegion, statesOnly) + return highlights + } + + if !statesOnly { + fullHighlights := make([]Group, lineLen) + for i := 0; i < len(fullHighlights); i++ { + fullHighlights[i] = curRegion.group + } + + if searchNesting { + for _, p := range curRegion.rules.patterns { + if curRegion.group == curRegion.limitGroup || p.group == curRegion.limitGroup { + matches := findAllIndex(p.regex, line) + for _, m := range matches { + if ((endLoc == nil) || (m[0] < endLoc[0])) { + for i := m[0]; i < m[1]; i++ { + fullHighlights[i] = p.group + } + } + } + } + } + } + for i, h := range fullHighlights { + if i == 0 || h != fullHighlights[i-1] { + highlights[start+i] = h + } + } + } + + loc := endLoc if loc != nil { if !statesOnly { highlights[start+loc[0]] = curRegion.limitGroup @@ -148,62 +206,11 @@ func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchE } if !statesOnly { highlights[start+loc[1]] = curRegion.parent.group - h.highlightRegion(highlights, start, false, lineNum, sliceEnd(line, loc[0]), curRegion, statesOnly) } h.highlightRegion(highlights, start+loc[1], canMatchEnd, lineNum, sliceStart(line, loc[1]), curRegion.parent, statesOnly) return highlights } - if lineLen == 0 { - if canMatchEnd { - h.lastRegion = curRegion - } - - return highlights - } - - firstLoc := []int{lineLen, 0} - - var firstRegion *region - for _, r := range curRegion.rules.regions { - loc := findIndex(r.start, r.skip, line) - if loc != nil { - if loc[0] < firstLoc[0] { - firstLoc = loc - firstRegion = r - } - } - } - if firstLoc[0] != lineLen { - if !statesOnly { - highlights[start+firstLoc[0]] = firstRegion.limitGroup - } - h.highlightRegion(highlights, start, false, lineNum, sliceEnd(line, firstLoc[0]), curRegion, statesOnly) - h.highlightRegion(highlights, start+firstLoc[1], canMatchEnd, lineNum, sliceStart(line, firstLoc[1]), firstRegion, statesOnly) - return highlights - } - - if !statesOnly { - fullHighlights := make([]Group, lineLen) - for i := 0; i < len(fullHighlights); i++ { - fullHighlights[i] = curRegion.group - } - - for _, p := range curRegion.rules.patterns { - matches := findAllIndex(p.regex, line) - for _, m := range matches { - for i := m[0]; i < m[1]; i++ { - fullHighlights[i] = p.group - } - } - } - for i, h := range fullHighlights { - if i == 0 || h != fullHighlights[i-1] { - highlights[start+i] = h - } - } - } - if canMatchEnd { h.lastRegion = curRegion } @@ -220,8 +227,8 @@ func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canM return highlights } - firstLoc := []int{lineLen, 0} var firstRegion *region + firstLoc := []int{lineLen, 0} for _, r := range h.Def.rules.regions { loc := findIndex(r.start, r.skip, line) if loc != nil { @@ -231,7 +238,7 @@ func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canM } } } - if firstLoc[0] != lineLen { + if firstRegion != nil && firstLoc[0] != lineLen { if !statesOnly { highlights[start+firstLoc[0]] = firstRegion.limitGroup } diff --git a/runtime/syntax/sh.yaml b/runtime/syntax/sh.yaml index 038d95a5..49eb4e3f 100644 --- a/runtime/syntax/sh.yaml +++ b/runtime/syntax/sh.yaml @@ -42,18 +42,18 @@ rules: - statement: " (-[A-Za-z]+|--[a-z]+)" - identifier: "\\$\\{[0-9A-Za-z_:!%&=+#~@*^$?, .\\-\\/\\[\\]]+\\}" - - identifier: "\\$[0-9A-Za-z_:!%&=+#~@*^$?,\\-\\/\\[\\]]+" + - identifier: "\\$[0-9A-Za-z_:!%&=+#~@*^$?,\\-\\[\\]]+" - constant.string: start: "\"" end: "\"" skip: "\\\\." - rules: - - constant.specialChar: "\\\\." + rules: [] - constant.string: start: "'" end: "'" + skip: "\\\\." rules: [] - comment: diff --git a/runtime/syntax/yaml.yaml b/runtime/syntax/yaml.yaml index b6cef3f1..54d4a647 100644 --- a/runtime/syntax/yaml.yaml +++ b/runtime/syntax/yaml.yaml @@ -30,6 +30,5 @@ rules: - comment: start: "#" end: "$" - rules: [] - - + rules: + - todo: "(TODO|XXX|FIXME):?"