editorconfig-core-go made breaking api changes and has recently released v2.1.1. This change consumes the new api and fixes up any breaking references.
177 lines
3.8 KiB
Go
177 lines
3.8 KiB
Go
package editorconfig
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var (
|
|
// findLeftBrackets matches the opening left bracket {
|
|
findLeftBrackets = regexp.MustCompile(`(^|[^\\])\{`)
|
|
// findLeftBrackets matches the closing right bracket {
|
|
findRightBrackets = regexp.MustCompile(`(^|[^\\])\}`)
|
|
// findNumericRange matches a range of number, e.g. -2..5
|
|
findNumericRange = regexp.MustCompile(`^([+-]?\d+)\.\.([+-]?\d+)$`)
|
|
)
|
|
|
|
// FnmatchCase tests whether the name matches the given pattern case included.
|
|
func FnmatchCase(pattern, name string) (bool, error) {
|
|
p, err := translate(pattern)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
r, err := regexp.Compile(fmt.Sprintf("^%s$", p))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return r.MatchString(name), nil
|
|
}
|
|
|
|
func translate(pattern string) (string, error) {
|
|
index := 0
|
|
pat := []rune(pattern)
|
|
length := len(pat)
|
|
|
|
result := strings.Builder{}
|
|
|
|
braceLevel := 0
|
|
isEscaped := false
|
|
inBrackets := false
|
|
|
|
matchesBraces := len(findLeftBrackets.FindAllString(pattern, -1)) == len(findRightBrackets.FindAllString(pattern, -1))
|
|
|
|
for index < length {
|
|
r := pat[index]
|
|
index++
|
|
|
|
if r == '*' {
|
|
p := index
|
|
if p < length && pat[p] == '*' {
|
|
result.WriteString(".*")
|
|
index++
|
|
} else {
|
|
result.WriteString("[^/]*")
|
|
}
|
|
} else if r == '/' {
|
|
p := index
|
|
if p+2 < length && pat[p] == '*' && pat[p+1] == '*' && pat[p+2] == '/' {
|
|
result.WriteString("(?:/|/.*/)")
|
|
index += 3
|
|
} else {
|
|
result.WriteRune(r)
|
|
}
|
|
} else if r == '?' {
|
|
result.WriteString("[^/]")
|
|
} else if r == '[' {
|
|
if inBrackets {
|
|
result.WriteString("\\[")
|
|
} else {
|
|
hasSlash := false
|
|
res := strings.Builder{}
|
|
|
|
p := index
|
|
for p < length {
|
|
if pat[p] == ']' && pat[p-1] != '\\' {
|
|
break
|
|
}
|
|
res.WriteRune(pat[p])
|
|
if pat[p] == '/' && pat[p-1] != '\\' {
|
|
hasSlash = true
|
|
break
|
|
}
|
|
p++
|
|
}
|
|
if hasSlash {
|
|
result.WriteString("\\[" + res.String())
|
|
index = p + 1
|
|
} else {
|
|
inBrackets = true
|
|
if index < length && pat[index] == '!' || pat[index] == '^' {
|
|
index++
|
|
result.WriteString("[^")
|
|
} else {
|
|
result.WriteRune('[')
|
|
}
|
|
}
|
|
}
|
|
} else if r == ']' {
|
|
if inBrackets && pat[index-2] == '\\' {
|
|
result.WriteString("\\]")
|
|
} else {
|
|
result.WriteRune(r)
|
|
inBrackets = false
|
|
}
|
|
} else if r == '{' {
|
|
hasComma := false
|
|
p := index
|
|
res := strings.Builder{}
|
|
|
|
for p < length {
|
|
if pat[p] == '}' && pat[p-1] != '\\' {
|
|
break
|
|
}
|
|
res.WriteRune(pat[p])
|
|
if pat[p] == ',' && pat[p-1] != '\\' {
|
|
hasComma = true
|
|
break
|
|
}
|
|
p++
|
|
}
|
|
|
|
if !hasComma && p < length {
|
|
inner := res.String()
|
|
sub := findNumericRange.FindStringSubmatch(inner)
|
|
if len(sub) == 3 {
|
|
from, _ := strconv.Atoi(sub[1])
|
|
to, _ := strconv.Atoi(sub[2])
|
|
result.WriteString("(?:")
|
|
// XXX does not scale well
|
|
for i := from; i < to; i++ {
|
|
result.WriteString(strconv.Itoa(i))
|
|
result.WriteRune('|')
|
|
}
|
|
result.WriteString(strconv.Itoa(to))
|
|
result.WriteRune(')')
|
|
} else {
|
|
r, _ := translate(inner)
|
|
result.WriteString(fmt.Sprintf("\\{%s\\}", r))
|
|
}
|
|
index = p + 1
|
|
} else if matchesBraces {
|
|
result.WriteString("(?:")
|
|
braceLevel++
|
|
} else {
|
|
result.WriteString("\\{")
|
|
}
|
|
} else if r == '}' {
|
|
if braceLevel > 0 {
|
|
if isEscaped {
|
|
result.WriteRune('}')
|
|
isEscaped = false
|
|
} else {
|
|
result.WriteRune(')')
|
|
braceLevel--
|
|
}
|
|
} else {
|
|
result.WriteString("\\}")
|
|
}
|
|
} else if r == ',' {
|
|
if braceLevel == 0 || isEscaped {
|
|
result.WriteRune(r)
|
|
} else {
|
|
result.WriteRune('|')
|
|
}
|
|
} else if r != '\\' || isEscaped {
|
|
result.WriteString(regexp.QuoteMeta(string(r)))
|
|
isEscaped = false
|
|
} else {
|
|
isEscaped = true
|
|
}
|
|
}
|
|
|
|
return result.String(), nil
|
|
}
|