-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
304 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Print package | ||
|
||
## Description | ||
|
||
`print` is a supercharged version of the `tabwriter` package. It provides a `SetHeader` method to set a header for the table, and a `AddFields` method to add lines to the table. It also provides a `PrintTable` method to print the table to a writer. | ||
|
||
`print` don't use external dependencies. | ||
|
||
## Usage | ||
|
||
A working example can be found in the `example` folder. | ||
|
||
```go | ||
package main | ||
|
||
import "github.com/orange-cloudavenue/common-go/print" | ||
|
||
func main() { | ||
p := print.New() | ||
p.SetHeader("String", "Int", "Bool", "Slice", "Map", "Struct", "Array") | ||
p.AddFields("I'm a string", 1, true, []string{"a", "b", "c"}, map[string]string{"a": "1", "b": "2", "c": "3"}, struct{ key1, key2, key3 string }{"a", "b", "c"}, [3]string{"a", "b", "c"}) | ||
p.PrintTable() | ||
} | ||
``` | ||
|
||
## Output | ||
|
||
```sh | ||
STRING INT BOOL SLICE MAP STRUCT ARRAY | ||
I'm a string 1 Enabled a,b,c a:1,b:2,c:3 key1:a,key2:b,key3:c a,b,c | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/orange-cloudavenue/common-go/print/example | ||
|
||
go 1.20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package main | ||
|
||
import "github.com/orange-cloudavenue/common-go/print" | ||
|
||
func main() { | ||
p := print.New() | ||
p.SetHeader("String", "Int", "Bool", "Slice", "Map", "Struct", "Array") | ||
p.AddFields("I'm a string", 1, true, []string{"a", "b", "c"}, map[string]string{"a": "1", "b": "2", "c": "3"}, struct{ key1, key2, key3 string }{"a", "b", "c"}, [3]string{"a", "b", "c"}) | ||
p.PrintTable() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package print | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"strings" | ||
) | ||
|
||
type ( | ||
fmtFormat string | ||
) | ||
|
||
const ( | ||
// String fmtFormat | ||
String fmtFormat = "%s" | ||
// Int fmtFormat | ||
Int fmtFormat = "%d" | ||
// Float fmtFormat | ||
Float fmtFormat = "%f" | ||
// Bool fmtFormat | ||
Bool fmtFormat = "%s" // Use %s for bool values instead of %t because AddFields() converts bool to string | ||
// Default fmtFormat | ||
Default fmtFormat = "%v" | ||
|
||
// Tab fmtFormat | ||
Tab fmtFormat = "\t" | ||
// NewLine fmtFormat | ||
NewLine fmtFormat = "\n" | ||
) | ||
|
||
// String | ||
func (f fmtFormat) String() string { | ||
return string(f) | ||
} | ||
|
||
// formatEntry is a function that formats the given value based on its type. | ||
// It returns the formatted string representation of the value. | ||
func formatEntry(value any) (fs string) { | ||
switch value.(type) { | ||
case string: | ||
fs += String.String() | ||
case int, int8, int16, int32, int64: | ||
fs += Int.String() | ||
case float32, float64: | ||
fs += Float.String() | ||
case bool: | ||
fs += Bool.String() | ||
default: | ||
fs += Default.String() | ||
} | ||
|
||
return fs + Tab.String() | ||
} | ||
|
||
// format is a function that takes in variadic arguments of any type and returns a formatted string. | ||
// It concatenates the formatted string representation of each argument using the formatEntry function, | ||
// and appends a newline character at the end. | ||
func format(fields ...any) (fs string) { | ||
fs = "" | ||
for _, field := range fields { | ||
fs += formatEntry(field) | ||
} | ||
fs += NewLine.String() | ||
return fs | ||
} | ||
|
||
// fieldFormat | ||
// fieldFormat is a function that formats a value based on its type. | ||
// It takes any value as input and returns a formatted string. | ||
// The formatting rules are as follows: | ||
// - For slices and arrays, it joins the elements with a comma. | ||
// - For maps, it formats the key-value pairs as "key:value" and joins them with a comma. | ||
// - For structs, it formats the field name and value pairs as "fieldName:fieldValue" and joins them with a comma. | ||
// - For booleans, it returns "Enabled" if the value is true, and "Disabled" if the value is false. | ||
// For all other types, it returns the input value as is. | ||
func fieldFormat(value any) any { | ||
x := reflect.ValueOf(value) | ||
switch x.Kind() { | ||
case reflect.Slice, reflect.Array: | ||
var s []string | ||
for i := 0; i < x.Len(); i++ { | ||
s = append(s, fmt.Sprintf("%v", x.Index(i))) | ||
} | ||
return strings.Join(s, ",") | ||
case reflect.Map: | ||
// format map to "a:1,b:2" | ||
var s []string | ||
for _, k := range x.MapKeys() { | ||
s = append(s, fmt.Sprintf("%v:%v", k, x.MapIndex(k))) | ||
} | ||
return strings.Join(s, ",") | ||
case reflect.Struct: | ||
// format struct to "fieldName:fieldValue,fieldName:fieldValue" | ||
var s []string | ||
for i := 0; i < x.NumField(); i++ { | ||
s = append(s, fmt.Sprintf("%v:%v", x.Type().Field(i).Name, x.Field(i))) | ||
} | ||
return strings.Join(s, ",") | ||
case reflect.Bool: | ||
if x.Bool() { | ||
return "Enabled" | ||
} | ||
return "Disabled" | ||
} | ||
|
||
return value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package print | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
) | ||
|
||
func TestFieldFormat(t *testing.T) { | ||
testCases := []struct { | ||
value interface{} | ||
expected string | ||
}{ | ||
{ | ||
value: []int{1, 2, 3}, | ||
expected: "1,2,3", | ||
}, | ||
{ | ||
value: map[string]int{"a": 1, "b": 2}, | ||
expected: "a:1,b:2", | ||
}, | ||
{ | ||
value: struct { | ||
Name string | ||
Age int | ||
Email string | ||
}{ | ||
Name: "John", | ||
Age: 30, | ||
Email: "[email protected]", | ||
}, | ||
expected: "Name:John,Age:30,Email:[email protected]", | ||
}, | ||
{ | ||
value: true, | ||
expected: "Enabled", | ||
}, | ||
{ | ||
value: false, | ||
expected: "Disabled", | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
actual := fieldFormat(tc.value) | ||
if fmt.Sprintf("%v", actual) != tc.expected { | ||
t.Errorf("Expected FieldFormat(%v) to return %s, but got %v", tc.value, tc.expected, actual) | ||
} | ||
} | ||
} | ||
|
||
func TestFormatEntry(t *testing.T) { | ||
testCases := []struct { | ||
value interface{} | ||
expected string | ||
}{ | ||
{ | ||
value: "Hello", | ||
expected: String.String() + Tab.String(), | ||
}, | ||
{ | ||
value: 42, | ||
expected: Int.String() + Tab.String(), | ||
}, | ||
{ | ||
value: 3.14, | ||
expected: Float.String() + Tab.String(), | ||
}, | ||
{ | ||
value: true, | ||
expected: Bool.String() + Tab.String(), | ||
}, | ||
{ | ||
value: struct{}{}, | ||
expected: Default.String() + Tab.String(), | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
actual := formatEntry(tc.value) | ||
if actual != tc.expected { | ||
t.Errorf("Expected formatEntry(%v) to return %s, but got %s", tc.value, tc.expected, actual) | ||
} | ||
} | ||
} | ||
func TestFormat(t *testing.T) { | ||
testCases := []struct { | ||
fields []interface{} | ||
expected string | ||
}{ | ||
{ | ||
fields: []interface{}{"Hello", 42, 3.14, true, struct{}{}}, | ||
expected: String.String() + Tab.String() + Int.String() + Tab.String() + Float.String() + Tab.String() + Bool.String() + Tab.String() + Default.String() + Tab.String() + NewLine.String(), | ||
}, | ||
{ | ||
fields: []interface{}{1, 2, 3, "a", "b", "c"}, | ||
expected: Int.String() + Tab.String() + Int.String() + Tab.String() + Int.String() + Tab.String() + String.String() + Tab.String() + String.String() + Tab.String() + String.String() + Tab.String() + NewLine.String(), | ||
}, | ||
{ | ||
fields: []interface{}{true, false, true, false}, | ||
expected: Bool.String() + Tab.String() + Bool.String() + Tab.String() + Bool.String() + Tab.String() + Bool.String() + Tab.String() + NewLine.String(), | ||
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
actual := format(tc.fields...) | ||
if actual != tc.expected { | ||
t.Errorf("Expected format(%v) to return %s, but got %s", tc.fields, tc.expected, actual) | ||
} | ||
} | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters