mirror of
https://github.com/zyedidia/micro.git
synced 2026-03-24 17:50:15 +09:00
Add support for skipping and remove need for lookbehind
This commit is contained in:
@@ -4,8 +4,6 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
)
|
||||
|
||||
// RunePos returns the rune index of a given byte index
|
||||
@@ -62,7 +60,7 @@ func NewHighlighter(def *Def) *Highlighter {
|
||||
// color's group (represented as one byte)
|
||||
type LineMatch map[int]Group
|
||||
|
||||
func findIndex(regex *regexp2.Regexp, str []rune, canMatchStart, canMatchEnd bool) []int {
|
||||
func findIndex(regex *regexp.Regexp, skip []*regexp.Regexp, str []rune, canMatchStart, canMatchEnd bool) []int {
|
||||
regexStr := regex.String()
|
||||
if strings.Contains(regexStr, "^") {
|
||||
if !canMatchStart {
|
||||
@@ -74,12 +72,30 @@ func findIndex(regex *regexp2.Regexp, str []rune, canMatchStart, canMatchEnd boo
|
||||
return nil
|
||||
}
|
||||
}
|
||||
match, _ := regex.FindStringMatch(string(str))
|
||||
|
||||
var strbytes []byte
|
||||
if skip != nil && len(skip) > 0 {
|
||||
for _, r := range skip {
|
||||
if r != nil {
|
||||
strbytes = r.ReplaceAllFunc([]byte(string(str)), func(match []byte) []byte {
|
||||
res := make([]byte, len(match))
|
||||
// for i := 0; i < len(match); i++ {
|
||||
//
|
||||
// }
|
||||
return res
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strbytes = []byte(string(str))
|
||||
}
|
||||
|
||||
match := regex.FindIndex(strbytes)
|
||||
if match == nil {
|
||||
return nil
|
||||
}
|
||||
return []int{match.Index, match.Index + match.Length}
|
||||
// return []int{runePos(match.Index, string(str)), runePos(match.Index+match.Length, string(str))}
|
||||
// return []int{match.Index, match.Index + match.Length}
|
||||
return []int{runePos(match[0], string(str)), runePos(match[1], string(str))}
|
||||
}
|
||||
|
||||
func findAllIndex(regex *regexp.Regexp, str []rune, canMatchStart, canMatchEnd bool) [][]int {
|
||||
@@ -111,7 +127,15 @@ func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchE
|
||||
}
|
||||
}
|
||||
|
||||
loc := findIndex(curRegion.end, line, start == 0, canMatchEnd)
|
||||
skips := make([]*regexp.Regexp, len(curRegion.rules.patterns)+1)
|
||||
for i := range skips {
|
||||
if i != len(skips)-1 {
|
||||
skips[i] = curRegion.rules.patterns[i].regex
|
||||
} else {
|
||||
skips[i] = curRegion.skip
|
||||
}
|
||||
}
|
||||
loc := findIndex(curRegion.end, skips, line, start == 0, canMatchEnd)
|
||||
if loc != nil {
|
||||
if !statesOnly {
|
||||
highlights[start+loc[1]-1] = curRegion.group
|
||||
@@ -144,7 +168,7 @@ func (h *Highlighter) highlightRegion(highlights LineMatch, start int, canMatchE
|
||||
|
||||
var firstRegion *region
|
||||
for _, r := range curRegion.rules.regions {
|
||||
loc := findIndex(r.start, line, start == 0, canMatchEnd)
|
||||
loc := findIndex(r.start, nil, line, start == 0, canMatchEnd)
|
||||
if loc != nil {
|
||||
if loc[0] < firstLoc[0] {
|
||||
firstLoc = loc
|
||||
@@ -198,7 +222,7 @@ func (h *Highlighter) highlightEmptyRegion(highlights LineMatch, start int, canM
|
||||
firstLoc := []int{len(line), 0}
|
||||
var firstRegion *region
|
||||
for _, r := range h.Def.rules.regions {
|
||||
loc := findIndex(r.start, line, start == 0, canMatchEnd)
|
||||
loc := findIndex(r.start, nil, line, start == 0, canMatchEnd)
|
||||
if loc != nil {
|
||||
if loc[0] < firstLoc[0] {
|
||||
firstLoc = loc
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
@@ -61,8 +59,9 @@ type rules struct {
|
||||
type region struct {
|
||||
group Group
|
||||
parent *region
|
||||
start *regexp2.Regexp
|
||||
end *regexp2.Regexp
|
||||
start *regexp.Regexp
|
||||
end *regexp.Regexp
|
||||
skip *regexp.Regexp
|
||||
rules *rules
|
||||
}
|
||||
|
||||
@@ -217,18 +216,27 @@ func parseRegion(group string, regionInfo map[interface{}]interface{}, prevRegio
|
||||
region.group = groupNum
|
||||
region.parent = prevRegion
|
||||
|
||||
region.start, err = regexp2.Compile(regionInfo["start"].(string), 0)
|
||||
region.start, err = regexp.Compile(regionInfo["start"].(string))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
region.end, err = regexp2.Compile(regionInfo["end"].(string), 0)
|
||||
region.end, err = regexp.Compile(regionInfo["end"].(string))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// skip is optional
|
||||
if _, ok := regionInfo["skip"]; ok {
|
||||
region.skip, err = regexp.Compile(regionInfo["skip"].(string))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
region.rules, err = parseRules(regionInfo["rules"].([]interface{}), region)
|
||||
|
||||
if err != nil {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user