diff options
-rw-r--r-- | LICENSE | 14 | ||||
-rw-r--r-- | err.go | 15 | ||||
-rw-r--r-- | go.mod | 3 | ||||
-rw-r--r-- | opts.go | 71 |
4 files changed, 103 insertions, 0 deletions
@@ -0,0 +1,14 @@ +BSD Zero Clause License + +Copyright (c) 2023 Thomas Voss + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. @@ -0,0 +1,15 @@ +package opts + +import "fmt" + +type ErrBadOption rune + +func (e ErrBadOption) Error() string { + return fmt.Sprintf("unknown option ā%cā", e) +} + +type ErrNoArgument rune + +func (e ErrNoArgument) Error() string { + return fmt.Sprintf("expected argument for option ā%cā", e) +} @@ -0,0 +1,3 @@ +module git.sr.ht/~mango/opts + +go 1.21.4 @@ -0,0 +1,71 @@ +package opts + +type ArgMode int + +const ( + None ArgMode = iota + Required + Optional +) + +type Flag struct { + Key rune + Value string +} + +type LongOpt struct { + Short rune + Long string + Arg ArgMode +} + +func Get(args []string, optstr string) (flags []Flag, optind int, err error) { + argmap := make(map[rune]bool) + + rs := []rune(optstr) + for i, r := range rs { + if r != ':' { + argmap[r] = false + } else if i > 0 { + argmap[rs[i-1]] = true + } + } + + for i := 1; i < len(args); i++ { + arg := args[i] + if len(arg) == 0 || arg == "-" || arg[0] != '-' { + optind = i + return + } else if arg == "--" { + optind = i + 1 + return + } + + rs := []rune(arg[1:]) + outer: + for j, r := range rs { + argp, ok := argmap[r] + if !ok { + return nil, 0, ErrBadOption(r) + } + + switch { + case argp && j < len(rs)-1: + s := string(rs[j+1:]) + flags = append(flags, Flag{r, s}) + break outer + case argp: + i++ + if i >= len(args) { + return nil, 0, ErrNoArgument(r) + } + flags = append(flags, Flag{r, args[i]}) + break outer + } + flags = append(flags, Flag{Key: r}) + } + } + + optind = len(args) + return +} |