func (a *Args) String(name, help string, opts ...ArgOption) {
	a.register(name, help, "string", false,
		func(args []string, res ArgMap) ([]string, error) {
			res[name] = &ArgMapItem{Value: args[0]}
			return args[1:], nil
		},
		opts...,
	)
}
String registers a string argument.
package grumble
import (
	"fmt"
	"strconv"
	"time"
)
type parseArgFunc func(args []string, res ArgMap) ([]string, error)
type argItem struct {
	Name     string
	Help     string
	HelpArgs string
	Default  interface{}
	parser   parseArgFunc
	isList   bool
	optional bool
	listMin  int
	listMax  int
}
type Args struct {
	list []*argItem
}
func (a *Args) register(
	name, help, helpArgs string,
	isList bool,
	pf parseArgFunc,
	opts ...ArgOption,
) {
	if name == "" {
		panic("empty argument name")
	} else if help == "" {
		panic(fmt.Errorf("missing help message for argument '%s'", name))
	}
	for _, ai := range a.list {
		if ai.Name == name {
			panic(fmt.Errorf("argument '%s' registered twice", name))
		}
	}
	item := &argItem{
		Name:     name,
		Help:     help,
		HelpArgs: helpArgs,
		parser:   pf,
		isList:   isList,
		optional: isList,
		listMin:  -1,
		listMax:  -1,
	}
	for _, opt := range opts {
		opt(item)
	}
	if item.isList && item.listMax > 0 && item.listMax < item.listMin {
		panic("max must not be less than min for list arguments")
	}
	if !a.empty() {
		last := a.list[len(a.list)-1]
		if last.isList {
			panic("list argument has been registered, nothing can come after it")
		}
		if !item.optional && last.optional {
			panic("mandatory argument not allowed after optional one")
		}
	}
	a.list = append(a.list, item)
}
func (a *Args) empty() bool {
	return len(a.list) == 0
}
func (a *Args) parse(args []string, res ArgMap) ([]string, error) {
	var err error
	for _, item := range a.list {
		if item.isList {
			if len(args) < item.listMin {
				return nil, fmt.Errorf("argument '%s' requires at least %d element(s)", item.Name, item.listMin)
			}
			if item.listMax > 0 && len(args) > item.listMax {
				return nil, fmt.Errorf("argument '%s' requires at most %d element(s)", item.Name, item.listMax)
			}
		}
		if len(args) == 0 {
			if !item.optional {
				return nil, fmt.Errorf("missing argument '%s'", item.Name)
			}
			res[item.Name] = &ArgMapItem{Value: item.Default, IsDefault: true}
			continue
		}
		args, err = item.parser(args, res)
		if err != nil {
			return nil, err
		}
	}
	return args, nil
}