forked from tordarus/format
color support
This commit is contained in:
106
main.go
106
main.go
@ -6,7 +6,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -46,7 +45,7 @@ var (
|
||||
// it may be useful to have a boolean flag for this behavior
|
||||
lineParseAmount = flag.Int("n", 1, "amount of lines to feed into input pattern")
|
||||
|
||||
replacePattern = regexp.MustCompile(`\{(\d+)(?::(.*?))?(?::(.*?))?\}`)
|
||||
replacePattern = regexp.MustCompile(`\{(\d+)(?::(.*?))?(?::(.*?))?(?::(.*?))?\}`)
|
||||
|
||||
numMutationPattern = regexp.MustCompile(`([+\-*/])(\d+|\((\d+)\))`)
|
||||
)
|
||||
@ -123,7 +122,8 @@ func replaceVars(format string, vars ...string) string {
|
||||
for _, replacement := range replacements {
|
||||
rplStr := replacement[0]
|
||||
varIndex, _ := strconv.Atoi(replacement[1])
|
||||
rplFmt := replacement[2]
|
||||
rplColor := makeColor(replacement[2])
|
||||
rplFmt := replacement[3]
|
||||
|
||||
// default format if not specified by user
|
||||
if rplFmt == "" {
|
||||
@ -132,106 +132,16 @@ func replaceVars(format string, vars ...string) string {
|
||||
|
||||
if strings.HasSuffix(rplFmt, "d") { // replace integers
|
||||
value, _ := strconv.ParseInt(vars[varIndex], 10, 64)
|
||||
mutate := numMut2func[int64](replacement[3])
|
||||
format = strings.Replace(format, rplStr, fmt.Sprintf(rplFmt, mutate(value, vars)), 1)
|
||||
mutate := numMut2func[int64](replacement[4])
|
||||
format = strings.Replace(format, rplStr, rplColor.Sprintf(rplFmt, mutate(value, vars)), 1)
|
||||
} else if strings.HasSuffix(rplFmt, "f") || strings.HasSuffix(rplFmt, "g") { // replace floats
|
||||
value, _ := strconv.ParseFloat(vars[varIndex], 64)
|
||||
mutate := numMut2func[float64](replacement[3])
|
||||
format = strings.Replace(format, rplStr, fmt.Sprintf(rplFmt, mutate(value, vars)), 1)
|
||||
mutate := numMut2func[float64](replacement[4])
|
||||
format = strings.Replace(format, rplStr, rplColor.Sprintf(rplFmt, mutate(value, vars)), 1)
|
||||
} else { // replace strings
|
||||
format = strings.Replace(format, rplStr, fmt.Sprintf(rplFmt, vars[varIndex]), 1)
|
||||
format = strings.Replace(format, rplStr, rplColor.Sprintf(rplFmt, vars[varIndex]), 1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return format
|
||||
}
|
||||
|
||||
var numMutatorCache = map[string]interface{}{}
|
||||
|
||||
func numMut2func[T int64 | float64](mutation string) (f func(value T, vars []string) T) {
|
||||
if mutation == "" {
|
||||
return func(value T, vars []string) T { return value }
|
||||
}
|
||||
|
||||
// caching
|
||||
if v, ok := numMutatorCache[mutation]; ok {
|
||||
return v.(func(value T, vars []string) T)
|
||||
}
|
||||
defer func() { numMutatorCache[mutation] = f }()
|
||||
|
||||
matches := numMutationPattern.FindAllStringSubmatch(mutation, -1)
|
||||
mutators := make([]NumMutator, 0, len(matches))
|
||||
var err error
|
||||
for _, match := range matches {
|
||||
mut := NumMutator{Op: NewNumOperatorFromString(match[1])}
|
||||
if match[3] == "" {
|
||||
mut.Value, err = strconv.Atoi(match[2])
|
||||
mut.Var = false
|
||||
if err != nil {
|
||||
panic("invalid number in number mutator: " + match[2])
|
||||
}
|
||||
} else {
|
||||
mut.Var = true
|
||||
mut.Value, err = strconv.Atoi(match[3])
|
||||
if err != nil {
|
||||
panic("invalid back reference group in number mutator: " + match[2])
|
||||
}
|
||||
}
|
||||
mutators = append(mutators, mut)
|
||||
}
|
||||
|
||||
numberParser := number_parser[T]()
|
||||
|
||||
return func(value T, vars []string) T {
|
||||
for _, mutator := range mutators {
|
||||
var otherValue T
|
||||
if mutator.Var {
|
||||
other := numberParser(vars[mutator.Value])
|
||||
otherValue = T(other)
|
||||
} else {
|
||||
otherValue = T(mutator.Value)
|
||||
}
|
||||
|
||||
switch mutator.Op {
|
||||
case NumOperatorAdd:
|
||||
value += otherValue
|
||||
case NumOperatorSub:
|
||||
value -= otherValue
|
||||
case NumOperatorMul:
|
||||
value *= otherValue
|
||||
case NumOperatorDiv:
|
||||
value /= otherValue
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
func number_parser[T int64 | float64]() func(str string) T {
|
||||
typeOfT := reflect.TypeOf(new(T)).Elem()
|
||||
typeOfInt64 := reflect.TypeOf(new(int64)).Elem()
|
||||
typeOfFloat64 := reflect.TypeOf(new(float64)).Elem()
|
||||
|
||||
if typeOfT == typeOfInt64 {
|
||||
return func(str string) T {
|
||||
num, err := strconv.Atoi(str)
|
||||
if err != nil {
|
||||
panic("expected integer but found " + str)
|
||||
}
|
||||
return T(num)
|
||||
}
|
||||
} else if typeOfT == typeOfFloat64 {
|
||||
return func(str string) T {
|
||||
num, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
panic("expected float but found " + str)
|
||||
}
|
||||
return T(num)
|
||||
}
|
||||
}
|
||||
|
||||
panic("invalid number type")
|
||||
}
|
||||
|
Reference in New Issue
Block a user