func (op *OptionParser) computeFlags(flags []string, opt *option) (configflag, shortflag, longflag string) { for _, flag := range flags { if strings.HasPrefix(flag, "--") { longflag = flag op.long2options[longflag] = opt slice.AppendString(&op.longflags, longflag) } else if strings.HasPrefix(flag, "-") { shortflag = flag op.short2options[shortflag] = opt slice.AppendString(&op.shortflags, shortflag) } else if strings.HasSuffix(flag, ":") { configflag = flag[0 : len(flag)-1] op.config2options[configflag] = opt slice.AppendString(&op.configflags, configflag) } else { longflag = flag op.long2options[longflag] = opt slice.AppendString(&op.longflags, longflag) } } return }
func (op *OptionParser) Parse(args []string) (remainder []string) { if op.ParseHelp && !op.helpAdded { op.Bool([]string{"-h", "--help"}, false, "show this help and exit") op.helpAdded = true } if op.ParseVersion && !op.versionAdded { op.Bool([]string{"-v", "--version"}, false, "show the version and exit") op.versionAdded = true } argLength := len(args) - 1 // Command-line auto-completion support. autocomplete := os.Getenv("OPTPARSE_AUTO_COMPLETE") if autocomplete != "" { compWords := os.Getenv("COMP_WORDS") if compWords == "" { // zsh's bashcompinit does not pass COMP_WORDS, replace with // COMP_LINE for now... compWords = os.Getenv("COMP_LINE") if compWords == "" { runtime.Exit(1) } } compWordsList := strings.Split(compWords, " ", -1) compLine := os.Getenv("COMP_LINE") compPoint, err := strconv.Atoi(os.Getenv("COMP_POINT")) if err != nil { runtime.Exit(1) } compWord, err := strconv.Atoi(os.Getenv("COMP_CWORD")) if err != nil { runtime.Exit(1) } prefix := "" if compWord > 0 { if compWord < len(compWordsList) { prefix = compWordsList[compWord] } } // At some point in the future, make autocompletion customisable per // option flag and, at that point, make use of these variables. _ = compLine _ = compPoint // Pass to the shell completion if the previous word was a flag // expecting some parameter. if (compWord - 1) > 0 { prev := compWordsList[compWord-1] if strings.HasPrefix(prev, "--") { opt, ok := op.long2options[prev] if ok { if opt.dest != "" { runtime.Exit(1) } } } else if strings.HasPrefix(prev, "-") { opt, ok := op.short2options[prev] if ok { if opt.dest != "" { runtime.Exit(1) } } } } completions := make([]string, 0) for flag, _ := range op.long2options { if strings.HasPrefix(flag, prefix) { slice.AppendString(&completions, flag) } } for flag, _ := range op.short2options { if strings.HasPrefix(flag, prefix) { slice.AppendString(&completions, flag) } } fmt.Print(strings.Join(completions, " ")) runtime.Exit(1) } if argLength == 0 { return } var opt *option var ok bool idx := 1 for { arg := args[idx] noOpt := true if strings.HasPrefix(arg, "--") { opt, ok = op.long2options[arg] if ok { noOpt = false } } else if strings.HasPrefix(arg, "-") { opt, ok = op.short2options[arg] if ok { noOpt = false } } else { slice.AppendString(&remainder, arg) if idx == argLength { break } else { idx += 1 continue } } if noOpt { runtime.Error("%s: error: no such option: %s\n", args[0], arg) } if opt.dest != "" { if idx == argLength { runtime.Error("%s: error: %s option requires an argument\n", args[0], arg) } } if opt.valueType == "bool" { if opt.longflag == "--help" && op.ParseHelp { op.PrintUsage() runtime.Exit(1) } else if opt.longflag == "--version" && op.ParseVersion { fmt.Printf("%s\n", op.Version) runtime.Exit(0) } *opt.boolValue = true opt.defined = true idx += 1 } else if opt.valueType == "string" { if idx == argLength { runtime.Error("%s: error: no value specified for %s\n", args[0], arg) } *opt.stringValue = args[idx+1] opt.defined = true idx += 2 } else if opt.valueType == "int" { if idx == argLength { runtime.Error("%s: error: no value specified for %s\n", args[0], arg) } intValue, err := strconv.Atoi(args[idx+1]) if err != nil { runtime.Error("%s: error: couldn't convert %s value '%s' to an integer\n", args[0], arg, args[idx+1]) } *opt.intValue = intValue opt.defined = true idx += 2 } if idx > argLength { break } } for _, opt := range op.options { if opt.requiredFlag && !opt.defined { runtime.Error("%s: error: required: %s", args[0], opt) } } return }