在Cobra库中是否有内置工具(如果有,我如何使用它?)要求标志是几个值之一,如果标志不是允许的值之一,则抛出错误?我在Github页面上没有看到这一点。
um6iljoc1#
Cobra允许您通过pflag.(*FlagSet).Var()方法(来自Cobra使用的https://github.com/spf13/pflag包)定义自定义值类型用作标志。您必须创建一个实现pflag.Value接口的新类型:
pflag.(*FlagSet).Var()
pflag.Value
type Value interface { String() string Set(string) error Type() string}
type Value interface {
String() string
Set(string) error
Type() string
}
字符集示例类型定义:
type myEnum stringconst ( myEnumFoo myEnum = "foo" myEnumBar myEnum = "bar" myEnumMoo myEnum = "moo")// String is used both by fmt.Print and by Cobra in help textfunc (e *myEnum) String() string { return string(*e)}// Set must have pointer receiver so it doesn't change the value of a copyfunc (e *myEnum) Set(v string) error { switch v { case "foo", "bar", "moo": *e = myEnum(v) return nil default: return errors.New(`must be one of "foo", "bar", or "moo"`) }}// Type is only used in help textfunc (e *myEnum) Type() string { return "myEnum"}
type myEnum string
const (
myEnumFoo myEnum = "foo"
myEnumBar myEnum = "bar"
myEnumMoo myEnum = "moo"
)
// String is used both by fmt.Print and by Cobra in help text
func (e *myEnum) String() string {
return string(*e)
// Set must have pointer receiver so it doesn't change the value of a copy
func (e *myEnum) Set(v string) error {
switch v {
case "foo", "bar", "moo":
*e = myEnum(v)
return nil
default:
return errors.New(`must be one of "foo", "bar", or "moo"`)
// Type is only used in help text
func (e *myEnum) Type() string {
return "myEnum"
型注册示例:
func init() { var flagMyEnum = myEnumFoo var myCmd = &cobra.Command{ Use: "mycmd", Short: "A brief description of your command", Run: func(cmd *cobra.Command, args []string) { fmt.Println("myenum value:", flagMyEnum) }, } rootCmd.AddCommand(myCmd) myCmd.Flags().Var(&flagMyEnum, "myenum", `my custom enum. allowed: "foo", "bar", "moo"`)}
func init() {
var flagMyEnum = myEnumFoo
var myCmd = &cobra.Command{
Use: "mycmd",
Short: "A brief description of your command",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("myenum value:", flagMyEnum)
},
rootCmd.AddCommand(myCmd)
myCmd.Flags().Var(&flagMyEnum, "myenum", `my custom enum. allowed: "foo", "bar", "moo"`)
型示例用法:(注意下面控制台输出中的第一行)
$ go run . mycmd --myenum razError: invalid argument "raz" for "--myenum" flag: must be one of "foo", "bar", or "moo"Usage: main mycmd [flags]Flags: -h, --help help for mycmd --myenum myEnum my custom enum. allowed: "foo", "bar", "moo" (default foo)exit status 1
$ go run . mycmd --myenum raz
Error: invalid argument "raz" for "--myenum" flag: must be one of "foo", "bar", or "moo"
Usage:
main mycmd [flags]
Flags:
-h, --help help for mycmd
--myenum myEnum my custom enum. allowed: "foo", "bar", "moo" (default foo)
exit status 1
$ go run . mycmd --myenum barmyenum value: bar
$ go run . mycmd --myenum bar
myenum value: bar
要添加自动补全功能,可以使用隐藏的文档cobra/shell_completions. md #completions-for-flags。对于我们的示例,您可以添加如下内容:
func init() { // ... myCmd.Flags().Var(&flagMyEnum, "myenum", `my custom enum. allowed: "foo", "bar", "moo"`) myCmd.RegisterFlagCompletionFunc("myenum", myEnumCompletion)}// myEnumCompletion should probably live next to the myEnum definitionfunc myEnumCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{ "foo\thelp text for foo", "bar\thelp text for bar", "moo\thelp text for moo", }, cobra.ShellCompDirectiveDefault}
// ...
myCmd.RegisterFlagCompletionFunc("myenum", myEnumCompletion)
// myEnumCompletion should probably live next to the myEnum definition
func myEnumCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{
"foo\thelp text for foo",
"bar\thelp text for bar",
"moo\thelp text for moo",
}, cobra.ShellCompDirectiveDefault
型示例用法:
$ go build -o main .$ source <(main completion bash)$ main mycmd --myenum <TAB><TAB>bar (help text for bar)foo (help text for foo)moo (help text for moo)
$ go build -o main .
$ source <(main completion bash)
$ main mycmd --myenum <TAB><TAB>
bar (help text for bar)
foo (help text for foo)
moo (help text for moo)
型
cotxawn72#
它看起来像一个enumflag包作为一个附加组件发布,以满足此用例:https://pkg.go.dev/github.com/thediveo/enumflag
enumflag
package mainimport ( "fmt" "github.com/spf13/cobra" "github.com/thediveo/enumflag")// ① Define your new enum flag type. It can be derived from enumflag.Flag, but// it doesn't need to be as long as it is compatible with enumflag.Flag, so// either an int or uint.type FooMode enumflag.Flag// ② Define the enumeration values for FooMode.const ( Foo FooMode = iota Bar)// ③ Map enumeration values to their textual representations (value// identifiers).var FooModeIds = map[FooMode][]string{ Foo: {"foo"}, Bar: {"bar"},}// User-defined enum flag types should be derived from "enumflag.Flag"; however// this is not strictly necessary as long as they can be converted into the// "enumflag.Flag" type. Actually, "enumflag.Flag" is just a fancy name for an// "uint". In order to use such user-defined enum flags, simply wrap them using// enumflag.New.func main() { // ④ Define your enum flag value. var foomode FooMode rootCmd := &cobra.Command{ Run: func(cmd *cobra.Command, _ []string) { fmt.Printf("mode is: %d=%q\n", foomode, cmd.PersistentFlags().Lookup("mode").Value.String()) }, } // ⑤ Define the CLI flag parameters for your wrapped enum flag. rootCmd.PersistentFlags().VarP( enumflag.New(&foomode, "mode", FooModeIds, enumflag.EnumCaseInsensitive), "mode", "m", "foos the output; can be 'foo' or 'bar'") rootCmd.SetArgs([]string{"--mode", "bAr"}) _ = rootCmd.Execute()}
package main
import (
"fmt"
"github.com/spf13/cobra"
"github.com/thediveo/enumflag"
// ① Define your new enum flag type. It can be derived from enumflag.Flag, but
// it doesn't need to be as long as it is compatible with enumflag.Flag, so
// either an int or uint.
type FooMode enumflag.Flag
// ② Define the enumeration values for FooMode.
Foo FooMode = iota
Bar
// ③ Map enumeration values to their textual representations (value
// identifiers).
var FooModeIds = map[FooMode][]string{
Foo: {"foo"},
Bar: {"bar"},
// User-defined enum flag types should be derived from "enumflag.Flag"; however
// this is not strictly necessary as long as they can be converted into the
// "enumflag.Flag" type. Actually, "enumflag.Flag" is just a fancy name for an
// "uint". In order to use such user-defined enum flags, simply wrap them using
// enumflag.New.
func main() {
// ④ Define your enum flag value.
var foomode FooMode
rootCmd := &cobra.Command{
Run: func(cmd *cobra.Command, _ []string) {
fmt.Printf("mode is: %d=%q\n",
foomode,
cmd.PersistentFlags().Lookup("mode").Value.String())
// ⑤ Define the CLI flag parameters for your wrapped enum flag.
rootCmd.PersistentFlags().VarP(
enumflag.New(&foomode, "mode", FooModeIds, enumflag.EnumCaseInsensitive),
"mode", "m",
"foos the output; can be 'foo' or 'bar'")
rootCmd.SetArgs([]string{"--mode", "bAr"})
_ = rootCmd.Execute()
字符集注意:它似乎不包括完成逻辑。
qvk1mo1f3#
虽然很难证明一个否定的,它不看这是目前的一个功能。
3条答案
按热度按时间um6iljoc1#
Cobra允许您通过
pflag.(*FlagSet).Var()
方法(来自Cobra使用的https://github.com/spf13/pflag包)定义自定义值类型用作标志。您必须创建一个实现pflag.Value
接口的新类型:字符集
示例类型定义:
型
注册示例:
型
示例用法:(注意下面控制台输出中的第一行)
完成
要添加自动补全功能,可以使用隐藏的文档cobra/shell_completions. md #completions-for-flags。对于我们的示例,您可以添加如下内容:
型
示例用法:
型
cotxawn72#
它看起来像一个
enumflag
包作为一个附加组件发布,以满足此用例:https://pkg.go.dev/github.com/thediveo/enumflag字符集
注意:它似乎不包括完成逻辑。
qvk1mo1f3#
虽然很难证明一个否定的,它不看这是目前的一个功能。