Start making help slightly configurable.
This commit is contained in:
+10
-16
@@ -1,15 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/alecthomas/kong"
|
"github.com/alecthomas/kong"
|
||||||
)
|
)
|
||||||
|
|
||||||
// nolint: govet
|
var cli struct {
|
||||||
var CLI struct {
|
|
||||||
Debug bool `help:"Debug mode."`
|
Debug bool `help:"Debug mode."`
|
||||||
|
|
||||||
Rm struct {
|
Rm struct {
|
||||||
@@ -17,19 +12,18 @@ var CLI struct {
|
|||||||
Force bool `help:"Force removal." short:"f"`
|
Force bool `help:"Force removal." short:"f"`
|
||||||
Recursive bool `help:"Recursively remove files." short:"r"`
|
Recursive bool `help:"Recursively remove files." short:"r"`
|
||||||
|
|
||||||
Paths []string `arg help:"Paths to remove." type:"path"`
|
Paths []string `arg:"" help:"Paths to remove." type:"path"`
|
||||||
} `cmd help:"Remove files."`
|
} `cmd:"" help:"Remove files."`
|
||||||
|
|
||||||
Ls struct {
|
Ls struct {
|
||||||
Paths []string `arg optional help:"Paths to list." type:"path"`
|
Paths []string `arg:"" optional:"" help:"Paths to list." type:"path"`
|
||||||
} `cmd help:"List paths."`
|
} `cmd:"" help:"List paths."`
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := kong.Must(&CLI, kong.Description("A shell-like example app."))
|
cmd := kong.Parse(&cli, kong.Description("A shell-like example app."), kong.HelpOptions(kong.CompactHelp()))
|
||||||
cmd, err := app.Parse(os.Args[1:])
|
switch cmd {
|
||||||
app.FatalIfErrorf(err)
|
case "rm":
|
||||||
s, _ := json.Marshal(&CLI)
|
case "ls":
|
||||||
fmt.Println(cmd)
|
}
|
||||||
fmt.Println(string(s))
|
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
@@ -9,28 +9,49 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultIndent = 2
|
defaultIndent = 2
|
||||||
|
defaultColumnPadding = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrintHelp is the default help printer.
|
// HelpOption configures the default help.
|
||||||
func PrintHelp(ctx *Context) error {
|
type HelpOption func(options *helpWriterOptions)
|
||||||
w := newHelpWriter(guessWidth(ctx.App.Stdout))
|
|
||||||
selected := ctx.Selected()
|
// CompactHelp writes help in a more compact form.
|
||||||
if selected == nil {
|
func CompactHelp() HelpOption {
|
||||||
printApp(w, ctx.App.Model)
|
return func(options *helpWriterOptions) {
|
||||||
} else {
|
options.compact = true
|
||||||
printCommand(w, ctx.App.Model, selected)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HelpPrinter returns a HelpFunction configured with the given HelpOptions.
|
||||||
|
func HelpPrinter(options ...HelpOption) HelpFunction {
|
||||||
|
return func(ctx *Context) error {
|
||||||
|
w := newHelpWriter(guessWidth(ctx.App.Stdout))
|
||||||
|
for _, option := range options {
|
||||||
|
option(&w.options)
|
||||||
|
}
|
||||||
|
selected := ctx.Selected()
|
||||||
|
if selected == nil {
|
||||||
|
printApp(w, ctx.App.Model)
|
||||||
|
} else {
|
||||||
|
printCommand(w, ctx.App.Model, selected)
|
||||||
|
}
|
||||||
|
return w.Write(ctx.App.Stdout)
|
||||||
}
|
}
|
||||||
return w.Write(ctx.App.Stdout)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printApp(w *helpWriter, app *Application) {
|
func printApp(w *helpWriter, app *Application) {
|
||||||
w.Printf("usage: %s", app.Summary())
|
w.Printf("Usage: %s", app.Summary())
|
||||||
printNodeDetail(w, &app.Node)
|
printNodeDetail(w, &app.Node)
|
||||||
|
cmds := app.Leaves()
|
||||||
|
if len(cmds) > 0 {
|
||||||
|
w.Print("")
|
||||||
|
w.Printf(`Run "%s <command> --help" for more information on a command.`, app.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printCommand(w *helpWriter, app *Application, cmd *Command) {
|
func printCommand(w *helpWriter, app *Application, cmd *Command) {
|
||||||
w.Printf("usage: %s %s", app.Name, cmd.Summary())
|
w.Printf("Usage: %s %s", app.Name, cmd.Summary())
|
||||||
printNodeDetail(w, cmd)
|
printNodeDetail(w, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +75,18 @@ func printNodeDetail(w *helpWriter, node *Node) {
|
|||||||
w.Print("")
|
w.Print("")
|
||||||
w.Print("Commands:")
|
w.Print("Commands:")
|
||||||
iw := w.Indent()
|
iw := w.Indent()
|
||||||
for i, cmd := range cmds {
|
if w.options.compact {
|
||||||
printCommandSummary(iw, cmd)
|
rows := [][2]string{}
|
||||||
if i != len(cmds)-1 {
|
for _, cmd := range cmds {
|
||||||
iw.Print("")
|
rows = append(rows, [2]string{cmd.Name, cmd.Help})
|
||||||
|
}
|
||||||
|
writeTwoColumns(iw, defaultColumnPadding, rows)
|
||||||
|
} else {
|
||||||
|
for i, cmd := range cmds {
|
||||||
|
printCommandSummary(iw, cmd)
|
||||||
|
if i != len(cmds)-1 {
|
||||||
|
iw.Print("")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,9 +100,14 @@ func printCommandSummary(w *helpWriter, cmd *Command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type helpWriter struct {
|
type helpWriter struct {
|
||||||
indent string
|
indent string
|
||||||
width int
|
width int
|
||||||
lines *[]string
|
lines *[]string
|
||||||
|
options helpWriterOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
type helpWriterOptions struct {
|
||||||
|
compact bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHelpWriter(width int) *helpWriter {
|
func newHelpWriter(width int) *helpWriter {
|
||||||
@@ -94,7 +128,7 @@ func (h *helpWriter) Print(text string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *helpWriter) Indent() *helpWriter {
|
func (h *helpWriter) Indent() *helpWriter {
|
||||||
return &helpWriter{indent: h.indent + " ", lines: h.lines, width: h.width - 2}
|
return &helpWriter{indent: h.indent + " ", lines: h.lines, width: h.width - 2, options: h.options}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *helpWriter) String() string {
|
func (h *helpWriter) String() string {
|
||||||
@@ -113,7 +147,7 @@ func (h *helpWriter) Write(w io.Writer) error {
|
|||||||
|
|
||||||
func (h *helpWriter) Wrap(text string) {
|
func (h *helpWriter) Wrap(text string) {
|
||||||
w := bytes.NewBuffer(nil)
|
w := bytes.NewBuffer(nil)
|
||||||
doc.ToText(w, strings.TrimSpace(text), "", "", h.width)
|
doc.ToText(w, strings.TrimSpace(text), "", " ", h.width)
|
||||||
for _, line := range strings.Split(strings.TrimSpace(w.String()), "\n") {
|
for _, line := range strings.Split(strings.TrimSpace(w.String()), "\n") {
|
||||||
h.Print(line)
|
h.Print(line)
|
||||||
}
|
}
|
||||||
@@ -124,7 +158,7 @@ func writePositionals(w *helpWriter, args []*Positional) {
|
|||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
rows = append(rows, [2]string{arg.Summary(), arg.Help})
|
rows = append(rows, [2]string{arg.Summary(), arg.Help})
|
||||||
}
|
}
|
||||||
writeTwoColumns(w, 2, rows)
|
writeTwoColumns(w, defaultColumnPadding, rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeFlags(w *helpWriter, groups [][]*Flag) {
|
func writeFlags(w *helpWriter, groups [][]*Flag) {
|
||||||
@@ -148,7 +182,7 @@ func writeFlags(w *helpWriter, groups [][]*Flag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeTwoColumns(w, 2, rows)
|
writeTwoColumns(w, defaultColumnPadding, rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeTwoColumns(w *helpWriter, padding int, rows [][2]string) {
|
func writeTwoColumns(w *helpWriter, padding int, rows [][2]string) {
|
||||||
|
|||||||
+18
-16
@@ -53,18 +53,18 @@ func TestHelp(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.True(t, exited)
|
require.True(t, exited)
|
||||||
t.Log(w.String())
|
t.Log(w.String())
|
||||||
require.Equal(t, `usage: test-app --required <command>
|
require.Equal(t, `Usage: test-app --required <command>
|
||||||
|
|
||||||
A test app.
|
A test app.
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--help Show context-sensitive help.
|
--help Show context-sensitive help.
|
||||||
--string=STRING A string flag.
|
--string=STRING A string flag.
|
||||||
--bool A bool flag with very long help that wraps a lot and is
|
--bool A bool flag with very long help that wraps a lot and is
|
||||||
verbose and is really verbose.
|
verbose and is really verbose.
|
||||||
--slice=STR,... A slice of strings.
|
--slice=STR,... A slice of strings.
|
||||||
--map=KEY=VALUE A map of strings to ints.
|
--map=KEY=VALUE A map of strings to ints.
|
||||||
--required A required flag.
|
--required A required flag.
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
one --required
|
one --required
|
||||||
@@ -75,6 +75,8 @@ Commands:
|
|||||||
|
|
||||||
two four --required --required-two
|
two four --required --required-two
|
||||||
Sub-sub-command.
|
Sub-sub-command.
|
||||||
|
|
||||||
|
Run "test-app <command> --help" for more information on a command.
|
||||||
`, w.String())
|
`, w.String())
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -87,19 +89,19 @@ Commands:
|
|||||||
})
|
})
|
||||||
require.True(t, exited)
|
require.True(t, exited)
|
||||||
t.Log(w.String())
|
t.Log(w.String())
|
||||||
require.Equal(t, `usage: test-app two <three> --required --required-two --required-three
|
require.Equal(t, `Usage: test-app two <three> --required --required-two --required-three
|
||||||
|
|
||||||
Sub-sub-arg.
|
Sub-sub-arg.
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--string=STRING A string flag.
|
--string=STRING A string flag.
|
||||||
--bool A bool flag with very long help that wraps a lot and is
|
--bool A bool flag with very long help that wraps a lot and is
|
||||||
verbose and is really verbose.
|
verbose and is really verbose.
|
||||||
--slice=STR,... A slice of strings.
|
--slice=STR,... A slice of strings.
|
||||||
--map=KEY=VALUE A map of strings to ints.
|
--map=KEY=VALUE A map of strings to ints.
|
||||||
--required A required flag.
|
--required A required flag.
|
||||||
|
|
||||||
--flag=STRING Nested flag under two.
|
--flag=STRING Nested flag under two.
|
||||||
--required-two
|
--required-two
|
||||||
|
|
||||||
--required-three
|
--required-three
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ type Kong struct {
|
|||||||
registry *Registry
|
registry *Registry
|
||||||
noDefaultHelp bool
|
noDefaultHelp bool
|
||||||
help func(*Context) error
|
help func(*Context) error
|
||||||
|
helpOptions []HelpOption
|
||||||
|
|
||||||
// Set temporarily by Options. These are applied after build().
|
// Set temporarily by Options. These are applied after build().
|
||||||
postBuildOptions []Option
|
postBuildOptions []Option
|
||||||
@@ -58,12 +59,17 @@ func New(grammar interface{}, options ...Option) (*Kong, error) {
|
|||||||
Stderr: os.Stderr,
|
Stderr: os.Stderr,
|
||||||
before: map[reflect.Value]HookFunc{},
|
before: map[reflect.Value]HookFunc{},
|
||||||
registry: NewRegistry().RegisterDefaults(),
|
registry: NewRegistry().RegisterDefaults(),
|
||||||
help: PrintHelp,
|
|
||||||
resolvers: []ResolverFunc{Envars()},
|
resolvers: []ResolverFunc{Envars()},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
option(k)
|
if err := option(k); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if k.help == nil {
|
||||||
|
k.help = HelpPrinter(k.helpOptions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
model, err := build(k, grammar)
|
model, err := build(k, grammar)
|
||||||
@@ -74,8 +80,11 @@ func New(grammar interface{}, options ...Option) (*Kong, error) {
|
|||||||
k.Model = model
|
k.Model = model
|
||||||
|
|
||||||
for _, option := range k.postBuildOptions {
|
for _, option := range k.postBuildOptions {
|
||||||
option(k)
|
if err := option(k); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
k.postBuildOptions = nil
|
||||||
|
|
||||||
return k, nil
|
return k, nil
|
||||||
}
|
}
|
||||||
@@ -98,14 +107,14 @@ func (k *Kong) extraFlags() []*Flag {
|
|||||||
}
|
}
|
||||||
helpFlag.Flag = helpFlag
|
helpFlag.Flag = helpFlag
|
||||||
hook := Hook(&helpValue, func(ctx *Context, path *Path) error {
|
hook := Hook(&helpValue, func(ctx *Context, path *Path) error {
|
||||||
err := PrintHelp(ctx)
|
err := k.help(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
k.Exit(1)
|
k.Exit(1)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
hook(k)
|
_ = hook(k)
|
||||||
return []*Flag{helpFlag}
|
return []*Flag{helpFlag}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,29 @@ type Node struct {
|
|||||||
Argument *Value // Populated when Type is ArgumentNode.
|
Argument *Value // Populated when Type is ArgumentNode.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Find a command/argument/flag by pointer to its field.
|
||||||
|
//
|
||||||
|
// Returns nil if not found. Panics if ptr is not a pointer.
|
||||||
|
func (n *Node) Find(ptr interface{}) *Node {
|
||||||
|
key := reflect.ValueOf(ptr)
|
||||||
|
if key.Kind() != reflect.Ptr {
|
||||||
|
panic("expected a pointer")
|
||||||
|
}
|
||||||
|
return n.findNode(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) findNode(key reflect.Value) *Node {
|
||||||
|
if n.Target == key {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
for _, child := range n.Children {
|
||||||
|
if found := child.findNode(key); found != nil {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// AllFlags returns flags from all ancestor branches encountered.
|
// AllFlags returns flags from all ancestor branches encountered.
|
||||||
func (n *Node) AllFlags() (out [][]*Flag) {
|
func (n *Node) AllFlags() (out [][]*Flag) {
|
||||||
if n.Parent != nil {
|
if n.Parent != nil {
|
||||||
|
|||||||
Executable → Regular
+51
-17
@@ -10,63 +10,84 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// An Option applies optional changes to the Kong application.
|
// An Option applies optional changes to the Kong application.
|
||||||
type Option func(k *Kong)
|
type Option func(k *Kong) error
|
||||||
|
|
||||||
// Exit overrides the function used to terminate. This is useful for testing or interactive use.
|
// Exit overrides the function used to terminate. This is useful for testing or interactive use.
|
||||||
func Exit(exit func(int)) Option {
|
func Exit(exit func(int)) Option {
|
||||||
return func(k *Kong) { k.Exit = exit }
|
return func(k *Kong) error {
|
||||||
|
k.Exit = exit
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoDefaultHelp disables the default help flags.
|
// NoDefaultHelp disables the default help flags.
|
||||||
func NoDefaultHelp() Option {
|
func NoDefaultHelp() Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.noDefaultHelp = true
|
k.noDefaultHelp = true
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name overrides the application name.
|
// Name overrides the application name.
|
||||||
func Name(name string) Option {
|
func Name(name string) Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.postBuildOptions = append(k.postBuildOptions, func(k *Kong) {
|
k.postBuildOptions = append(k.postBuildOptions, func(k *Kong) error {
|
||||||
k.Model.Name = name
|
k.Model.Name = name
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Description sets the application description.
|
// Description sets the application description.
|
||||||
func Description(description string) Option {
|
func Description(description string) Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.postBuildOptions = append(k.postBuildOptions, func(k *Kong) {
|
k.postBuildOptions = append(k.postBuildOptions, func(k *Kong) error {
|
||||||
k.Model.Help = description
|
k.Model.Help = description
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeMapper registers a mapper to a type.
|
// TypeMapper registers a mapper to a type.
|
||||||
func TypeMapper(typ reflect.Type, mapper Mapper) Option {
|
func TypeMapper(typ reflect.Type, mapper Mapper) Option {
|
||||||
return func(k *Kong) { k.registry.RegisterType(typ, mapper) }
|
return func(k *Kong) error {
|
||||||
|
k.registry.RegisterType(typ, mapper)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// KindMapper registers a mapper to a kind.
|
// KindMapper registers a mapper to a kind.
|
||||||
func KindMapper(kind reflect.Kind, mapper Mapper) Option {
|
func KindMapper(kind reflect.Kind, mapper Mapper) Option {
|
||||||
return func(k *Kong) { k.registry.RegisterKind(kind, mapper) }
|
return func(k *Kong) error {
|
||||||
|
k.registry.RegisterKind(kind, mapper)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueMapper registers a mapper to a field value.
|
// ValueMapper registers a mapper to a field value.
|
||||||
func ValueMapper(ptr interface{}, mapper Mapper) Option {
|
func ValueMapper(ptr interface{}, mapper Mapper) Option {
|
||||||
return func(k *Kong) { k.registry.RegisterValue(ptr, mapper) }
|
return func(k *Kong) error {
|
||||||
|
k.registry.RegisterValue(ptr, mapper)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamedMapper registers a mapper to a name.
|
// NamedMapper registers a mapper to a name.
|
||||||
func NamedMapper(name string, mapper Mapper) Option {
|
func NamedMapper(name string, mapper Mapper) Option {
|
||||||
return func(k *Kong) { k.registry.RegisterName(name, mapper) }
|
return func(k *Kong) error {
|
||||||
|
k.registry.RegisterName(name, mapper)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writers overrides the default writers. Useful for testing or interactive use.
|
// Writers overrides the default writers. Useful for testing or interactive use.
|
||||||
func Writers(stdout, stderr io.Writer) Option {
|
func Writers(stdout, stderr io.Writer) Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.Stdout = stdout
|
k.Stdout = stdout
|
||||||
k.Stderr = stderr
|
k.Stderr = stderr
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +105,9 @@ func Hook(ptr interface{}, hook HookFunc) Option {
|
|||||||
if key.Kind() != reflect.Ptr {
|
if key.Kind() != reflect.Ptr {
|
||||||
panic("expected a pointer")
|
panic("expected a pointer")
|
||||||
}
|
}
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.before[key] = hook
|
k.before[key] = hook
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,22 +118,33 @@ type HelpFunction func(*Context) error
|
|||||||
//
|
//
|
||||||
// Defaults to PrintHelp.
|
// Defaults to PrintHelp.
|
||||||
func Help(help HelpFunction) Option {
|
func Help(help HelpFunction) Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.help = help
|
k.help = help
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HelpOptions specifies options for the default help printer, if used.
|
||||||
|
func HelpOptions(options ...HelpOption) Option {
|
||||||
|
return func(k *Kong) error {
|
||||||
|
k.helpOptions = options
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearResolvers clears all existing resolvers.
|
// ClearResolvers clears all existing resolvers.
|
||||||
func ClearResolvers() Option {
|
func ClearResolvers() Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.resolvers = nil
|
k.resolvers = nil
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolver registers flag resolvers.
|
// Resolver registers flag resolvers.
|
||||||
func Resolver(resolvers ...ResolverFunc) Option {
|
func Resolver(resolvers ...ResolverFunc) Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
k.resolvers = append(k.resolvers, resolvers...)
|
k.resolvers = append(k.resolvers, resolvers...)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +159,7 @@ type ConfigurationFunc func(r io.Reader) (ResolverFunc, error)
|
|||||||
//
|
//
|
||||||
// ~ expansion will occur on the provided paths.
|
// ~ expansion will occur on the provided paths.
|
||||||
func Configuration(loader ConfigurationFunc, paths ...string) Option {
|
func Configuration(loader ConfigurationFunc, paths ...string) Option {
|
||||||
return func(k *Kong) {
|
return func(k *Kong) error {
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
path = expandPath(path)
|
path = expandPath(path)
|
||||||
r, err := os.Open(path) // nolint: gas
|
r, err := os.Open(path) // nolint: gas
|
||||||
@@ -139,6 +172,7 @@ func Configuration(loader ConfigurationFunc, paths ...string) Option {
|
|||||||
}
|
}
|
||||||
_ = r.Close()
|
_ = r.Close()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Executable → Regular
Executable → Regular
Reference in New Issue
Block a user