Skip to content

Commit 7cddd05

Browse files
Allow array results to be displayed in table mode and update mac-12 to mac-13 (#1164)
Co-authored-by: yuangen <[email protected]>
1 parent 9da9cb6 commit 7cddd05

File tree

4 files changed

+115
-13
lines changed

4 files changed

+115
-13
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
build:
1212
strategy:
1313
matrix:
14-
os: [ubuntu-latest, macos-12, windows-latest]
14+
os: [ubuntu-latest, macos-13, windows-latest]
1515
runs-on: ${{ matrix.os }}
1616
environment: CI
1717
steps:

.github/workflows/installer.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
installer:
1212
strategy:
1313
matrix:
14-
os: [ubuntu-latest, macos-12]
14+
os: [ubuntu-latest, macos-13]
1515
runs-on: ${{ matrix.os }}
1616
steps:
1717
- uses: actions/checkout@v4

openapi/output_filter.go

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"bytes"
1919
"encoding/json"
2020
"fmt"
21+
"reflect"
22+
"strconv"
2123
"strings"
2224
"text/tabwriter"
2325

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

99+
func isArrayOrSlice(value interface{}) bool {
100+
v := reflect.ValueOf(value)
101+
return v.Kind() == reflect.Array || v.Kind() == reflect.Slice
102+
}
103+
97104
func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v interface{}) (string, error) {
98105
// Add row number
99106
if v, ok := OutputFlag(a.ctx.Flags()).GetFieldValue("num"); ok {
@@ -112,20 +119,80 @@ func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v int
112119
return "", fmt.Errorf("jmespath: '%s' failed Need Array Expr", rowPath)
113120
}
114121

122+
// delete date type is struct
123+
// 1 = object, 2 = array
124+
dataType := 1
125+
if len(rowsArray) > 0 {
126+
_, ok := rowsArray[0].(map[string]interface{})
127+
if !ok {
128+
// check if it is an array
129+
if isArrayOrSlice(rowsArray[0]) {
130+
dataType = 2
131+
}
132+
}
133+
}
134+
135+
colNamesArray := make([]string, 0)
136+
colIndexArray := make([]int, 0)
137+
138+
if dataType == 2 {
139+
// all colNames must be string:number format
140+
for _, colName := range colNames {
141+
// Num ignore
142+
if colName == "Num" {
143+
colNamesArray = append(colNamesArray, colName)
144+
continue
145+
}
146+
if !strings.Contains(colName, ":") {
147+
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
148+
}
149+
// split colName to name and number, must be two parts
150+
parts := strings.Split(colName, ":")
151+
if len(parts) != 2 {
152+
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
153+
}
154+
// check if number is a number, use regex match
155+
if !isNumber(parts[1]) {
156+
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
157+
}
158+
colNamesArray = append(colNamesArray, parts[0])
159+
num, err := strconv.Atoi(parts[1])
160+
if err != nil {
161+
return "", fmt.Errorf("colNames: %s must be string:number format, like 'name:0', 0 is the array index", colName)
162+
}
163+
colIndexArray = append(colIndexArray, num)
164+
}
165+
}
166+
115167
var buf bytes.Buffer
116168
writer := bufio.NewWriter(&buf)
117169
format := strings.Repeat("%v\t ", len(colNames)-1) + "%v"
118170
w := tabwriter.NewWriter(writer, 0, 0, 1, ' ', tabwriter.Debug)
119-
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(colNames)...))
171+
if dataType == 1 {
172+
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(colNames)...))
173+
174+
separator := ""
175+
for i, colName := range colNames {
176+
separator = separator + strings.Repeat("-", len(colName))
177+
if i < len(colNames)-1 {
178+
separator = separator + "\t "
179+
}
180+
}
181+
182+
fmt.Fprintln(w, separator)
183+
} else {
184+
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(colNamesArray)...))
120185

121-
separator := ""
122-
for i, colName := range colNames {
123-
separator = separator + strings.Repeat("-", len(colName))
124-
if i < len(colNames)-1 {
125-
separator = separator + "\t "
186+
separator := ""
187+
for i, colNameArray := range colNamesArray {
188+
separator = separator + strings.Repeat("-", len(colNameArray))
189+
if i < len(colNamesArray)-1 {
190+
separator = separator + "\t "
191+
}
126192
}
193+
194+
fmt.Fprintln(w, separator)
127195
}
128-
fmt.Fprintln(w, separator)
129196

130197
for i, row := range rowsArray {
131198
r := make([]string, 0)
@@ -138,10 +205,18 @@ func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v int
138205
index = 1
139206
}
140207
}
141-
for _, colName := range colNames[index:] {
142-
v, _ := jmespath.Search(colName, row)
143-
s = fmt.Sprintf("%v", v)
144-
r = append(r, s)
208+
if dataType == 1 {
209+
for _, colName := range colNames[index:] {
210+
v, _ := jmespath.Search(colName, row)
211+
s = fmt.Sprintf("%v", v)
212+
r = append(r, s)
213+
}
214+
} else {
215+
for _, colIndex := range colIndexArray {
216+
v, _ := jmespath.Search(fmt.Sprintf("[%d]", colIndex), row)
217+
s = fmt.Sprintf("%v", v)
218+
r = append(r, s)
219+
}
145220
}
146221
fmt.Fprintln(w, fmt.Sprintf(format, toIntfArray(r)...))
147222
}
@@ -150,6 +225,16 @@ func (a *TableOutputFilter) FormatTable(rowPath string, colNames []string, v int
150225
return buf.String(), nil
151226
}
152227

228+
func isNumber(s string) bool {
229+
for _, c := range s {
230+
if c < '0' || c > '9' {
231+
return false
232+
}
233+
}
234+
return true
235+
236+
}
237+
153238
func toIntfArray(stringArray []string) []interface{} {
154239
intfArray := []interface{}{}
155240

openapi/output_filter_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,23 @@ func TestTableOutputFilter_FormatTable(t *testing.T) {
104104
str, err = tableout.FormatTable(rowpath, colNames, v)
105105
assert.Equal(t, "Num | name | type | api\n--- | ---- | ---- | ---\n0 | <nil> | <nil> | <nil>\n1 | <nil> | <nil> | <nil>\n", str)
106106
assert.Nil(t, err)
107+
108+
// test array format
109+
v = map[string]interface{}{
110+
"User": []interface{}{
111+
[]string{"test", "test2"},
112+
[]string{"test3", "test4"},
113+
},
114+
}
115+
colNames = []string{"name:0", "type:1"}
116+
str, err = tableout.FormatTable(rowpath, colNames, v)
117+
assert.Equal(t, "Num | name | type\n--- | ---- | ----\n0 | test | test2\n1 | test3 | test4\n", str)
118+
assert.Nil(t, err)
119+
// test array format
120+
colNames = []string{"name", "type:1"}
121+
str, err = tableout.FormatTable(rowpath, colNames, v)
122+
assert.NotNil(t, err)
123+
assert.Equal(t, "colNames: name must be string:number format, like 'name:0', 0 is the array index", err.Error())
107124
}
108125

109126
func TestUnquoteString(t *testing.T) {

0 commit comments

Comments
 (0)