Skip to content

Commit 9953904

Browse files
feat: add markdown table rendering
1 parent 4bdc53d commit 9953904

11 files changed

Lines changed: 266 additions & 299 deletions

File tree

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.6.1] - 2024-05-15
9+
10+
### Changed
11+
12+
- Use a table writing package instead of the builtin package
13+
14+
### Added
15+
16+
- `gatecheck list --markdown` support for rendering markdown tables
17+
818
## [0.6.0] - 2024-04-26
919

1020
### Changed

cmd/v1/helper.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"os"
99
"strings"
1010

11-
"github.com/gatecheckdev/gatecheck/pkg/format"
1211
"github.com/gatecheckdev/gatecheck/pkg/gatecheck"
12+
"github.com/olekukonko/tablewriter"
1313
"github.com/spf13/cobra"
1414
"github.com/spf13/viper"
1515
)
@@ -106,14 +106,14 @@ func LoadConfigFromFile(config *gatecheck.Config, filename string) error {
106106

107107
// WriteConfigInfo as a human readable display table
108108
func WriteConfigInfo(w io.Writer, v *viper.Viper, config *gatecheck.Config) error {
109-
table := format.NewTable()
110-
table.AppendRow("key", "Value")
109+
table := tablewriter.NewWriter(w)
110+
table.SetHeader([]string{"key", "value"})
111111

112112
for _, key := range viper.AllKeys() {
113-
table.AppendRow(key, fmt.Sprintf("%v", viper.Get(key)))
113+
table.Append([]string{key, fmt.Sprintf("%v", viper.Get(key))})
114114
}
115115

116-
_, infoErr := format.NewTableWriter(table).WriteTo(w)
116+
table.Render()
117117
_, configErr := fmt.Fprintln(w, config.String())
118-
return errors.Join(infoErr, configErr)
118+
return configErr
119119
}

cmd/v1/list.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ func newListCommand() *cobra.Command {
3030
cmd.Flags().String("epss-file", "", "use this file for epss scores, will not query API")
3131
_ = viper.BindPFlag("cli.list.epss-file", cmd.Flags().Lookup("epss-file"))
3232

33+
cmd.Flags().Bool("markdown", false, "print the list as markdown")
34+
3335
return cmd
3436
}
3537

@@ -43,9 +45,16 @@ func runList(cmd *cobra.Command, args []string) error {
4345

4446
inputType, _ := cmd.Flags().GetString("input-type")
4547
listAll, _ := cmd.Flags().GetBool("all")
48+
markdown, _ := cmd.Flags().GetBool("markdown")
49+
4650
epssURL := viper.GetString("api.epss-url")
4751
epssFilename := viper.GetString("cli.list.epss-file")
4852

53+
displayFormat := "ascii"
54+
if markdown {
55+
displayFormat = "markdown"
56+
}
57+
4958
src, err := fileOrStdin(filename, cmd)
5059
if err != nil {
5160
return err
@@ -68,8 +77,21 @@ func runList(cmd *cobra.Command, args []string) error {
6877

6978
if listAll {
7079
slog.Debug("listing with epss scores")
71-
return gatecheck.ListAll(cmd.OutOrStdout(), src, filename, http.DefaultClient, epssURL, epssFile)
80+
return gatecheck.ListAll(
81+
cmd.OutOrStdout(),
82+
src,
83+
filename,
84+
http.DefaultClient,
85+
epssURL,
86+
epssFile,
87+
gatecheck.WithDisplayFormat(displayFormat),
88+
)
7289
}
7390

74-
return gatecheck.List(cmd.OutOrStdout(), src, filename)
91+
return gatecheck.List(
92+
cmd.OutOrStdout(),
93+
src,
94+
filename,
95+
gatecheck.WithDisplayFormat(displayFormat),
96+
)
7597
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.22.1
55
require (
66
github.com/dustin/go-humanize v1.0.1
77
github.com/lmittmann/tint v1.0.4
8+
github.com/olekukonko/tablewriter v0.0.5
89
github.com/pelletier/go-toml/v2 v2.2.1
910
github.com/sagikazarmark/slog-shim v0.1.0
1011
github.com/spf13/cobra v1.8.0
@@ -18,6 +19,7 @@ require (
1819
github.com/hashicorp/hcl v1.0.0 // indirect
1920
github.com/inconshreveable/mousetrap v1.1.0 // indirect
2021
github.com/magiconair/properties v1.8.7 // indirect
22+
github.com/mattn/go-runewidth v0.0.9 // indirect
2123
github.com/mitchellh/mapstructure v1.5.0 // indirect
2224
github.com/rogpeppe/go-internal v1.12.0 // indirect
2325
github.com/sagikazarmark/locafero v0.4.0 // indirect

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,12 @@ github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc=
2626
github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
2727
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
2828
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
29+
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
30+
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
2931
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
3032
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
33+
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
34+
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
3135
github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg=
3236
github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
3337
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

pkg/archive/bundle.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"io"
1414
"log/slog"
1515
"os"
16+
"sort"
1617
"strings"
1718
"time"
1819

@@ -101,7 +102,7 @@ func (b *Bundle) AddFrom(r io.Reader, label string, properties map[string]string
101102
p, err := io.ReadAll(r)
102103
_, _ = bytes.NewReader(p).WriteTo(hasher)
103104
if err != nil {
104-
return err
105+
return err
105106
}
106107
digest := fmt.Sprintf("%x", hasher.Sum(nil))
107108

@@ -146,16 +147,20 @@ func (b *Bundle) Delete(label string) {
146147
}
147148

148149
func (b *Bundle) Content() string {
149-
table := format.NewTable()
150-
table.AppendRow("Label", "Digest", "Tags", "Size")
150+
matrix := format.NewSortableMatrix(make([][]string, 0), 0, format.AlphabeticLess)
151151

152152
for label, descriptor := range b.Manifest().Files {
153153
fileSize := humanize.Bytes(uint64(b.FileSize(label)))
154154
tags := strings.Join(descriptor.Tags, ", ")
155-
table.AppendRow(label, descriptor.Digest, tags, fileSize)
155+
row := []string{label, descriptor.Digest, tags, fileSize}
156+
matrix.Append(row)
156157
}
157158

158-
return format.NewTableWriter(table).String()
159+
sort.Sort(matrix)
160+
buf := new(bytes.Buffer)
161+
header := []string{"Label", "Digest", "Tags", "Size"}
162+
matrix.Table(buf, header).Render()
163+
return buf.String()
159164
}
160165

161166
func TarGzipBundle(dst io.Writer, bundle *Bundle) (int64, error) {

pkg/format/matrix.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package format
2+
3+
import (
4+
"io"
5+
6+
"github.com/olekukonko/tablewriter"
7+
)
8+
9+
type SortableMatrix struct {
10+
data [][]string
11+
selectedColumn int
12+
lessFunc func(a, b string) bool
13+
}
14+
15+
func NewSortableMatrix(data [][]string, sortColIdx int, sortFunc func(a, b string) bool) *SortableMatrix {
16+
return &SortableMatrix{
17+
data: data,
18+
selectedColumn: sortColIdx,
19+
lessFunc: sortFunc,
20+
}
21+
}
22+
23+
func (m *SortableMatrix) Append(row []string) {
24+
m.data = append(m.data, row)
25+
}
26+
27+
func (m *SortableMatrix) Matrix() [][]string {
28+
return m.data
29+
}
30+
31+
func (m *SortableMatrix) Table(w io.Writer, header []string) *tablewriter.Table {
32+
table := tablewriter.NewWriter(w)
33+
table.SetHeader(header)
34+
table.AppendBulk(m.data)
35+
return table
36+
}
37+
38+
func (m *SortableMatrix) Len() int {
39+
return len(m.data)
40+
}
41+
42+
func (m *SortableMatrix) Swap(i, j int) {
43+
m.data[i], m.data[j] = m.data[j], m.data[i]
44+
}
45+
46+
func (m *SortableMatrix) Less(i, j int) bool {
47+
return m.lessFunc(m.data[i][m.selectedColumn], m.data[j][m.selectedColumn])
48+
}
49+
50+
func AlphabeticLess(a, b string) bool {
51+
return a < b
52+
}
53+
54+
func NewCatagoricLess(categories []string) func(a, b string) bool {
55+
return func(a, b string) bool {
56+
aIndex, bIndex := 0, 0
57+
for i, category := range categories {
58+
if a == category {
59+
aIndex = i
60+
}
61+
if b == category {
62+
bIndex = i
63+
}
64+
}
65+
return aIndex < bIndex
66+
}
67+
}

0 commit comments

Comments
 (0)