parse cli long args
parent
36b292c9a0
commit
ed40455f5d
@ -0,0 +1,91 @@
|
||||
package moon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parseArgs(args []string, dest interface{}) (map[string]interface{}, error) {
|
||||
reqs, err := requirements(dest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse args: bad requirements: %s", err)
|
||||
}
|
||||
|
||||
out := make(map[string]interface{})
|
||||
shorts := make(map[string]req, len(reqs))
|
||||
longs := make(map[string]req, len(reqs))
|
||||
for _, req := range reqs {
|
||||
if req.short != "" {
|
||||
shorts[req.short] = req
|
||||
}
|
||||
if req.long != "" {
|
||||
longs[req.long] = req
|
||||
}
|
||||
}
|
||||
|
||||
for i := 1; i < len(args); i++ {
|
||||
arg := args[i]
|
||||
if arg == "help" {
|
||||
showHelp(dest)
|
||||
}
|
||||
if arg == "--" {
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(arg, "--") {
|
||||
arg = strings.TrimPrefix(arg, "--")
|
||||
|
||||
var (
|
||||
key string
|
||||
val string
|
||||
)
|
||||
if strings.ContainsRune(arg, '=') {
|
||||
parts := strings.SplitN(arg, "=", 2)
|
||||
key, val = parts[0], parts[1]
|
||||
} else {
|
||||
key = arg
|
||||
i++
|
||||
if i >= len(args) {
|
||||
return nil, fmt.Errorf("terminal arg %s is missing a value", key)
|
||||
}
|
||||
val = args[i]
|
||||
}
|
||||
|
||||
req, ok := longs[key]
|
||||
if !ok {
|
||||
// ignore unknown options silently?
|
||||
log.Printf("no such long opt: %s", key)
|
||||
continue
|
||||
}
|
||||
if req.t.Kind() == reflect.Bool {
|
||||
out[key] = true
|
||||
continue
|
||||
}
|
||||
|
||||
d, err := ReadString(fmt.Sprintf("%s: %s", key, val)) // :(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse cli argument %s: %s", key, err)
|
||||
}
|
||||
out[key] = d.items[key]
|
||||
} else if strings.HasPrefix(arg, "-") {
|
||||
panic("i'm not doing short args yet")
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func showHelp(dest interface{}) {
|
||||
reqs, err := requirements(dest)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, req := range reqs {
|
||||
req.writeHelpLine(os.Stdout)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package moon
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestArgs(t *testing.T) {
|
||||
var one struct {
|
||||
Host string `name: host; short: h; default: localhost`
|
||||
Port int `name: port; short: p; required: true`
|
||||
UseSSL bool `name: ssl_enabled; long: ssl-enabled`
|
||||
CertPath string `name: ssl_cert; long: ssl-cert`
|
||||
}
|
||||
args := []string{"program", "--host=example.com", "--port", "9000"}
|
||||
vals, err := parseArgs(args, &one)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
if vals["host"] != "example.com" {
|
||||
t.Errorf("expected host 'example.com', saw host '%s'", vals["host"])
|
||||
}
|
||||
|
||||
if vals["port"] != 9000 {
|
||||
t.Errorf("expected port 9000, saw port %d", vals["port"])
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue