Beispiel #1
0
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
}
Beispiel #2
0
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

}