getopt: init module
This commit is contained in:
parent
8290a04536
commit
2729e58eab
17 changed files with 1076 additions and 3 deletions
155
getopt/getopt.go
Normal file
155
getopt/getopt.go
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
// getopt is a POSIX-compatible implementation of getopt(3) for Go.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// import (
|
||||
// "os"
|
||||
// "git.sr.ht/~sircmpwn/getopt"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// opts, optind, err := getopt.Getopts(os.Args, "abc:d:")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// for _, opt := range opts {
|
||||
// switch opt.Option {
|
||||
// case 'a':
|
||||
// println("Option -a specified")
|
||||
// case 'b':
|
||||
// println("Option -b specified")
|
||||
// case 'c':
|
||||
// println("Option -c specified: " + opt.Value)
|
||||
// case 'd':
|
||||
// println("Option -d specified: " + opt.Value)
|
||||
// }
|
||||
// }
|
||||
// println("Remaining arguments:")
|
||||
// for _, arg := range os.Args[optind:] {
|
||||
// println(arg)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// A flag[0]-like interface is also supported.
|
||||
//
|
||||
// import (
|
||||
// "git.sr.ht/~sircmpwn/getopt"
|
||||
// )
|
||||
//
|
||||
// func main() {
|
||||
// a := getopt.Bool("a", false, "turn on option a")
|
||||
// b := getopt.Int("b", 1, "set b to a numerical value")
|
||||
// var opt string
|
||||
// getopt.StringVar(&opt, "c", "", "let c be specified string")
|
||||
//
|
||||
// err := getopt.Parse()
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
//
|
||||
// print("Value of a: ")
|
||||
// println(*a)
|
||||
// print("Value of b: ")
|
||||
// println(*b)
|
||||
// println("Value of c: " + opt)
|
||||
//
|
||||
// println("Remaining arguments:")
|
||||
// for _, arg := range getopt.Args() {
|
||||
// println(arg)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// [0]: https://golang.org/pkg/flag/
|
||||
package getopt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// In the case of "-o example", Option is 'o' and "example" is Value. For
|
||||
// options which do not take an argument, Value is "".
|
||||
type Option struct {
|
||||
Option rune
|
||||
Value string
|
||||
}
|
||||
|
||||
// This is returned when an unknown option is found in argv, but not in the
|
||||
// option spec.
|
||||
type UnknownOptionError rune
|
||||
|
||||
func (e UnknownOptionError) Error() string {
|
||||
return fmt.Sprintf("%s: unknown option -%c", os.Args[0], rune(e))
|
||||
}
|
||||
|
||||
// This is returned when an option with a mandatory argument is missing that
|
||||
// argument.
|
||||
type MissingOptionError rune
|
||||
|
||||
func (e MissingOptionError) Error() string {
|
||||
return fmt.Sprintf("%s: expected argument for -%c", os.Args[0], rune(e))
|
||||
}
|
||||
|
||||
// Getopts implements a POSIX-compatible options interface.
|
||||
//
|
||||
// Returns a slice of options and the index of the first non-option argument.
|
||||
//
|
||||
// If an error is returned, you must print it to stderr to be POSIX complaint.
|
||||
func Getopts(argv []string, spec string) ([]Option, int, error) {
|
||||
optmap := make(map[rune]bool)
|
||||
runes := []rune(spec)
|
||||
for i, rn := range spec {
|
||||
if rn == ':' {
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
optmap[runes[i-1]] = true
|
||||
} else {
|
||||
optmap[rn] = false
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
i int
|
||||
opts []Option
|
||||
)
|
||||
for i = 1; i < len(argv); i++ {
|
||||
arg := argv[i]
|
||||
runes = []rune(arg)
|
||||
if len(arg) == 0 || arg == "-" {
|
||||
break
|
||||
}
|
||||
if arg[0] != '-' {
|
||||
break
|
||||
}
|
||||
if arg == "--" {
|
||||
i++
|
||||
break
|
||||
}
|
||||
for j, opt := range runes[1:] {
|
||||
if optopt, ok := optmap[opt]; !ok {
|
||||
opts = append(opts, Option{'?', ""})
|
||||
return opts, i, UnknownOptionError(opt)
|
||||
} else if optopt {
|
||||
if j+1 < len(runes)-1 {
|
||||
opts = append(opts, Option{opt, string(runes[j+2:])})
|
||||
break
|
||||
} else {
|
||||
if i+1 >= len(argv) {
|
||||
if len(spec) >= 1 && spec[0] == ':' {
|
||||
opts = append(opts, Option{':', string(opt)})
|
||||
} else {
|
||||
return opts, i, MissingOptionError(opt)
|
||||
}
|
||||
} else {
|
||||
opts = append(opts, Option{opt, argv[i+1]})
|
||||
i++
|
||||
}
|
||||
}
|
||||
} else {
|
||||
opts = append(opts, Option{opt, ""})
|
||||
}
|
||||
}
|
||||
}
|
||||
return opts, i, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue