color support
This commit is contained in:
parent
06648c9177
commit
9bd2401fd9
36
color.go
Normal file
36
color.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import "github.com/fatih/color"
|
||||
|
||||
var colorCache = map[string]*color.Color{}
|
||||
|
||||
func makeColor(name string) (c *color.Color) {
|
||||
// caching
|
||||
if c, ok := colorCache[name]; ok {
|
||||
return c
|
||||
}
|
||||
defer func() { colorCache[name] = c }()
|
||||
|
||||
switch name {
|
||||
case "black":
|
||||
return color.New(color.FgBlack)
|
||||
case "red":
|
||||
return color.New(color.FgRed)
|
||||
case "green":
|
||||
return color.New(color.FgGreen)
|
||||
case "yellow":
|
||||
return color.New(color.FgYellow)
|
||||
case "blue":
|
||||
return color.New(color.FgBlue)
|
||||
case "magenta":
|
||||
return color.New(color.FgMagenta)
|
||||
case "cyan":
|
||||
return color.New(color.FgCyan)
|
||||
case "white":
|
||||
return color.New(color.FgWhite)
|
||||
case "":
|
||||
return color.New()
|
||||
default:
|
||||
panic("unknown color name. valid color names: black, red, green, yellow, blue, magenta, cyan, white")
|
||||
}
|
||||
}
|
7
go.mod
7
go.mod
@ -1,3 +1,10 @@
|
||||
module git.tordarus.net/Tordarus/format
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e // indirect
|
||||
)
|
||||
|
14
go.sum
Normal file
14
go.sum
Normal file
@ -0,0 +1,14 @@
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e h1:w36l2Uw3dRan1K3TyXriXvY+6T56GNmlKGcqiQUJDfM=
|
||||
golang.org/x/sys v0.0.0-20220517195934-5e4e11fc645e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
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")
|
||||
}
|
||||
|
94
mutator.go
94
mutator.go
@ -1,5 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type NumMutator struct {
|
||||
Op NumOperator
|
||||
Var bool
|
||||
@ -29,3 +34,92 @@ func NewNumOperatorFromString(str string) NumOperator {
|
||||
panic("invalid number operator: " + str)
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user