-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CLI Show Workflow Namespaces Option (#200)
* add get namespaces option * use tab writer to aligned table * add print namespace obj fn * add unnest long and column swap fns Signed-off-by: Matthew F Leader <[email protected]> ---------
- Loading branch information
Showing
8 changed files
with
316 additions
and
13 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
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
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,53 @@ | ||
// Package tablefmt provides functions to create tabular data where | ||
// 1. Each variable is a column; each column is a variable. | ||
// 2. Each observation is a row; each row is an observation. | ||
// 3. Each value is a cell; each cell is a single value. | ||
// | ||
// Its behavior is inspired by the R package tidyr. | ||
// https://tidyr.tidyverse.org/index.html | ||
package tablefmt | ||
|
||
import "sort" | ||
|
||
// UnnestLongerSorted turns each element of a list-group | ||
// into a row. Each key in the map represents a group and | ||
// each group is associated with a list of values. | ||
func UnnestLongerSorted(twoColDf map[string][]string) [][]string { | ||
df := [][]string{} | ||
groupNames := []string{} | ||
for name := range twoColDf { | ||
groupNames = append(groupNames, name) | ||
} | ||
sort.Strings(groupNames) | ||
for _, name := range groupNames { | ||
groupRows := twoColDf[name] | ||
sort.Strings(groupRows) | ||
for _, rowValue := range groupRows { | ||
df = append(df, []string{name, rowValue}) | ||
} | ||
} | ||
return df | ||
} | ||
|
||
// SwapColumns swaps the row values between the first and second column, if | ||
// the row has a length of two. | ||
func SwapColumns(df [][]string) [][]string { | ||
for k := range df { | ||
if len(df[k]) == 2 { | ||
df[k][0], df[k][1] = df[k][1], df[k][0] | ||
} | ||
} | ||
return df | ||
} | ||
|
||
// ExtractGroupedLists transforms a map of maps into a map of strings. The keys | ||
// in the nested map become a list of values. | ||
func ExtractGroupedLists[T any](data map[string]map[string]T) map[string][]string { | ||
groupLists := map[string][]string{} | ||
for namespace, objects := range data { | ||
for objName := range objects { | ||
groupLists[namespace] = append(groupLists[namespace], objName) | ||
} | ||
} | ||
return groupLists | ||
} |
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,122 @@ | ||
package tablefmt_test | ||
|
||
import ( | ||
"go.arcalot.io/assert" | ||
"go.flow.arcalot.io/engine/internal/tablefmt" | ||
"sort" | ||
"testing" | ||
) | ||
|
||
func TestUnnestLongerSortedHappy(t *testing.T) { | ||
astromech := []string{"q7", "bb", "r2", "r4"} | ||
protocol := []string{"3po", "000", "chatty"} | ||
battle := []string{"b1", "ig"} | ||
probe := []string{"cobra"} | ||
astromechGroup := "astromech" | ||
protocolGroup := "protocol" | ||
battleGroup := "battle" | ||
probeGroup := "probe" | ||
astromechSorted := make([]string, len(astromech)) | ||
protocolSorted := make([]string, len(protocol)) | ||
battleSorted := make([]string, len(battle)) | ||
probeSorted := make([]string, len(probe)) | ||
sort.Strings(astromechSorted) | ||
sort.Strings(battleSorted) | ||
sort.Strings(probeSorted) | ||
sort.Strings(protocolSorted) | ||
expOut := [][]string{ | ||
{"astromech", "bb"}, | ||
{"astromech", "q7"}, | ||
{"astromech", "r2"}, | ||
{"astromech", "r4"}, | ||
{"battle", "b1"}, | ||
{"battle", "ig"}, | ||
{"probe", "cobra"}, | ||
{"protocol", "000"}, | ||
{"protocol", "3po"}, | ||
{"protocol", "chatty"}, | ||
} | ||
input := map[string][]string{ | ||
protocolGroup: protocol, | ||
astromechGroup: astromech, | ||
battleGroup: battle, | ||
probeGroup: probe, | ||
} | ||
assert.Equals(t, tablefmt.UnnestLongerSorted(input), expOut) | ||
} | ||
|
||
func TestUnnestLongerSortedEmpty(t *testing.T) { | ||
input := map[string][]string{} | ||
assert.Equals(t, tablefmt.UnnestLongerSorted(input), [][]string{}) | ||
} | ||
|
||
func TestUnnestLongerSortedEmptyGroup(t *testing.T) { | ||
input := map[string][]string{ | ||
"G": {"g"}, | ||
"D": {}, | ||
} | ||
expOut := [][]string{ | ||
{"G", "g"}, | ||
} | ||
assert.Equals(t, tablefmt.UnnestLongerSorted(input), expOut) | ||
} | ||
|
||
func TestSwapColumnsHappy(t *testing.T) { | ||
testData := map[string]struct { | ||
input [][]string | ||
expected [][]string | ||
}{ | ||
"happy": { | ||
input: [][]string{{"fruit", "tomato"}, | ||
{"fruit", "cucumber"}, | ||
{"veggie", "spinach"}, | ||
{"veggie", "carrot"}, | ||
}, | ||
expected: [][]string{ | ||
{"tomato", "fruit"}, | ||
{"cucumber", "fruit"}, | ||
{"spinach", "veggie"}, | ||
{"carrot", "veggie"}, | ||
}, | ||
}, | ||
"row_with_zero_len": { | ||
input: [][]string{ | ||
{"a", "b"}, | ||
{}, | ||
{"a", "c"}, | ||
}, | ||
expected: [][]string{ | ||
{"b", "a"}, | ||
{}, | ||
{"c", "a"}, | ||
}, | ||
}, | ||
"row_with_one_len": { | ||
input: [][]string{ | ||
{"a", "b"}, | ||
{"z"}, | ||
{"a", "c"}, | ||
}, | ||
expected: [][]string{ | ||
{"b", "a"}, | ||
{"z"}, | ||
{"c", "a"}, | ||
}, | ||
}, | ||
"row_with_three_len": { | ||
input: [][]string{ | ||
{"a", "b"}, | ||
{"x", "y", "z"}, | ||
{"a", "c"}, | ||
}, | ||
expected: [][]string{ | ||
{"b", "a"}, | ||
{"x", "y", "z"}, | ||
{"c", "a"}, | ||
}, | ||
}, | ||
} | ||
for _, tc := range testData { | ||
assert.Equals(t, tablefmt.SwapColumns(tc.input), tc.expected) | ||
} | ||
} |
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,43 @@ | ||
// Package tableprinter provides behavior to write tabular data to a given | ||
// destination. | ||
package tableprinter | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"strings" | ||
"text/tabwriter" | ||
) | ||
|
||
const ( | ||
tabwriterMinWidth = 6 | ||
tabwriterWidth = 4 | ||
tabwriterPadding = 3 | ||
tabwriterPadChar = ' ' | ||
tabwriterFlags = tabwriter.FilterHTML | ||
) | ||
|
||
// newTabWriter returns a tabwriter that transforms tabbed columns into aligned | ||
// text. | ||
func newTabWriter(output io.Writer) *tabwriter.Writer { | ||
return tabwriter.NewWriter(output, tabwriterMinWidth, tabwriterWidth, tabwriterPadding, tabwriterPadChar, tabwriterFlags) | ||
} | ||
|
||
// PrintTwoColumnTable uses a list of two item records (rows) to write a two | ||
// column table with headers to a given output destination. | ||
func PrintTwoColumnTable(output io.Writer, headers []string, rows [][]string) { | ||
w := newTabWriter(output) | ||
|
||
// column headers are at the top, so they are written first | ||
for _, col := range headers { | ||
_, _ = fmt.Fprint(w, strings.ToUpper(col), "\t") | ||
} | ||
_, _ = fmt.Fprintln(w) | ||
|
||
// rows form the body of the table | ||
for _, row := range rows { | ||
_, _ = fmt.Fprintln(w, row[0], "\t", row[1]) | ||
} | ||
|
||
_ = w.Flush() | ||
} |
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,26 @@ | ||
package tableprinter_test | ||
|
||
import ( | ||
"bytes" | ||
"go.arcalot.io/assert" | ||
"go.flow.arcalot.io/engine/internal/tableprinter" | ||
"testing" | ||
) | ||
|
||
const basicTwoColTable = `FUNCTION MODEL | ||
a 1 | ||
b 2 | ||
c 3 | ||
` | ||
|
||
func TestPrintTwoColumnTable(t *testing.T) { | ||
buf := bytes.NewBuffer(nil) | ||
headers := []string{"function", "model"} | ||
rows := [][]string{ | ||
{"a", "1"}, | ||
{"b", "2"}, | ||
{"c", "3"}, | ||
} | ||
tableprinter.PrintTwoColumnTable(buf, headers, rows) | ||
assert.Equals(t, buf.String(), basicTwoColTable) | ||
} |
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
Oops, something went wrong.