refactor: named regex captures

This commit is contained in:
Jan De Dobbeleer 2020-11-22 15:02:27 +01:00 committed by Jan De Dobbeleer
parent 56778276b2
commit fd84a469ef
6 changed files with 67 additions and 36 deletions

View file

@ -2,7 +2,6 @@ package main
import (
"fmt"
"regexp"
)
// Property defines one property of a segment for context
@ -62,8 +61,7 @@ func (p *properties) getColor(property Property, defaultValue string) string {
if err == nil {
return colorString
}
r := regexp.MustCompile(`(?P<color>#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})`)
values := groupDict(r, colorString)
values := findNamedRegexMatch(`(?P<color>#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})`, colorString)
if values != nil && values["color"] != "" {
return values["color"]
}

45
regex.go Normal file
View file

@ -0,0 +1,45 @@
package main
import "regexp"
func findNamedRegexMatch(pattern, text string) map[string]string {
re := regexp.MustCompile(pattern)
match := re.FindStringSubmatch(text)
result := make(map[string]string)
if len(match) == 0 {
return result
}
for i, name := range re.SubexpNames() {
if i == 0 {
continue
}
result[name] = match[i]
}
return result
}
func findAllNamedRegexMatch(pattern, text string) []map[string]string {
re := regexp.MustCompile(pattern)
match := re.FindAllStringSubmatch(text, -1)
var results []map[string]string
if len(match) == 0 {
return results
}
for _, set := range match {
result := make(map[string]string)
for i, name := range re.SubexpNames() {
if i == 0 {
result["text"] = set[i]
continue
}
result[name] = set[i]
}
results = append(results, result)
}
return results
}
func replaceAllString(pattern, text, replaceText string) string {
re := regexp.MustCompile(pattern)
return re.ReplaceAllString(text, replaceText)
}

View file

@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"fmt"
"regexp"
"strings"
"github.com/gookit/color"
@ -147,18 +146,16 @@ func (r *Renderer) writeAndRemoveText(background, foreground, text, textToRemove
func (r *Renderer) write(background, foreground, text string) {
// first we match for any potentially valid colors enclosed in <>
rex := regexp.MustCompile(`<([#A-Za-z0-9]+)?(?:,([#A-Za-z0-9]+))?>(.*?)<\/>`)
match := rex.FindAllStringSubmatch(text, -1)
match := findAllNamedRegexMatch(`<(?P<foreground>[^,>]+)?,?(?P<background>[^>]+)?>(?P<content>[^<]*)<\/>`, text)
for i := range match {
extractedForegroundColor := match[i][1]
extractedBackgroundColor := match[i][2]
extractedForegroundColor := match[i]["foreground"]
extractedBackgroundColor := match[i]["background"]
if col := r.getAnsiFromColorString(extractedForegroundColor, false); col == "" && extractedForegroundColor != Transparent && len(extractedBackgroundColor) == 0 {
continue // we skip invalid colors
}
if col := r.getAnsiFromColorString(extractedBackgroundColor, false); col == "" && extractedBackgroundColor != Transparent && len(extractedForegroundColor) == 0 {
continue // we skip invalid colors
}
// reuse function colors if only one was specified
if len(extractedBackgroundColor) == 0 {
extractedBackgroundColor = background
@ -166,9 +163,8 @@ func (r *Renderer) write(background, foreground, text string) {
if len(extractedForegroundColor) == 0 {
extractedForegroundColor = foreground
}
escapedTextSegment := match[i][0]
innerText := match[i][3]
escapedTextSegment := match[i]["text"]
innerText := match[i]["content"]
textBeforeColorOverride := strings.Split(text, escapedTextSegment)[0]
text = r.writeAndRemoveText(background, foreground, textBeforeColorOverride, textBeforeColorOverride, text)
text = r.writeAndRemoveText(extractedBackgroundColor, extractedForegroundColor, innerText, escapedTextSegment, text)
@ -178,8 +174,7 @@ func (r *Renderer) write(background, foreground, text string) {
}
func (r *Renderer) lenWithoutANSI(str string) int {
re := regexp.MustCompile(r.formats.rANSI)
stripped := re.ReplaceAllString(str, "")
stripped := replaceAllString(r.formats.rANSI, str, "")
switch r.shell {
case zsh:
stripped = strings.ReplaceAll(stripped, "%{", "")

View file

@ -85,6 +85,17 @@ func TestWriteColorOverrideBoth16(t *testing.T) {
assert.NotContains(t, renderer.string(), "</>")
}
func TestWriteColorOverrideDouble(t *testing.T) {
renderer := &Renderer{
Buffer: new(bytes.Buffer),
}
text := "<#ffffff>jan</>@<#ffffff>Jans-MBP</>"
renderer.init("pwsh")
renderer.write("#193549", "#ff5733", text)
assert.NotContains(t, renderer.string(), "<#ffffff>")
assert.NotContains(t, renderer.string(), "</>")
}
func TestWriteColorTransparent(t *testing.T) {
renderer := &Renderer{
Buffer: new(bytes.Buffer),

View file

@ -3,7 +3,6 @@ package main
import (
"bytes"
"fmt"
"regexp"
"strconv"
"strings"
)
@ -180,8 +179,7 @@ func (g *git) getStatusDetailString(status *gitStatus, color, icon Property, def
}
func (g *git) getUpstreamSymbol() string {
upstreamRegex := regexp.MustCompile("/.*")
upstream := upstreamRegex.ReplaceAllString(g.repo.upstream, "")
upstream := replaceAllString("/.*", g.repo.upstream, "")
url := g.getGitCommandOutput("remote", "get-url", upstream)
if strings.Contains(url, "github") {
return g.props.getString(GithubIcon, "\uF408 ")
@ -348,19 +346,6 @@ func (g *git) getStashContext() string {
}
func (g *git) parseGitStatusInfo(branchInfo string) map[string]string {
var branchRegex = regexp.MustCompile(`^## (?P<local>\S+?)(\.{3}(?P<upstream>\S+?)( \[(?P<upstream_status>(ahead (?P<ahead>\d+)(, )?)?(behind (?P<behind>\d+))?(gone)?)])?)?$`)
return groupDict(branchRegex, branchInfo)
}
func groupDict(pattern *regexp.Regexp, haystack string) map[string]string {
match := pattern.FindStringSubmatch(haystack)
result := make(map[string]string)
if len(match) > 0 {
for i, name := range pattern.SubexpNames() {
if i != 0 {
result[name] = match[i]
}
}
}
return result
var branchRegex = `^## (?P<local>\S+?)(\.{3}(?P<upstream>\S+?)( \[(?P<upstream_status>(ahead (?P<ahead>\d+)(, )?)?(behind (?P<behind>\d+))?(gone)?)])?)?$`
return findNamedRegexMatch(branchRegex, branchInfo)
}

View file

@ -1,7 +1,5 @@
package main
import "regexp"
type language struct {
props *properties
env environmentInfo
@ -39,8 +37,7 @@ func (l *language) enabled() bool {
}
}
versionInfo, _ := l.env.runCommand(executable, l.versionParam)
r := regexp.MustCompile(l.versionRegex)
values := groupDict(r, versionInfo)
values := findNamedRegexMatch(l.versionRegex, versionInfo)
l.version = values["version"]
return true
}