Skip to content

Commit

Permalink
feat: allow for configurable line length limit in the usage messages
Browse files Browse the repository at this point in the history
  • Loading branch information
steverusso committed May 19, 2024
1 parent 10d4657 commit ed0c4e8
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 25 deletions.
37 changes: 31 additions & 6 deletions clap.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"io"
"os"
"reflect"
"strconv"
)

Expand Down Expand Up @@ -93,19 +94,42 @@ func (v *clapString) Set(s string) error {
return nil
}

type clapInt[T int | int8 | int16 | int32 | int64] struct{ v *T }

func clapNewInt[T int | int8 | int16 | int32 | int64](p *T) clapInt[T] { return clapInt[T]{p} }

func (v clapInt[T]) String() string { return strconv.FormatInt(int64(*v.v), 10) }

func (v clapInt[T]) Set(s string) error {
u64, err := strconv.ParseInt(s, 0, reflect.TypeFor[T]().Bits())
if err != nil {
return numError(err)
}
*v.v = T(u64)
return nil
}

func numError(err error) error {
if ne, ok := err.(*strconv.NumError); ok {
return ne.Err
}
return err
}

func (*goclap) UsageHelp() string {
return `goclap - Pre-build tool to generate command line argument parsing code from Go comments
usage:
goclap [options]
options:
-type <arg> The root command struct name
-srcdir <arg> Directory of source files to parse (default ".")
-with-version Include goclap's version info in the generated code
-out <arg> Output file path (default "./clap.gen.go")
-version Print version info and exit
-h Show this help message`
-type <arg> The root command struct name
-srcdir <arg> Directory of source files to parse (default ".")
-with-version Include goclap's version info in the generated code
-out <arg> Output file path (default "./clap.gen.go")
-usg-text-width <arg> Max width for lines of text in the usage message
-version Print version info and exit
-h Show this help message`
}

func (c *goclap) Parse(args []string) {
Expand All @@ -116,6 +140,7 @@ func (c *goclap) Parse(args []string) {
{name: "srcdir", value: clapNewString(&c.srcDir)},
{name: "with-version", value: clapNewBool(&c.withVersion)},
{name: "out", value: clapNewString(&c.outFilePath)},
{name: "usg-text-width", value: clapNewInt(&c.usgTextWidth)},
{name: "version", value: clapNewBool(&c.version)},
},
}
Expand Down
35 changes: 17 additions & 18 deletions generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"unicode"
)

const maxUsgLineLen = 90

var (
//go:embed tmpls/base-unexported.go.tmpl
baseUnexportedTmplText string
Expand All @@ -22,8 +20,8 @@ var (
parseFnTmplText string
)

func generate(incVersion bool, pkgName string, root *command) ([]byte, error) {
g, err := newGenerator()
func generate(incVersion bool, pkgName string, usgTextWidth int, root *command) ([]byte, error) {
g, err := newGenerator(usgTextWidth)
if err != nil {
return nil, fmt.Errorf("initializing generator: %w", err)
}
Expand All @@ -37,16 +35,15 @@ func generate(incVersion bool, pkgName string, root *command) ([]byte, error) {
}

type generator struct {
buf bytes.Buffer
usgFnTmpl *template.Template
parseFnTmpl *template.Template
buf bytes.Buffer
usgTextWidth int
usgFnTmpl *template.Template
parseFnTmpl *template.Template
}

func newGenerator() (generator, error) {
usgFnTmpl, err := template.New("usagefunc").Parse(usgFnTmplText)
if err != nil {
return generator{}, fmt.Errorf("parsing template: %w", err)
}
func newGenerator(usgTextWidth int) (generator, error) {
usgFnTmpl := template.Must(template.New("usagefunc").Parse(usgFnTmplText))

parseFuncs := template.FuncMap{
"add": func(a, b int) int { return a + b },
}
Expand All @@ -55,8 +52,9 @@ func newGenerator() (generator, error) {
return generator{}, fmt.Errorf("parsing template: %w", err)
}
return generator{
usgFnTmpl: usgFnTmpl,
parseFnTmpl: parseFnTmpl,
usgTextWidth: usgTextWidth,
usgFnTmpl: usgFnTmpl,
parseFnTmpl: parseFnTmpl,
}, nil
}

Expand Down Expand Up @@ -183,7 +181,7 @@ func (g *generator) genCmdUsageFunc(c *command) error {
if v, ok := o.data.getConfig("env"); ok {
desc += " [$" + v + "]"
}
optUsgs[i] = paddedNameAndArg + wrapBlurb(desc, len(paddedNameAndArg), maxUsgLineLen)
optUsgs[i] = paddedNameAndArg + wrapBlurb(desc, len(paddedNameAndArg), g.usgTextWidth)
}
}

Expand All @@ -201,7 +199,7 @@ func (g *generator) genCmdUsageFunc(c *command) error {
if v, ok := a.data.getConfig("env"); ok {
desc += " [$" + v + "]"
}
argUsgs[i] = paddedName + wrapBlurb(desc, len(paddedName), maxUsgLineLen)
argUsgs[i] = paddedName + wrapBlurb(desc, len(paddedName), g.usgTextWidth)
}
}

Expand All @@ -215,7 +213,7 @@ func (g *generator) genCmdUsageFunc(c *command) error {
}
for i, sc := range c.Subcmds {
paddedName := fmt.Sprintf(" %-*s ", subcmdNameColWidth, sc.UsgName())
subcmdUsgs[i] = paddedName + wrapBlurb(sc.Data.Blurb, len(paddedName), maxUsgLineLen)
subcmdUsgs[i] = paddedName + wrapBlurb(sc.Data.Blurb, len(paddedName), g.usgTextWidth)
}
}

Expand Down Expand Up @@ -287,7 +285,8 @@ func (c *command) Overview() string {
paras := c.Data.overview
var s strings.Builder
for i := range paras {
s.WriteString(wrapText(paras[i], 3, maxUsgLineLen))
s.WriteString(" ")
s.WriteString(paras[i])
if i != len(paras)-1 {
s.WriteString("\n\n")
}
Expand Down
10 changes: 9 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type goclap struct {
//
// clap:opt out
outFilePath string
// Max width for lines of text in the usage message.
//
// clap:opt usg-text-width
usgTextWidth int
// Print version info and exit.
//
// clap:opt version
Expand Down Expand Up @@ -143,6 +147,10 @@ func (c *command) UsgName() string {
}

func gen(c *goclap) error {
if c.usgTextWidth == 0 {
c.usgTextWidth = 90
}

rootCmdTypeName := c.rootCmdType
if rootCmdTypeName == "" {
fmt.Fprintf(os.Stderr, "no root command type provided\n")
Expand All @@ -155,7 +163,7 @@ func gen(c *goclap) error {
return err
}

code, err := generate(c.withVersion, pkgName, &rootCmd)
code, err := generate(c.withVersion, pkgName, c.usgTextWidth, &rootCmd)
if err != nil {
return err
}
Expand Down

0 comments on commit ed0c4e8

Please sign in to comment.