Skip to content

Commit b91adb8

Browse files
committed
implement map => map[string]string beautified output (inl. unit tests)
1 parent 84beed4 commit b91adb8

File tree

2 files changed

+90
-13
lines changed

2 files changed

+90
-13
lines changed

bmfmt.go

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,23 @@ import (
88
"strings"
99
)
1010

11-
// Beautify prints a given map (any key and value type) to a better readable format
11+
var keyTypePadLen = 3
12+
var valueTypePadLen = 3
13+
14+
var keyDelim = map[string]string{
15+
"open": "[",
16+
"close": "]",
17+
}
18+
var keyValueSep = ": "
19+
var valDelim = map[string]string{
20+
"open": "",
21+
"close": "",
22+
}
23+
24+
var rowTmpl = keyDelim["open"] + " %v %v " + keyDelim["close"] +
25+
keyValueSep + valDelim["open"] + "%v %v" + valDelim["close"] + "\n"
26+
27+
// Beautify prints a given map (any key and value type) to better readable format
1228
func Beautify(a interface{}) error {
1329

1430
// prevent argument a NOT to be a map
@@ -21,6 +37,15 @@ func Beautify(a interface{}) error {
2137

2238
switch {
2339

40+
// map structure is => map[string]string
41+
case keyType == reflect.String && // is key of type <string>
42+
valueType == reflect.String: // is value of type <string>
43+
44+
var targetType map[string]string
45+
var convertedArg = reflect.ValueOf(a).Convert(reflect.TypeOf(targetType)).Interface().(map[string]string)
46+
47+
printMapKeyStringWithStrings(convertedArg)
48+
2449
// map structure is => map[string][]string
2550
case keyType == reflect.String && // is key of type <string>
2651
valueType == reflect.Slice && // is value of type <slice>
@@ -39,29 +64,63 @@ func Beautify(a interface{}) error {
3964
return nil
4065
}
4166

42-
// printMapKeyStringWithSliceOfStrings prints out a map with string keys and slice of strings as value
43-
func printMapKeyStringWithSliceOfStrings(aMap map[string][]string) {
67+
// printMapKeyStringWithString prints out a map with string keys and strings as value
68+
func printMapKeyStringWithStrings(aMap map[string]string) {
69+
maxKeyLength, maxValueLength := getMaxLengthOfKeyStringValueString(aMap)
70+
71+
for key, value := range aMap {
72+
maxKeyStringLen := len("string(" + string(maxKeyLength) + ")")
73+
keyType := fmt.Sprintf("string(%v)", leftPad(strconv.Itoa(len(key)), " ", keyTypePadLen))
74+
maxValueStringLen := len("string(" + string(maxValueLength) + ")")
75+
valueType := fmt.Sprintf("string(%v)", leftPad(strconv.Itoa(len(value)), " ", valueTypePadLen))
76+
fmt.Printf(
77+
rowTmpl,
78+
rightPad("\""+key+"\"", " ", maxKeyLength+2),
79+
rightPad(keyType, " ", maxKeyStringLen+1),
80+
rightPad("\""+value+"\"", " ", maxValueLength+2),
81+
leftPad(valueType, " ", maxValueStringLen+1),
82+
)
83+
}
84+
}
4485

45-
var stringPadLen = 3
86+
// getMaxLengthOfKeyStringValueString detects the max. length of the key, value and value count
87+
func getMaxLengthOfKeyStringValueString(aMap map[string]string) (int, int) {
88+
var maxKeyLength = 0
89+
var maxValueLength = 0
4690

47-
maxKeyLength, maxValueLength, maxValueCount := getMaxLength(aMap)
91+
for key, value := range aMap {
92+
if len(key) > maxKeyLength {
93+
maxKeyLength = len(key)
94+
}
95+
if len(value) > maxValueLength {
96+
maxValueLength = len(value)
97+
}
98+
}
99+
100+
return maxKeyLength, maxValueLength
101+
}
102+
103+
// printMapKeyStringWithSliceOfStrings prints out a map with string keys and slice of strings as value
104+
func printMapKeyStringWithSliceOfStrings(aMap map[string][]string) {
105+
maxKeyLength, maxValueLength, maxValueCount := getMaxLengthOfKeyStringSliceOfStrings(aMap)
48106

49107
for key, value := range aMap {
50108
stringValue := strings.Join(value, "\", \"")
51109
maxKeyStringLen := len("string(" + string(maxKeyLength) + ")")
52-
keyTypeString := fmt.Sprintf("string(%v)", leftPad(strconv.Itoa(len(key)), " ", stringPadLen))
110+
keyTypeString := fmt.Sprintf("string(%v)", leftPad(strconv.Itoa(len(key)), " ", keyTypePadLen))
111+
valueType := fmt.Sprintf("string(%v)", leftPad(strconv.Itoa(len(stringValue)), " ", valueTypePadLen))
53112
fmt.Printf(
54-
"[ %v %v ]: %v string(%v)\n",
113+
rowTmpl,
55114
rightPad("\""+key+"\"", " ", maxKeyLength+2),
56115
rightPad(keyTypeString, " ", maxKeyStringLen+1),
57116
rightPad("\""+stringValue+"\"", " ", maxValueLength+(maxValueCount*2)),
58-
leftPad(strconv.Itoa(len(stringValue)), " ", stringPadLen),
117+
leftPad(valueType, " ", valueTypePadLen),
59118
)
60119
}
61120
}
62121

63-
// getMaxLength detects the max. length of the key, value and value count
64-
func getMaxLength(aMap map[string][]string) (int, int, int) {
122+
// getMaxLengthOfKeyStringSliceOfStrings detects the max. length of the key, value and value count
123+
func getMaxLengthOfKeyStringSliceOfStrings(aMap map[string][]string) (int, int, int) {
65124
var maxKeyLength = 0
66125
var maxValueLength = 0
67126
var maxValueCount = 0

bmfmt_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,33 @@ func TestBeautifyCauseAnErrorOnNonMap(t *testing.T) {
1919
assert.Equal(t, "given argument is NOT a map", err.Error())
2020
}
2121

22-
// TestBeautifyOutputASimpleMap test a valid map[string][]string output
23-
func TestBeautifyOutputASimpleMap(t *testing.T) {
22+
// TestBeautifyOutputSimpleMapWithStringKeysAndStringValues test a simple map with string keys and string values
23+
func TestBeautifyOutputSimpleMapWithStringKeysAndStringValues(t *testing.T) {
24+
25+
var err error
26+
candidateSingleValue := map[string]string{
27+
"a key": "a short value",
28+
}
29+
30+
expectedOutputSingleValue := `[ "a key" string( 5) ]: "a short value" string( 13)
31+
`
32+
output := capturer.CaptureStdout(func() {
33+
err = Beautify(candidateSingleValue)
34+
})
35+
36+
assert.NoError(t, err, "nil is expected")
37+
assert.Equal(t, expectedOutputSingleValue, output, "beautified map output expected (1)")
38+
}
39+
40+
// TestBeautifyOutputSimpleMapWithStringKeysAndSliceOfStringValues test a valid map[string][]string output
41+
func TestBeautifyOutputSimpleMapWithStringKeysAndSliceOfStringValues(t *testing.T) {
2442

2543
var err error
2644
candidateSingleValue := map[string][]string{
2745
"a key": {"a single value"},
2846
}
2947

30-
// due to the fact, that maps are NOT sorted, the output order may vary, so we ned to test both orderings
48+
// due to the fact, that maps are NOT sorted, the output order may vary, so we can test 1 element in map only
3149
expectedOutputSingleValue := `[ "a key" string( 5) ]: "a single value" string( 14)
3250
`
3351
output := capturer.CaptureStdout(func() {

0 commit comments

Comments
 (0)