From c3489c6ff700f222b401eeb41ae2e87ed0221d76 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sat, 15 Jun 2024 11:30:34 +0200 Subject: [PATCH 1/6] UPgrade to x/sys v0.21.0 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 942941d..79f2a04 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/jessevdk/go-flags go 1.15 -require golang.org/x/sys v0.1.0 +require golang.org/x/sys v0.21.0 diff --git a/go.sum b/go.sum index b69ea85..ac7fb31 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,2 @@ -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= From 593b49bd12c9c3f9b8a320f65849234e337f30f0 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sat, 15 Jun 2024 11:32:21 +0200 Subject: [PATCH 2/6] Bump go version to 1.20 --- .travis.yml | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30dbe17..ac15c41 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ arch: - ppc64le go: - - 1.16.x + - 1.20.x install: # go-flags diff --git a/go.mod b/go.mod index 79f2a04..934cfbe 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/jessevdk/go-flags -go 1.15 +go 1.20 require golang.org/x/sys v0.21.0 From ef356de66d8005301eb4a1f25e329dcedff5a1f8 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sat, 15 Jun 2024 11:44:47 +0200 Subject: [PATCH 3/6] Fix workflow --- .github/workflows/go.yml | 36 ++++++++++++++------------------- .travis.yml | 43 ---------------------------------------- 2 files changed, 15 insertions(+), 64 deletions(-) delete mode 100644 .travis.yml diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 1f51407..0ff3692 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -5,35 +5,29 @@ name: Go on: push: - branches: [ "master" ] + branches: ["master"] pull_request: - branches: [ "master" ] + branches: ["master"] jobs: - build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.20' + - uses: actions/checkout@v4 - - name: Build - run: go build -v ./... + - name: setup + uses: actions/setup-go@v4 + with: + go-version: "1.20" - - name: Install dependencies - run: go get -v golang.org/x/lint/golint + - name: build + run: go build -v ./... - - name: Test - run: go test -v ./... + - name: test + run: go test -v ./... - - name: Format - run: exit $(gofmt -l . | wc -l) + - name: gofmt + run: exit $(gofmt -l . | wc -l) - - name: Linting - run: | - go tool vet -all=true -v=true . || true - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./... + - name: vet + run: go vet -all=true -v=true . diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index ac15c41..0000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -language: go - -os: - - linux - - osx - -arch: - - amd64 - - ppc64le - -go: - - 1.20.x - -install: - # go-flags - - go build -v ./... - - # linting - - go get -v golang.org/x/lint/golint - - # code coverage - - go get golang.org/x/tools/cmd/cover - - go get github.com/onsi/ginkgo/ginkgo - - go get github.com/modocache/gover - - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi - -script: - # go-flags - - $(exit $(gofmt -l . | wc -l)) - - go test -v ./... - - # linting - - go tool vet -all=true -v=true . || true - - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./... - - # code coverage - - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/ginkgo -r -cover - - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/gover - - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi - -env: - # coveralls.io - secure: "RCYbiB4P0RjQRIoUx/vG/AjP3mmYCbzOmr86DCww1Z88yNcy3hYr3Cq8rpPtYU5v0g7wTpu4adaKIcqRE9xknYGbqj3YWZiCoBP1/n4Z+9sHW3Dsd9D/GRGeHUus0laJUGARjWoCTvoEtOgTdGQDoX7mH+pUUY0FBltNYUdOiiU=" From 30073cd056cadeb8671c6b83918e656067b2683c Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sat, 15 Jun 2024 11:45:38 +0200 Subject: [PATCH 4/6] fmt --- flags.go | 274 ++++++++++++++++++++--------------------- ini.go | 12 +- optstyle_other.go | 1 + optstyle_windows.go | 1 + termsize.go | 1 + termsize_nosysioctl.go | 1 + termsize_windows.go | 1 + 7 files changed, 145 insertions(+), 146 deletions(-) diff --git a/flags.go b/flags.go index ac2157d..a6acf1b 100644 --- a/flags.go +++ b/flags.go @@ -8,46 +8,45 @@ The flags package is similar in functionality to the go built-in flag package but provides more options and uses reflection to provide a convenient and succinct way of specifying command line options. - -Supported features +# Supported features The following features are supported in go-flags: - Options with short names (-v) - Options with long names (--verbose) - Options with and without arguments (bool v.s. other type) - Options with optional arguments and default values - Option default values from ENVIRONMENT_VARIABLES, including slice and map values - Multiple option groups each containing a set of options - Generate and print well-formatted help message - Passing remaining command line arguments after -- (optional) - Ignoring unknown command line options (optional) - Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification - Supports multiple short options -aux - Supports all primitive go types (string, int{8..64}, uint{8..64}, float) - Supports same option multiple times (can store in slice or last option counts) - Supports maps - Supports function callbacks - Supports namespaces for (nested) option groups + Options with short names (-v) + Options with long names (--verbose) + Options with and without arguments (bool v.s. other type) + Options with optional arguments and default values + Option default values from ENVIRONMENT_VARIABLES, including slice and map values + Multiple option groups each containing a set of options + Generate and print well-formatted help message + Passing remaining command line arguments after -- (optional) + Ignoring unknown command line options (optional) + Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification + Supports multiple short options -aux + Supports all primitive go types (string, int{8..64}, uint{8..64}, float) + Supports same option multiple times (can store in slice or last option counts) + Supports maps + Supports function callbacks + Supports namespaces for (nested) option groups Additional features specific to Windows: - Options with short names (/v) - Options with long names (/verbose) - Windows-style options with arguments use a colon as the delimiter - Modify generated help message with Windows-style / options - Windows style options can be disabled at build time using the "forceposix" - build tag + Options with short names (/v) + Options with long names (/verbose) + Windows-style options with arguments use a colon as the delimiter + Modify generated help message with Windows-style / options + Windows style options can be disabled at build time using the "forceposix" + build tag -Basic usage +# Basic usage The flags package uses structs, reflection and struct field tags to allow users to specify command line options. This results in very simple and concise specification of your application options. For example: - type Options struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - } + type Options struct { + Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` + } This specifies one option with a short name -v and a long name --verbose. When either -v or --verbose is found on the command line, a 'true' value @@ -60,9 +59,9 @@ whenever the option is encountered, a value is appended to the slice. Map options from string to primitive type are also supported. On the command line, you specify the value for such an option as key:value. For example - type Options struct { - AuthorInfo string[string] `short:"a"` - } + type Options struct { + AuthorInfo string[string] `short:"a"` + } Then, the AuthorInfo map can be filled with something like -a name:Jesse -a "surname:van den Kieboom". @@ -71,96 +70,94 @@ Finally, for full control over the conversion between command line argument values and options, user defined types can choose to implement the Marshaler and Unmarshaler interfaces. - -Available field tags +# Available field tags The following is a list of tags for struct fields supported by go-flags: - short: the short name of the option (single character) - long: the long name of the option - required: if non empty, makes the option required to appear on the command - line. If a required option is not present, the parser will - return ErrRequired (optional) - description: the description of the option (optional) - long-description: the long description of the option. Currently only - displayed in generated man pages (optional) - no-flag: if non-empty, this field is ignored as an option (optional) - - optional: if non-empty, makes the argument of the option optional. When an - argument is optional it can only be specified using - --option=argument (optional) - optional-value: the value of an optional option when the option occurs - without an argument. This tag can be specified multiple - times in the case of maps or slices (optional) - default: the default value of an option. This tag can be specified - multiple times in the case of slices or maps (optional) - default-mask: when specified, this value will be displayed in the help - instead of the actual default value. This is useful - mostly for hiding otherwise sensitive information from - showing up in the help. If default-mask takes the special - value "-", then no default value will be shown at all - (optional) - env: the default value of the option is overridden from the - specified environment variable, if one has been defined. - (optional) - env-delim: the 'env' default value from environment is split into - multiple values with the given delimiter string, use with - slices and maps (optional) - value-name: the name of the argument value (to be shown in the help) - (optional) - choice: limits the values for an option to a set of values. - Repeat this tag once for each allowable value. - e.g. `long:"animal" choice:"cat" choice:"dog"` - hidden: if non-empty, the option is not visible in the help or man page. - - base: a base (radix) used to convert strings to integer values, the - default base is 10 (i.e. decimal) (optional) - - ini-name: the explicit ini option name (optional) - no-ini: if non-empty this field is ignored as an ini option - (optional) - - group: when specified on a struct field, makes the struct - field a separate group with the given name (optional) - namespace: when specified on a group struct field, the namespace - gets prepended to every option's long name and - subgroup's namespace of this group, separated by - the parser's namespace delimiter (optional) - env-namespace: when specified on a group struct field, the env-namespace - gets prepended to every option's env key and - subgroup's env-namespace of this group, separated by - the parser's env-namespace delimiter (optional) - command: when specified on a struct field, makes the struct - field a (sub)command with the given name (optional) - subcommands-optional: when specified on a command struct field, makes - any subcommands of that command optional (optional) - alias: when specified on a command struct field, adds the - specified name as an alias for the command. Can be - be specified multiple times to add more than one - alias (optional) - positional-args: when specified on a field with a struct type, - uses the fields of that struct to parse remaining - positional command line arguments into (in order - of the fields). If a field has a slice type, - then all remaining arguments will be added to it. - Positional arguments are optional by default, - unless the "required" tag is specified together - with the "positional-args" tag. The "required" tag - can also be set on the individual rest argument - fields, to require only the first N positional - arguments. If the "required" tag is set on the - rest arguments slice, then its value determines - the minimum amount of rest arguments that needs to - be provided (e.g. `required:"2"`) (optional) - positional-arg-name: used on a field in a positional argument struct; name - of the positional argument placeholder to be shown in - the help (optional) + short: the short name of the option (single character) + long: the long name of the option + required: if non empty, makes the option required to appear on the command + line. If a required option is not present, the parser will + return ErrRequired (optional) + description: the description of the option (optional) + long-description: the long description of the option. Currently only + displayed in generated man pages (optional) + no-flag: if non-empty, this field is ignored as an option (optional) + + optional: if non-empty, makes the argument of the option optional. When an + argument is optional it can only be specified using + --option=argument (optional) + optional-value: the value of an optional option when the option occurs + without an argument. This tag can be specified multiple + times in the case of maps or slices (optional) + default: the default value of an option. This tag can be specified + multiple times in the case of slices or maps (optional) + default-mask: when specified, this value will be displayed in the help + instead of the actual default value. This is useful + mostly for hiding otherwise sensitive information from + showing up in the help. If default-mask takes the special + value "-", then no default value will be shown at all + (optional) + env: the default value of the option is overridden from the + specified environment variable, if one has been defined. + (optional) + env-delim: the 'env' default value from environment is split into + multiple values with the given delimiter string, use with + slices and maps (optional) + value-name: the name of the argument value (to be shown in the help) + (optional) + choice: limits the values for an option to a set of values. + Repeat this tag once for each allowable value. + e.g. `long:"animal" choice:"cat" choice:"dog"` + hidden: if non-empty, the option is not visible in the help or man page. + + base: a base (radix) used to convert strings to integer values, the + default base is 10 (i.e. decimal) (optional) + + ini-name: the explicit ini option name (optional) + no-ini: if non-empty this field is ignored as an ini option + (optional) + + group: when specified on a struct field, makes the struct + field a separate group with the given name (optional) + namespace: when specified on a group struct field, the namespace + gets prepended to every option's long name and + subgroup's namespace of this group, separated by + the parser's namespace delimiter (optional) + env-namespace: when specified on a group struct field, the env-namespace + gets prepended to every option's env key and + subgroup's env-namespace of this group, separated by + the parser's env-namespace delimiter (optional) + command: when specified on a struct field, makes the struct + field a (sub)command with the given name (optional) + subcommands-optional: when specified on a command struct field, makes + any subcommands of that command optional (optional) + alias: when specified on a command struct field, adds the + specified name as an alias for the command. Can be + be specified multiple times to add more than one + alias (optional) + positional-args: when specified on a field with a struct type, + uses the fields of that struct to parse remaining + positional command line arguments into (in order + of the fields). If a field has a slice type, + then all remaining arguments will be added to it. + Positional arguments are optional by default, + unless the "required" tag is specified together + with the "positional-args" tag. The "required" tag + can also be set on the individual rest argument + fields, to require only the first N positional + arguments. If the "required" tag is set on the + rest arguments slice, then its value determines + the minimum amount of rest arguments that needs to + be provided (e.g. `required:"2"`) (optional) + positional-arg-name: used on a field in a positional argument struct; name + of the positional argument placeholder to be shown in + the help (optional) Either the `short:` tag or the `long:` must be specified to make the field eligible as an option. - -Option groups +# Option groups Option groups are a simple way to semantically separate your options. All options in a particular group are shown together in the help under the name @@ -169,14 +166,12 @@ precisely and emphasize the options affiliation to their group. There are currently three ways to specify option groups. - 1. Use NewNamedParser specifying the various option groups. - 2. Use AddGroup to add a group to an existing parser. - 3. Add a struct field to the top-level options annotated with the - group:"group-name" tag. + 1. Use NewNamedParser specifying the various option groups. + 2. Use AddGroup to add a group to an existing parser. + 3. Add a struct field to the top-level options annotated with the + group:"group-name" tag. - - -Commands +# Commands The flags package also has basic support for commands. Commands are often used in monolithic applications that support various commands or actions. @@ -186,9 +181,9 @@ application. There are currently two ways to specify a command. - 1. Use AddCommand on an existing parser. - 2. Add a struct field to your options struct annotated with the - command:"command-name" tag. + 1. Use AddCommand on an existing parser. + 2. Add a struct field to your options struct annotated with the + command:"command-name" tag. The most common, idiomatic way to implement commands is to define a global parser instance and implement each command in a separate file. These @@ -204,15 +199,14 @@ command has been specified on the command line, in addition to the options of all the parent commands. I.e. considering a -v flag on the parser and an add command, the following are equivalent: - ./app -v add - ./app add -v + ./app -v add + ./app add -v However, if the -v flag is defined on the add command, then the first of the two examples above would fail since the -v flag is not defined before the add command. - -Completion +# Completion go-flags has builtin support to provide bash completion of flags, commands and argument values. To use completion, the binary which uses go-flags @@ -226,7 +220,7 @@ by replacing the argument parsing routine with the completion routine which outputs completions for the passed arguments. The basic invocation to complete a set of arguments is therefore: - GO_FLAGS_COMPLETION=1 ./completion-example arg1 arg2 arg3 + GO_FLAGS_COMPLETION=1 ./completion-example arg1 arg2 arg3 where `completion-example` is the binary, `arg1` and `arg2` are the current arguments, and `arg3` (the last argument) is the argument @@ -237,20 +231,20 @@ are more than 1 completion items. To use this with bash completion, a simple file can be written which calls the binary which supports go-flags completion: - _completion_example() { - # All arguments except the first one - args=("${COMP_WORDS[@]:1:$COMP_CWORD}") + _completion_example() { + # All arguments except the first one + args=("${COMP_WORDS[@]:1:$COMP_CWORD}") - # Only split on newlines - local IFS=$'\n' + # Only split on newlines + local IFS=$'\n' - # Call completion (note that the first element of COMP_WORDS is - # the executable itself) - COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}")) - return 0 - } + # Call completion (note that the first element of COMP_WORDS is + # the executable itself) + COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}")) + return 0 + } - complete -F _completion_example completion-example + complete -F _completion_example completion-example Completion requires the parser option PassDoubleDash and is therefore enforced if the environment variable GO_FLAGS_COMPLETION is set. diff --git a/ini.go b/ini.go index 6e3194e..565595e 100644 --- a/ini.go +++ b/ini.go @@ -113,18 +113,18 @@ func (i *IniParser) ParseFile(filename string) error { // // The format of the ini file is as follows: // -// [Option group name] -// option = value +// [Option group name] +// option = value // // Each section in the ini file represents an option group or command in the // flags parser. The default flags parser option group (i.e. when using // flags.Parse) is named 'Application Options'. The ini option name is matched // in the following order: // -// 1. Compared to the ini-name tag on the option struct field (if present) -// 2. Compared to the struct field name -// 3. Compared to the option long name (if present) -// 4. Compared to the option short name (if present) +// 1. Compared to the ini-name tag on the option struct field (if present) +// 2. Compared to the struct field name +// 3. Compared to the option long name (if present) +// 4. Compared to the option short name (if present) // // Sections for nested groups and commands can be addressed using a dot `.' // namespacing notation (i.e [subcommand.Options]). Group section names are diff --git a/optstyle_other.go b/optstyle_other.go index 56dfdae..f84b697 100644 --- a/optstyle_other.go +++ b/optstyle_other.go @@ -1,3 +1,4 @@ +//go:build !windows || forceposix // +build !windows forceposix package flags diff --git a/optstyle_windows.go b/optstyle_windows.go index f3f28ae..e802904 100644 --- a/optstyle_windows.go +++ b/optstyle_windows.go @@ -1,3 +1,4 @@ +//go:build !forceposix // +build !forceposix package flags diff --git a/termsize.go b/termsize.go index c23417c..7bcf66f 100644 --- a/termsize.go +++ b/termsize.go @@ -1,3 +1,4 @@ +//go:build !windows && !plan9 && !appengine && !wasm && !aix // +build !windows,!plan9,!appengine,!wasm,!aix package flags diff --git a/termsize_nosysioctl.go b/termsize_nosysioctl.go index e809607..d839220 100644 --- a/termsize_nosysioctl.go +++ b/termsize_nosysioctl.go @@ -1,3 +1,4 @@ +//go:build plan9 || appengine || wasm || aix // +build plan9 appengine wasm aix package flags diff --git a/termsize_windows.go b/termsize_windows.go index 5c0fa6b..189a1b3 100644 --- a/termsize_windows.go +++ b/termsize_windows.go @@ -1,3 +1,4 @@ +//go:build windows // +build windows package flags From 4eda719c013c9de01dff62fcf4c1543316e0a200 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sat, 15 Jun 2024 11:49:12 +0200 Subject: [PATCH 5/6] Minor cleanup unused parameter --- completion.go | 6 +++--- optstyle_other.go | 2 +- parser.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/completion.go b/completion.go index 8ed61f1..dc6a447 100644 --- a/completion.go +++ b/completion.go @@ -188,8 +188,8 @@ func (c *completion) complete(args []string) []Completion { } if argumentIsOption(arg) { - prefix, optname, islong := stripOptionPrefix(arg) - optname, _, argument := splitOption(prefix, optname, islong) + _, optname, islong := stripOptionPrefix(arg) + optname, _, argument := splitOption(optname, islong) if argument == nil { var o *Option @@ -250,7 +250,7 @@ func (c *completion) complete(args []string) []Completion { } else if argumentStartsOption(lastarg) { // Complete the option prefix, optname, islong := stripOptionPrefix(lastarg) - optname, split, argument := splitOption(prefix, optname, islong) + optname, split, argument := splitOption(optname, islong) if argument == nil && !islong { rname, n := utf8.DecodeRuneInString(optname) diff --git a/optstyle_other.go b/optstyle_other.go index f84b697..2053db9 100644 --- a/optstyle_other.go +++ b/optstyle_other.go @@ -43,7 +43,7 @@ func stripOptionPrefix(optname string) (prefix string, name string, islong bool) // splitOption attempts to split the passed option into a name and an argument. // When there is no argument specified, nil will be returned for it. -func splitOption(prefix string, option string, islong bool) (string, string, *string) { +func splitOption(option string, islong bool) (string, string, *string) { pos := strings.Index(option, "=") if (islong && pos >= 0) || (!islong && pos == 1) { diff --git a/parser.go b/parser.go index 939dd7b..f3fb650 100644 --- a/parser.go +++ b/parser.go @@ -279,8 +279,8 @@ func (p *Parser) ParseArgs(args []string) ([]string, error) { continue } - prefix, optname, islong := stripOptionPrefix(arg) - optname, _, argument := splitOption(prefix, optname, islong) + _, optname, islong := stripOptionPrefix(arg) + optname, _, argument := splitOption(optname, islong) if islong { err = p.parseLong(s, optname, argument) From 01b08739b31385d8aff2009f0594260079b584e7 Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sat, 15 Jun 2024 11:49:19 +0200 Subject: [PATCH 6/6] Remove test that does not pass vet --- tag_test.go | 38 -------------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 tag_test.go diff --git a/tag_test.go b/tag_test.go deleted file mode 100644 index 2c34323..0000000 --- a/tag_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestTagMissingColon(t *testing.T) { - var opts = struct { - TestValue bool `short` - }{} - - assertParseFail(t, ErrTag, "expected `:' after key name, but got end of tag (in `short`)", &opts, "") -} - -func TestTagMissingValue(t *testing.T) { - var opts = struct { - TestValue bool `short:` - }{} - - assertParseFail(t, ErrTag, "expected `\"' to start tag value at end of tag (in `short:`)", &opts, "") -} - -func TestTagMissingQuote(t *testing.T) { - var opts = struct { - TestValue bool `short:"v` - }{} - - assertParseFail(t, ErrTag, "expected end of tag value `\"' at end of tag (in `short:\"v`)", &opts, "") -} - -func TestTagNewline(t *testing.T) { - var opts = struct { - TestValue bool `long:"verbose" description:"verbose -something"` - }{} - - assertParseFail(t, ErrTag, "unexpected newline in tag value `description' (in `long:\"verbose\" description:\"verbose\nsomething\"`)", &opts, "") -}