Skip to content

Commit

Permalink
feat(plc4go/spi): add color support to ascii box
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Oct 1, 2024
1 parent 12ecb9e commit 09439fb
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 23 deletions.
1 change: 1 addition & 0 deletions plc4go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ require (
github.com/IBM/netaddr v1.5.0
github.com/ajankovic/xdiff v0.0.1
github.com/cstockton/go-conv v1.0.0
github.com/fatih/color v1.17.0
github.com/google/uuid v1.6.0
github.com/gopacket/gopacket v1.3.0
github.com/icza/bitio v1.1.0
Expand Down
2 changes: 2 additions & 0 deletions plc4go/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ github.com/cstockton/go-conv v1.0.0/go.mod h1:HuiHkkRgOA0IoBNPC7ysG7kNpjDYlgM7Kj
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand Down
2 changes: 1 addition & 1 deletion plc4go/internal/s7/s7Io_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ package s7
import (
"context"
"fmt"
"github.com/stretchr/testify/require"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/apache/plc4x/plc4go/protocols/s7/readwrite/model"
"github.com/apache/plc4x/plc4go/spi/utils"
Expand Down
91 changes: 70 additions & 21 deletions plc4go/spi/utils/asciiBox.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
package utils

import (
"fmt"
"math"
"regexp"
"strings"

"github.com/fatih/color"
"github.com/rs/zerolog"
)

Expand Down Expand Up @@ -141,22 +143,7 @@ type AsciiBoxWriter interface {
}

func NewAsciiBoxWriter(opts ...func(writer *asciiBoxWriter)) AsciiBoxWriter {
a := &asciiBoxWriter{
newLine: '\n',
emptyPadding: " ",
// the name gets prefixed with an extra symbol for indent
extraNameCharIndent: 1,
borderWidth: 1,
newLineCharWidth: 1,
defaultBoxSet: DefaultBoxSet(),
}
for _, opt := range opts {
opt(a)
}
hl := a.defaultBoxSet.HorizontalLine
a.boxHeaderRegex = regexp.MustCompile(`^` + a.defaultBoxSet.UpperLeftCorner + hl + `(?P<name>[^` + hl + `]+)` + hl + `*` + `(?P<header>[^` + hl + `]+)?` + hl + `*` + a.defaultBoxSet.UpperRightCorner)
a.boxFooterRegex = regexp.MustCompile(`(?m)^` + a.defaultBoxSet.LowerLeftCorner + hl + `*` + `(?P<footer>[^` + hl + `]+)` + hl + `*` + a.defaultBoxSet.LowerRightCorner)
return a
return newAsciiBoxWriter(opts...)
}

func WithAsciiBoxWriterDefaultBoxSet(boxSet BoxSet) func(*asciiBoxWriter) {
Expand All @@ -165,6 +152,34 @@ func WithAsciiBoxWriterDefaultBoxSet(boxSet BoxSet) func(*asciiBoxWriter) {
}
}

func WithAsciiBoxWriterDefaultColoredBoxes(nameColor, headerColor, footerColor *color.Color) func(*asciiBoxWriter) {
return func(a *asciiBoxWriter) {
if nameColor != nil {
a.namePrinter = nameColor.Sprint
} else {
a.namePrinter = fmt.Sprint
}
if headerColor != nil {
a.headerPrinter = headerColor.Sprint
} else {
a.headerPrinter = fmt.Sprint
}
if footerColor != nil {
a.footerPrinter = footerColor.Sprint
} else {
a.footerPrinter = fmt.Sprint
}
}
}

func WithAsciiBoxWriterDisableColoredBoxes() func(*asciiBoxWriter) {
return func(a *asciiBoxWriter) {
a.namePrinter = fmt.Sprint
a.headerPrinter = fmt.Sprint
a.footerPrinter = fmt.Sprint
}
}

///////////////////////////////////////
///////////////////////////////////////
//
Expand Down Expand Up @@ -217,10 +232,35 @@ type asciiBoxWriter struct {
defaultBoxSet BoxSet
boxHeaderRegex *regexp.Regexp
boxFooterRegex *regexp.Regexp
namePrinter func(a ...any) string
headerPrinter func(a ...any) string
footerPrinter func(a ...any) string
}

var _ AsciiBoxWriter = (*asciiBoxWriter)(nil)

func newAsciiBoxWriter(opts ...func(writer *asciiBoxWriter)) *asciiBoxWriter {
a := &asciiBoxWriter{
newLine: '\n',
emptyPadding: " ",
// the name gets prefixed with an extra symbol for indent
extraNameCharIndent: 1,
borderWidth: 1,
newLineCharWidth: 1,
defaultBoxSet: DefaultBoxSet(),
namePrinter: color.New(color.FgGreen, color.Bold).Sprint,
headerPrinter: color.New(color.FgBlue).Sprint,
footerPrinter: color.New(color.FgRed, color.Italic).Sprint,
}
for _, opt := range opts {
opt(a)
}
hl := a.defaultBoxSet.HorizontalLine
a.boxHeaderRegex = regexp.MustCompile(`^` + a.defaultBoxSet.UpperLeftCorner + hl + `(?P<name>[^` + hl + `]+)` + hl + `*` + `(?P<header>[^` + hl + `]+)?` + hl + `*` + a.defaultBoxSet.UpperRightCorner)
a.boxFooterRegex = regexp.MustCompile(`(?m)^` + a.defaultBoxSet.LowerLeftCorner + hl + `*` + `(?P<footer>[^` + hl + `]+)` + hl + `*` + a.defaultBoxSet.LowerRightCorner)
return a
}

func (a *asciiBoxWriter) boxString(data string, options ...func(*BoxOptions)) AsciiBox {
var opts BoxOptions
opts.BoxSet = a.defaultBoxSet
Expand All @@ -229,16 +269,19 @@ func (a *asciiBoxWriter) boxString(data string, options ...func(*BoxOptions)) As
}
name := opts.Name
nameLength := countChars(name)
if name != "" {
name = a.namePrinter(name)
}

header := opts.Header
if name != "" && header != "" {
header = opts.BoxSet.HorizontalLine + opts.BoxSet.HorizontalLine + header + opts.BoxSet.HorizontalLine // Lazy manipulation to trick calculation below (adds a spacing between name and header)
header = opts.BoxSet.HorizontalLine + opts.BoxSet.HorizontalLine + a.headerPrinter(header) + opts.BoxSet.HorizontalLine // Lazy manipulation to trick calculation below (adds a spacing between name and header)
}
headerLength := countChars(header)

footer := opts.Footer
if footer != "" {
footer = footer + opts.BoxSet.HorizontalLine
footer = a.footerPrinter(footer) + opts.BoxSet.HorizontalLine
}
footerLength := countChars(footer)

Expand Down Expand Up @@ -292,7 +335,7 @@ func (a *asciiBoxWriter) getBoxName(box AsciiBox) string {
if index < 0 {
return ""
}
return subMatch[index]
return cleanString(subMatch[index])
}

func (a *asciiBoxWriter) getBoxHeader(box AsciiBox) string {
Expand All @@ -304,7 +347,7 @@ func (a *asciiBoxWriter) getBoxHeader(box AsciiBox) string {
if index < 0 {
return ""
}
return subMatch[index]
return cleanString(subMatch[index])
}

func (a *asciiBoxWriter) getBoxFooter(box AsciiBox) string {
Expand All @@ -316,7 +359,7 @@ func (a *asciiBoxWriter) getBoxFooter(box AsciiBox) string {
if index < 0 {
return ""
}
return subMatch[index]
return cleanString(subMatch[index])
}

func (a *asciiBoxWriter) changeBoxName(box AsciiBox, newName string) AsciiBox {
Expand Down Expand Up @@ -445,6 +488,12 @@ func countChars(s string) int {
return len([]rune(ANSI_PATTERN.ReplaceAllString(s, "")))
}

// cleanString returns the strings minus the control sequences
func cleanString(s string) string {
regex, _ := regexp.Compile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`)
return regex.ReplaceAllString(s, "")
}

//
// Internal section
//
Expand Down
37 changes: 36 additions & 1 deletion plc4go/spi/utils/asciiBox_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func init() {
Expand Down Expand Up @@ -1029,7 +1030,17 @@ func TestNewAsciiBoxWriter(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, NewAsciiBoxWriter(), "NewAsciiBoxWriter()")
got := NewAsciiBoxWriter()
require.NotNil(t, got)
require.IsType(t, new(asciiBoxWriter), got)
boxWriter := got.(*asciiBoxWriter)
assert.NotNil(t, boxWriter.namePrinter)
boxWriter.namePrinter = nil
assert.NotNil(t, boxWriter.headerPrinter)
boxWriter.headerPrinter = nil
assert.NotNil(t, boxWriter.footerPrinter)
boxWriter.footerPrinter = nil
assert.Equalf(t, tt.want, got, "NewAsciiBoxWriter()")
})
}
}
Expand Down Expand Up @@ -1363,6 +1374,9 @@ func Test_asciiBoxWriter_boxString(t *testing.T) {
borderWidth int
newLineCharWidth int
boxNameRegex *regexp.Regexp
namePrinter func(a ...any) string
headerPrinter func(a ...any) string
footerPrinter func(a ...any) string
}
type args struct {
data string
Expand Down Expand Up @@ -1580,6 +1594,18 @@ func Test_asciiBoxWriter_boxString(t *testing.T) {
borderWidth: tt.fields.borderWidth,
newLineCharWidth: tt.fields.newLineCharWidth,
boxHeaderRegex: tt.fields.boxNameRegex,
namePrinter: tt.fields.namePrinter,
headerPrinter: tt.fields.headerPrinter,
footerPrinter: tt.fields.footerPrinter,
}
if a.namePrinter == nil {
a.namePrinter = fmt.Sprint
}
if a.headerPrinter == nil {
a.headerPrinter = fmt.Sprint
}
if a.footerPrinter == nil {
a.footerPrinter = fmt.Sprint
}
tt.want.asciiBoxWriter = a
assert.Equalf(t, tt.want, a.boxString(tt.args.data, tt.args.options...), "boxString(%v)", tt.args.data)
Expand Down Expand Up @@ -1671,6 +1697,15 @@ func Test_asciiBoxWriter_changeBoxName(t *testing.T) {
boxHeaderRegex: tt.fields.boxHeaderRegex,
boxFooterRegex: tt.fields.boxFooterRegex,
}
if a.namePrinter == nil {
a.namePrinter = fmt.Sprint
}
if a.headerPrinter == nil {
a.headerPrinter = fmt.Sprint
}
if a.footerPrinter == nil {
a.footerPrinter = fmt.Sprint
}
tt.want.asciiBoxWriter = a
assert.Equalf(t, tt.want, a.changeBoxName(tt.args.box, tt.args.newName), "changeBoxName(%v, %v)", tt.args.box, tt.args.newName)
})
Expand Down

0 comments on commit 09439fb

Please sign in to comment.