Skip to content

Commit

Permalink
Allow array results to be displayed in table mode and update mac-12 t…
Browse files Browse the repository at this point in the history
…o mac-13 (#1164)

Co-authored-by: yuangen <[email protected]>
  • Loading branch information
CodeSpaceiiii and CodeSpaceiiii authored Dec 21, 2024
1 parent 9da9cb6 commit 7cddd05
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-12, windows-latest]
os: [ubuntu-latest, macos-13, windows-latest]
runs-on: ${{ matrix.os }}
environment: CI
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/installer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
installer:
strategy:
matrix:
os: [ubuntu-latest, macos-12]
os: [ubuntu-latest, macos-13]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand Down
107 changes: 96 additions & 11 deletions openapi/output_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"strconv"
"strings"
"text/tabwriter"

Expand Down Expand Up @@ -94,6 +96,11 @@ func (a *TableOutputFilter) FilterOutput(s string) (string, error) {
return a.FormatTable(rowPath, colNames, v)
}

func isArrayOrSlice(value interface{}) bool {
v := reflect.ValueOf(value)
return v.Kind() == reflect.Array || v.Kind() == reflect.Slice
}

func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v interface{}) (string, error) {
// Add row number
if v, ok := OutputFlag(a.ctx.Flags()).GetFieldValue("num"); ok {
Expand All @@ -112,20 +119,80 @@ func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v int
return "", fmt.Errorf("jmespath: '%s' failed Need Array Expr", rowPath)
}

// delete date type is struct
// 1 = object, 2 = array
dataType := 1
if len(rowsArray) > 0 {
_, ok := rowsArray[0].(map[string]interface{})
if !ok {
// check if it is an array
if isArrayOrSlice(rowsArray[0]) {
dataType = 2
}
}
}

colNamesArray := make([]string, 0)
colIndexArray := make([]int, 0)

if dataType == 2 {
// all colNames must be string:number format
for _, colName := range colNames {
// Num ignore
if colName == "Num" {
colNamesArray = append(colNamesArray, colName)
continue
}
if !strings.Contains(colName, ":") {
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
}
// split colName to name and number, must be two parts
parts := strings.Split(colName, ":")
if len(parts) != 2 {
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
}
// check if number is a number, use regex match
if !isNumber(parts[1]) {
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
}
colNamesArray = append(colNamesArray, parts[0])
num, err := strconv.Atoi(parts[1])
if err != nil {
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
}
colIndexArray = append(colIndexArray, num)
}
}

var buf bytes.Buffer
writer := bufio.NewWriter(&buf)
format := strings.Repeat("%v\t ", len(colNames)-1) + "%v"
w := tabwriter.NewWriter(writer, 0, 0, 1, ' ', tabwriter.Debug)
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(colNames)...))
if dataType == 1 {
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(colNames)...))

separator := ""
for i, colName := range colNames {
separator = separator + strings.Repeat("-", len(colName))
if i < len(colNames)-1 {
separator = separator + "\t "
}
}

fmt.Fprintln(w, separator)
} else {
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(colNamesArray)...))

separator := ""
for i, colName := range colNames {
separator = separator + strings.Repeat("-", len(colName))
if i < len(colNames)-1 {
separator = separator + "\t "
separator := ""
for i, colNameArray := range colNamesArray {
separator = separator + strings.Repeat("-", len(colNameArray))
if i < len(colNamesArray)-1 {
separator = separator + "\t "
}
}

fmt.Fprintln(w, separator)
}
fmt.Fprintln(w, separator)

for i, row := range rowsArray {
r := make([]string, 0)
Expand All @@ -138,10 +205,18 @@ func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v int
index = 1
}
}
for _, colName := range colNames[index:] {
v, _ := jmespath.Search(colName, row)
s = fmt.Sprintf("%v", v)
r = append(r, s)
if dataType == 1 {
for _, colName := range colNames[index:] {
v, _ := jmespath.Search(colName, row)
s = fmt.Sprintf("%v", v)
r = append(r, s)
}
} else {
for _, colIndex := range colIndexArray {
v, _ := jmespath.Search(fmt.Sprintf("[%d]", colIndex), row)
s = fmt.Sprintf("%v", v)
r = append(r, s)
}
}
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(r)...))
}
Expand All @@ -150,6 +225,16 @@ func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v int
return buf.String(), nil
}

func isNumber(s string) bool {
for _, c := range s {
if c < '0' || c > '9' {
return false
}
}
return true

}

func toIntfArray(stringArray []string) []interface{} {
intfArray := []interface{}{}

Expand Down
17 changes: 17 additions & 0 deletions openapi/output_filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ func TestTableOutputFilter_FormatTable(t *testing.T) {
str, err = tableout.FormatTable(rowpath, colNames, v)
assert.Equal(t, "Num | name | type | api\n--- | ---- | ---- | ---\n0 | <nil> | <nil> | <nil>\n1 | <nil> | <nil> | <nil>\n", str)
assert.Nil(t, err)

// test array format
v = map[string]interface{}{
"User": []interface{}{
[]string{"test", "test2"},
[]string{"test3", "test4"},
},
}
colNames = []string{"name:0", "type:1"}
str, err = tableout.FormatTable(rowpath, colNames, v)
assert.Equal(t, "Num | name | type\n--- | ---- | ----\n0 | test | test2\n1 | test3 | test4\n", str)
assert.Nil(t, err)
// test array format
colNames = []string{"name", "type:1"}
str, err = tableout.FormatTable(rowpath, colNames, v)
assert.NotNil(t, err)
assert.Equal(t, "colNames: name must be string:number format, like 'name:0', 0 is the array index", err.Error())
}

func TestUnquoteString(t *testing.T) {
Expand Down

0 comments on commit 7cddd05

Please sign in to comment.