func (p *Parser) WithOptCompleter(c Completer) *Parser {
	p.nextCompleter = c
	return p
}
WithOptCompleter will use the provided Completer to
autocomplete the next defined option.
package optparse
import (
	"fmt"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
	"github.com/flynn/go-shlex"
	"github.com/tav/golly/log"
	"github.com/tav/golly/process"
	"github.com/tav/golly/structure"
)
type valueType int
const (
	boolValue valueType = iota
	durationValue
	floatValue
	intValue
	intSliceValue
	stringValue
	stringSliceValue
)
type Completer interface {
	Complete([]string, int) []string
}
type IndexedCompleter map[int][]string
func (c IndexedCompleter) Complete(args []string, cword int) []string {
	return c[cword]
}
type ListCompleter []string
func (c ListCompleter) Complete([]string, int) []string {
	return c
}
func exit(message string, v ...interface{}) {
	log.Errorf(message, v...)
	process.Exit(1)
}
type Parser struct {
	Completer             Completer
	HelpOptDescription    string
	HideHelpOpt           bool
	HideVersionOpt        bool
	OptPadding            int
	ParseHelp             bool
	ParseVersion          bool
	Usage                 string
	VersionOptDescription string
	haltFlagParsing       bool
	haltFlagParsingN      int
	haltFlagParsingString string
	helpAdded             bool
	long2options          map[string]*option
	longFlags             []string
	nextCompleter         Completer
	nextFlags             []string
	nextHidden            bool
	nextLabel             string
	nextRequired          bool
	options               []*option
	short2options         map[string]*option
	shortFlags            []string
	version               func() string
	versionAdded          bool
}
type option struct {
	completer   Completer
	defined     bool
	description string
	hidden      bool
	label       string
	longFlag    string
	required    bool
	shortFlag   string
	value       interface{}
	valueType   valueType
}
func (op *option) FlagString() string {
	output := "  "
	if op.shortFlag != "" {
		output += op.shortFlag
		if op.longFlag != "" {
			output += ", "
		}
	}
	if op.longFlag != "" {
		output += op.longFlag
	}
	if op.label != "" {
		output += " " + op.label
	}
	return output
}
func (op *option) Print(format string) {
	flagString := op.FlagString()
	fmt.Printf(format, flagString, op.description)
}
func (p *Parser) newOpt(description string, showLabel bool) *option {
	op := &option{}
	op.completer = p.nextCompleter
	op.description = description
	op.hidden = p.nextHidden
	op.required = p.nextRequired
	for _, flag := range p.nextFlags {
		if strings.HasPrefix(flag, "--") {
			op.longFlag = flag
			p.long2options[flag] = op
			p.longFlags = append(p.longFlags, flag)
		} else if strings.HasPrefix(flag, "-") {
			op.shortFlag = flag
			p.short2options[flag] = op
			p.shortFlags = append(p.shortFlags, flag)
		}
	}
	if op.shortFlag == "" && op.longFlag == "" {
		exit("optparse: no -short or --long flags found for option with description: %s", description)
	}
	if !op.hidden {
		if showLabel {
			if p.nextLabel != "" {
				op.label = p.nextLabel
			} else {
				if op.longFlag != "" {
					op.label = strings.ToUpper(strings.TrimLeft(op.longFlag, "-"))
				} else {
					op.label = strings.ToUpper(strings.TrimLeft(op.shortFlag, "-"))
				}
			}
		}
		width := len(op.FlagString())
		if width > p.OptPadding {
			p.OptPadding = width
		}
	}
	p.options = append(p.options, op)
	p.nextCompleter = nil
	p.nextFlags = nil
	p.nextHidden = false
	p.nextLabel = ""
	p.nextRequired = false
	return op
}
func (p *Parser) Bool(description string) *bool {
	v := false
	op := p.newOpt(description, false)
	op.valueType = boolValue
	op.value = &v
	return &v
}
func (p *Parser) Duration(description string, defaultValue ...time.Duration) *time.Duration {
	v := time.Duration(0)
	if len(defaultValue) > 0 {
		v = defaultValue[0]
	} else if strings.HasSuffix(description, "]") {
		if idx := strings.LastIndex(description, "["); idx != 1 {
			var err error
			v, err = time.ParseDuration(description[idx+1 : len(description)-1])
			if err != nil {
				exit("optparse: could not parse default value from: %s", description)
			}
		}
	}
	op := p.newOpt(description, true)
	op.valueType = durationValue
	op.value = &v
	return &v
}
func (p *Parser) Float(description string, defaultValue ...float64) *float64 {
	var v float64
	if len(defaultValue) > 0 {
		v = defaultValue[0]
	} else if strings.HasSuffix(description, "]") {
		if idx := strings.LastIndex(description, "["); idx != 1 {
			var err error
			v, err = strconv.ParseFloat(description[idx+1:len(description)-1], 64)
			if err != nil {
				exit("optparse: could not parse default value from: %s", description)
			}
		}
	}
	op := p.newOpt(description, true)
	op.valueType = floatValue
	op.value = &v
	return &v
}
func (p *Parser) Int(description string, defaultValue ...int) *int {
	v := 0
	if len(defaultValue) > 0 {
		v = defaultValue[0]
	} else if strings.HasSuffix(description, "]") {
		if idx := strings.LastIndex(description, "["); idx != 1 {
			var err error
			v, err = strconv.Atoi(description[idx+1 : len(description)-1])
			if err != nil {
				exit("optparse: could not parse default value from: %s", description)
			}
		}
	}
	op := p.newOpt(description, true)
	op.valueType = intValue
	op.value = &v
	return &v
}
func (p *Parser) String(description string, defaultValue ...string) *string {
	v := ""
	if len(defaultValue) > 0 {
		v = defaultValue[0]
	} else if strings.HasSuffix(description, "]") {
		if idx := strings.LastIndex(description, "["); idx != 1 {
			v = description[idx+1 : len(description)-1]
		}
	}
	op := p.newOpt(description, true)
	op.valueType = stringValue
	op.value = &v
	return &v
}
func (p *Parser) Flags(flags ...string) *Parser {
	p.nextFlags = flags
	return p
}
func (p *Parser) Hidden() *Parser {
	p.nextHidden = true
	return p
}
func (p *Parser) Required() *Parser {
	p.nextRequired = true
	return p
}