Merge pull request #32 from alexflint/override_program_name
make it possible to override the name of the program
This commit is contained in:
commit
aaae1550b7
26
parse.go
26
parse.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -28,7 +29,7 @@ var ErrHelp = errors.New("help requested by user")
|
||||||
|
|
||||||
// MustParse processes command line arguments and exits upon failure
|
// MustParse processes command line arguments and exits upon failure
|
||||||
func MustParse(dest ...interface{}) *Parser {
|
func MustParse(dest ...interface{}) *Parser {
|
||||||
p, err := NewParser(dest...)
|
p, err := NewParser(Config{}, dest...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
|
@ -46,20 +47,26 @@ func MustParse(dest ...interface{}) *Parser {
|
||||||
|
|
||||||
// Parse processes command line arguments and stores them in dest
|
// Parse processes command line arguments and stores them in dest
|
||||||
func Parse(dest ...interface{}) error {
|
func Parse(dest ...interface{}) error {
|
||||||
p, err := NewParser(dest...)
|
p, err := NewParser(Config{}, dest...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return p.Parse(os.Args[1:])
|
return p.Parse(os.Args[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config represents configuration options for an argument parser
|
||||||
|
type Config struct {
|
||||||
|
Program string // Program is the name of the program used in the help text
|
||||||
|
}
|
||||||
|
|
||||||
// Parser represents a set of command line options with destination values
|
// Parser represents a set of command line options with destination values
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
spec []*spec
|
spec []*spec
|
||||||
|
config Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewParser constructs a parser from a list of destination structs
|
// NewParser constructs a parser from a list of destination structs
|
||||||
func NewParser(dests ...interface{}) (*Parser, error) {
|
func NewParser(config Config, dests ...interface{}) (*Parser, error) {
|
||||||
var specs []*spec
|
var specs []*spec
|
||||||
for _, dest := range dests {
|
for _, dest := range dests {
|
||||||
v := reflect.ValueOf(dest)
|
v := reflect.ValueOf(dest)
|
||||||
|
@ -134,7 +141,16 @@ func NewParser(dests ...interface{}) (*Parser, error) {
|
||||||
specs = append(specs, &spec)
|
specs = append(specs, &spec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Parser{spec: specs}, nil
|
if config.Program == "" {
|
||||||
|
config.Program = "program"
|
||||||
|
if len(os.Args) > 0 {
|
||||||
|
config.Program = filepath.Base(os.Args[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &Parser{
|
||||||
|
spec: specs,
|
||||||
|
config: config,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse processes the given command line option, storing the results in the field
|
// Parse processes the given command line option, storing the results in the field
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func parse(cmdline string, dest interface{}) error {
|
func parse(cmdline string, dest interface{}) error {
|
||||||
p, err := NewParser(dest)
|
p, err := NewParser(Config{}, dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
6
usage.go
6
usage.go
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -30,7 +29,7 @@ func (p *Parser) WriteUsage(w io.Writer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(w, "usage: %s", filepath.Base(os.Args[0]))
|
fmt.Fprintf(w, "usage: %s", p.config.Program)
|
||||||
|
|
||||||
// write the option component of the usage message
|
// write the option component of the usage message
|
||||||
for _, spec := range options {
|
for _, spec := range options {
|
||||||
|
@ -114,8 +113,7 @@ func printOption(w io.Writer, spec *spec) {
|
||||||
}
|
}
|
||||||
fmt.Fprint(w, spec.help)
|
fmt.Fprint(w, spec.help)
|
||||||
}
|
}
|
||||||
// Check if spec.dest is zero value or not
|
// If spec.dest is not the zero value then a default value has been added.
|
||||||
// If it isn't a default value have been added
|
|
||||||
v := spec.dest
|
v := spec.dest
|
||||||
if v.IsValid() {
|
if v.IsValid() {
|
||||||
z := reflect.Zero(v.Type())
|
z := reflect.Zero(v.Type())
|
||||||
|
|
|
@ -43,7 +43,7 @@ options:
|
||||||
}
|
}
|
||||||
args.Name = "Foo Bar"
|
args.Name = "Foo Bar"
|
||||||
args.Value = 42
|
args.Value = 42
|
||||||
p, err := NewParser(&args)
|
p, err := NewParser(Config{}, &args)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
os.Args[0] = "example"
|
os.Args[0] = "example"
|
||||||
|
@ -71,7 +71,25 @@ options:
|
||||||
VeryLongPositionalWithHelp string `arg:"positional,help:this positional argument is very long"`
|
VeryLongPositionalWithHelp string `arg:"positional,help:this positional argument is very long"`
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := NewParser(&args)
|
p, err := NewParser(Config{}, &args)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
os.Args[0] = "example"
|
||||||
|
var help bytes.Buffer
|
||||||
|
p.WriteHelp(&help)
|
||||||
|
assert.Equal(t, expectedHelp, help.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUsageWithProgramName(t *testing.T) {
|
||||||
|
expectedHelp := `usage: myprogram
|
||||||
|
|
||||||
|
options:
|
||||||
|
--help, -h display this help and exit
|
||||||
|
`
|
||||||
|
config := Config{
|
||||||
|
Program: "myprogram",
|
||||||
|
}
|
||||||
|
p, err := NewParser(config, &struct{}{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
os.Args[0] = "example"
|
os.Args[0] = "example"
|
||||||
|
|
Loading…
Reference in New Issue