func (gopt *GetOpt) HelpCommand(description string) *GetOpt {
	if description == "" {
		description = gopt.extraDetails()
	}
	opt := gopt.NewCommand("help", description)
	commands := []string{}
	for name, _ := range gopt.commands {
		commands = append(commands, name)
	}
	opt.CustomCompletion(commands)
	return opt
}
HelpCommand - Adds a help command with completion for all other commands.
NOTE: Define after all other commands have been defined.
package getoptions
import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
	"syscall"
	"github.com/DavidGamba/go-getoptions/completion"
	"github.com/DavidGamba/go-getoptions/help"
	"github.com/DavidGamba/go-getoptions/option"
	"github.com/DavidGamba/go-getoptions/text"
)
var Debug = log.New(ioutil.Discard, "DEBUG: ", log.Ldate|log.Ltime|log.Lshortfile)
type Mode int
const (
	Normal Mode = iota
	Bundling
	SingleDash
)
type UnknownMode int
const (
	Fail UnknownMode = iota
	Warn
	Pass
)
type HelpSection int
const (
	helpDefaultName HelpSection = iota
	HelpName
	HelpSynopsis
	HelpCommandList
	HelpOptionList
)
var exitFn = os.Exit
var completionWriter io.Writer = os.Stdout
type GetOpt struct {
	name         string
	description  string
	synopsisArgs string
	selfCalled   bool
	isCommand bool
	CommandFn CommandFn
	parent *GetOpt
	mode           Mode         
	unknownMode    UnknownMode  
	requireOrder   bool         
	mapKeysToLower bool         
	Writer io.Writer  
	obj        map[string]*option.Option  
	commands   map[string]*GetOpt
	args       *argList
	completion *completion.Node
}
type ModifyFn func(*option.Option)
type CommandFn func(context.Context, *GetOpt, []string) error
func New() *GetOpt {
	root := completion.NewNode("root", completion.Root, nil)
	root.AddChild(completion.NewNode("options", completion.OptionsNode, nil))
	gopt := &GetOpt{
		name:       filepath.Base(os.Args[0]),
		obj:        make(map[string]*option.Option),
		commands:   make(map[string]*GetOpt),
		Writer:     os.Stderr,
		completion: root,
	}
	return gopt
}
func (gopt *GetOpt) NewCommand(name string, description string) *GetOpt {
	if name == "" {
		panic("NewCommand name must not be empty!")
	}
	cmd := New()
	cmd.isCommand = true
	cmd.name = name
	cmd.description = description
	cmd.parent = gopt
	node := cmd.completion
	node.Kind = completion.StringNode
	node.Name = cmd.name
	gopt.completion.AddChild(node)
	gopt.commands[cmd.name] = cmd
	return cmd
}
func (gopt *GetOpt) SetCommandFn(fn CommandFn) *GetOpt {
	gopt.CommandFn = fn
	return gopt
}
func (gopt *GetOpt) completionAppendAliases(aliases []string) {
	node := gopt.completion.GetChildByName("options")
	for _, alias := range aliases {
		if len(alias) == 1 {
			node.Entries = append(node.Entries, "-"+alias)
		} else {
			node.Entries = append(node.Entries, "--"+alias)
		}
	}
}
func (gopt *GetOpt) Self(name string, description string) *GetOpt {
	if name != "" {
		gopt.name = name
	}
	gopt.description = description
	gopt.selfCalled = true
	return gopt
}
func (gopt *GetOpt) extraDetails() string {
	scriptName := filepath.Base(os.Args[0])
	description := ""
	if gopt.isCommand {
		description = fmt.Sprintf("Use '%s %s help <command>' for extra details.", scriptName, gopt.name)
	} else {
		description = fmt.Sprintf("Use '%s help <command>' for extra details.", scriptName)
	}
	return description
}
func (gopt *GetOpt) Dispatch(ctx context.Context, helpOptionName string, args []string) error {
	if len(args) == 0 {
		fmt.Fprintf(gopt.Writer, gopt.Help())
		fmt.Fprintf(gopt.Writer, gopt.extraDetails()+"\n")
		exitFn(1)
		return nil
	}
	switch args[0] {
	case "help":
		if len(args) > 1 {
			commandName := args[1]
			for name, v := range gopt.commands {
				if commandName == name {
					fmt.Fprintf(gopt.Writer, v.Help())
					exitFn(1)
					return nil
				}
			}
			return fmt.Errorf("Unkown help entry '%s'", commandName)
		}
		fmt.Fprintf(gopt.Writer, gopt.Help())
		fmt.Fprintf(gopt.Writer, gopt.extraDetails()+"\n")
		exitFn(1)
		return nil
	default:
		commandName := args[0]
		for name, v := range gopt.commands {
			if commandName == name {
				if v.CommandFn != nil {
					err := v.CommandFn(ctx, v, args[1:])
					if err != nil {
						return err
					}
				}
				return nil
			}
		}
		if strings.HasPrefix(args[0], "-") {
			return fmt.Errorf(`Not a command or a valid option: '%s'
       Did you mean to pass it after the command?`, args[0])
		}
		return fmt.Errorf("Not a command: '%s'", args[0])
	}
}
func (gopt *GetOpt) failIfDefined(aliases []string) {
	for _, a := range aliases {
		for _, option := range gopt.obj {
			for _, v := range option.Aliases {
				if v == a {
					panic(fmt.Sprintf("Option/Alias '%s' is already defined", a))
				}
			}
		}
		if gopt.parent != nil {
			for _, option := range gopt.parent.obj {
				for _, v := range option.Aliases {
					if v == a {
						panic(fmt.Sprintf("Option/Alias '%s' is already defined", a))
					}
				}
			}
		}
	}
}
func (gopt *GetOpt) Called(name string) bool {
	if v, ok := gopt.obj[name]; ok {
		return v.Called
	}
	return false
}
func (gopt *GetOpt) CalledAs(name string) string {
	if v, ok := gopt.obj[name]; ok {
		return v.UsedAlias
	}
	return ""
}
func (gopt *GetOpt) Value(name string) interface{} {
	opt := gopt.Option(name)
	if opt != nil {
		return opt.Value()
	}
	return nil
}
func (gopt *GetOpt) Option(name string) *option.Option {
	if value, ok := gopt.obj[name]; ok {
		return value
	}
	return nil
}
func (gopt *GetOpt) SetOption(opts ...*option.Option) *GetOpt {
	node := gopt.completion.GetChildByName("options")
	for _, opt := range opts {
		if gopt.isCommand {
			opt.IsPassedToCommand = true
		}
		gopt.obj[opt.Name] = opt
		node.Entries = append(node.Entries, opt.Name)
	}
	return gopt
}
func (gopt *GetOpt) setOption(opts ...*option.Option) *GetOpt {
	node := gopt.completion.GetChildByName("options")
	for _, opt := range opts {
		gopt.obj[opt.Name] = opt
		node.Entries = append(node.Entries, opt.Name)
	}
	return gopt
}
func (gopt *GetOpt) SetMode(mode Mode) *GetOpt {
	gopt.mode = mode
	return gopt
}
func (gopt *GetOpt) SetUnknownMode(mode UnknownMode) *GetOpt {
	gopt.unknownMode = mode
	return gopt
}
func (gopt *GetOpt) SetRequireOrder() *GetOpt {
	gopt.requireOrder = true
	return gopt
}
func (gopt *GetOpt) SetMapKeysToLower() *GetOpt {
	gopt.mapKeysToLower = true
	return gopt
}
func (gopt *GetOpt) Alias(alias ...string) ModifyFn {
	gopt.failIfDefined(alias)
	return func(opt *option.Option) {
		opt.SetAlias(alias...)
	}
}
func (gopt *GetOpt) Required(msg ...string) ModifyFn {
	var errTxt string
	if len(msg) >= 1 {
		errTxt = msg[0]
	}
	return func(opt *option.Option) {
		opt.SetRequired(errTxt)
	}
}
func (gopt *GetOpt) Description(msg string) ModifyFn {
	return func(opt *option.Option) {
		opt.Description = msg
	}
}
func (gopt *GetOpt) ArgName(name string) ModifyFn {
	return func(opt *option.Option) {
		opt.SetHelpArgName(name)
	}
}
func (gopt *GetOpt) HelpSynopsisArgs(args string) *GetOpt {
	gopt.synopsisArgs = args
	return gopt
}
func getCommandName(opt *GetOpt) string {
	if opt.isCommand {
		name := getCommandName(opt.parent)
		return fmt.Sprintf("%s %s", name, opt.name)
	}
	return opt.name
}
func (gopt *GetOpt) Help(sections ...HelpSection) string {
	if len(sections) == 0 {
		sections = []HelpSection{helpDefaultName, HelpSynopsis, HelpCommandList, HelpOptionList}
	}
	helpTxt := ""
	var scriptName string
	if gopt.isCommand {
		scriptName = getCommandName(gopt.parent)
	}
	for _, section := range sections {
		switch section {
		case helpDefaultName:
			if gopt.selfCalled || gopt.isCommand {
				helpTxt += help.Name(scriptName, gopt.name, gopt.description)
				helpTxt += "\n"
			}
		case HelpName:
			helpTxt += help.Name(scriptName, gopt.name, gopt.description)
			helpTxt += "\n"
		case HelpSynopsis:
			options := []*option.Option{}
			commands := []string{}
			for _, option := range gopt.obj {
				options = append(options, option)
			}
			for _, command := range gopt.commands {
				commands = append(commands, command.name)
			}
			helpTxt += help.Synopsis(scriptName, gopt.name, gopt.synopsisArgs, options, commands)
			helpTxt += "\n"
		case HelpCommandList:
			m := make(map[string]string)
			for _, command := range gopt.commands {
				m[command.name] = command.description
			}
			commands := help.CommandList(m)
			if commands != "" {
				helpTxt += commands
				helpTxt += "\n"
			}
		case HelpOptionList:
			options := []*option.Option{}
			for _, option := range gopt.obj {
				options = append(options, option)
			}
			helpTxt += help.OptionList(options)
			if gopt.isCommand {
				helpTxt += fmt.Sprintf("See '%s help' for information about global parameters.\n", scriptName)
			}
		}
	}
	return helpTxt
}