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