Skip to content

Commit

Permalink
Make a thin wrapper around tabwriter (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
FollowTheProcess authored Aug 3, 2024
1 parent 7e11a1b commit 79a8195
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 23 deletions.
2 changes: 1 addition & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ Things I want to do to make this library as good as it can be and a better, simp
- [ ] Write a package example doc
- [ ] Make the help output as pretty as possible, see [clap] for inspiration as their help is so nice
- [x] Implement something nice to do the whole `-- <bonus args>` thing, maybe `ExtraArgs`?
- [ ] Thin wrapper around tabwriter to keep it consistent
- [x] Thin wrapper around tabwriter to keep it consistent

[clap]: https://github.com/clap-rs/clap
14 changes: 3 additions & 11 deletions command.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,10 @@ import (
"os"
"slices"
"strings"
"text/tabwriter"
"unicode/utf8"

"github.com/FollowTheProcess/cli/internal/flag"
)

// TableWriter config, used for showing subcommands in help.
const (
minWidth = 2 // Min cell width
tabWidth = 8 // Tab width in spaces
padding = 1 // Padding
padChar = '\t' // Char to pad with
"github.com/FollowTheProcess/cli/internal/table"
)

// New builds and returns a new [Command].
Expand Down Expand Up @@ -474,9 +466,9 @@ func defaultHelp(cmd *Command) error {
// Now show subcommands
if len(cmd.subcommands) != 0 {
s.WriteString("\n\nCommands:\n")
tab := tabwriter.NewWriter(s, minWidth, tabWidth, padding, padChar, tabwriter.AlignRight)
tab := table.New(s)
for _, subcommand := range cmd.subcommands {
fmt.Fprintf(tab, " %s\t%s\n", subcommand.name, subcommand.short)
tab.Row(" %s\t%s\n", subcommand.name, subcommand.short)
}
if err := tab.Flush(); err != nil {
return fmt.Errorf("could not format subcommands: %w", err)
Expand Down
16 changes: 5 additions & 11 deletions internal/flag/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,9 @@ import (
"fmt"
"slices"
"strings"
"text/tabwriter"
"unicode/utf8"
)

// TableWriter config, used for showing subcommands in help.
const (
minWidth = 0 // Min cell width
tabWidth = 8 // Tab width in spaces
padding = 1 // Padding
padChar = '\t' // Char to pad with
"github.com/FollowTheProcess/cli/internal/table"
)

// Set is a set of command line flags.
Expand Down Expand Up @@ -197,8 +190,9 @@ func (s *Set) Usage() (string, error) {
}
slices.Sort(names)

tab := tabwriter.NewWriter(buf, minWidth, tabWidth, padding, padChar, tabwriter.TabIndent)
fmt.Fprintln(tab, "Short\tLong\tType\tDefault\tUsage")
tab := table.New(buf)
tab.Row("Short\tLong\tType\tDefault\tUsage\n")

for _, name := range names {
entry := s.flags[name]
var shorthand string
Expand All @@ -215,7 +209,7 @@ func (s *Set) Usage() (string, error) {
defaultValue = `""`
}

fmt.Fprintf(tab, "%s\t--%s\t%s\t%s\t%s\n", shorthand, entry.Name, entry.Value.Type(), defaultValue, entry.Usage)
tab.Row("%s\t--%s\t%s\t%s\t%s\n", shorthand, entry.Name, entry.Value.Type(), defaultValue, entry.Usage)
}

if err := tab.Flush(); err != nil {
Expand Down
38 changes: 38 additions & 0 deletions internal/table/table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Package table implements a thin wrapper around [text/tabwriter] to keep
// formatting consistent across cli.
package table

import (
"fmt"
"io"
"text/tabwriter"
)

// TableWriter config, used for showing subcommands in help.
const (
minWidth = 2 // Min cell width
tabWidth = 8 // Tab width in spaces
padding = 1 // Padding
padChar = '\t' // Char to pad with
)

// Table is a text table.
type Table struct {
tw *tabwriter.Writer // The underlying writer
}

// New returns a new [Table], writing to w.
func New(w io.Writer) Table {
tw := tabwriter.NewWriter(w, minWidth, tabWidth, padding, padChar, tabwriter.TabIndent)
return Table{tw: tw}
}

// Row adds a row to the [Table].
func (t Table) Row(format string, a ...any) {
fmt.Fprintf(t.tw, format, a...)
}

// Flush flushes the written data to the writer.
func (t Table) Flush() error {
return t.tw.Flush()
}
45 changes: 45 additions & 0 deletions internal/table/table_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package table_test

import (
"bytes"
"flag"
"fmt"
"os"
"path/filepath"
"testing"

"github.com/FollowTheProcess/cli/internal/table"
"github.com/FollowTheProcess/test"
)

var (
debug = flag.Bool("debug", false, "Print debug output during tests")
update = flag.Bool("update", false, "Update golden files")
)

func TestTable(t *testing.T) {
buf := &bytes.Buffer{}

tab := table.New(buf)

tab.Row("Col1\tCol2\tCol3\n")
tab.Row("val1\tval2\tval3\n")
tab.Row("val4\tval5\tval6\n")

err := tab.Flush()
test.Ok(t, err)

file := filepath.Join(test.Data(t), "table.txt")

if *debug {
fmt.Printf("DEBUG (%s)\n_____\n\n%s\n", "TestTable", buf.String())
}

if *update {
t.Logf("Updating %s\n", file)
err := os.WriteFile(file, buf.Bytes(), os.ModePerm)
test.Ok(t, err)
}

test.File(t, buf.String(), "table.txt")
}
3 changes: 3 additions & 0 deletions internal/table/testdata/table.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Col1 Col2 Col3
val1 val2 val3
val4 val5 val6

0 comments on commit 79a8195

Please sign in to comment.