mirror of https://github.com/golang/go.git
flag: add TextVar function
The TextVar function makes it easier to integrate the flag package
with any Go type that implements encoding.Text{Marshaler,Unmarshaler}.
Fixes #45754
Change-Id: Id23c37d59cf8c9699a7943a22ce27a45eb685c0f
Reviewed-on: https://go-review.googlesource.com/c/go/+/313329
Trust: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Joseph Tsai <joetsai@digital-static.net>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
2d026a4ea5
commit
91daaabd56
|
|
@ -3,5 +3,7 @@ pkg encoding/binary, type AppendByteOrder interface, AppendUint16([]uint8, uint1
|
||||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
|
pkg encoding/binary, type AppendByteOrder interface, AppendUint32([]uint8, uint32) []uint8
|
||||||
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
|
pkg encoding/binary, type AppendByteOrder interface, AppendUint64([]uint8, uint64) []uint8
|
||||||
pkg encoding/binary, type AppendByteOrder interface, String() string
|
pkg encoding/binary, type AppendByteOrder interface, String() string
|
||||||
|
pkg flag, func TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string)
|
||||||
|
pkg flag, method (*FlagSet) TextVar(encoding.TextUnmarshaler, string, encoding.TextMarshaler, string)
|
||||||
pkg net/url, func JoinPath(string, ...string) (string, error)
|
pkg net/url, func JoinPath(string, ...string) (string, error)
|
||||||
pkg net/url, method (*URL) JoinPath(...string) *URL
|
pkg net/url, method (*URL) JoinPath(...string) *URL
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package flag_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleTextVar() {
|
||||||
|
fs := flag.NewFlagSet("ExampleTextVar", flag.ContinueOnError)
|
||||||
|
fs.SetOutput(os.Stdout)
|
||||||
|
var ip net.IP
|
||||||
|
fs.TextVar(&ip, "ip", net.IPv4(192, 168, 0, 100), "`IP address` to parse")
|
||||||
|
fs.Parse([]string{"-ip", "127.0.0.1"})
|
||||||
|
fmt.Printf("{ip: %v}\n\n", ip)
|
||||||
|
|
||||||
|
// 256 is not a valid IPv4 component
|
||||||
|
ip = nil
|
||||||
|
fs.Parse([]string{"-ip", "256.0.0.1"})
|
||||||
|
fmt.Printf("{ip: %v}\n\n", ip)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// {ip: 127.0.0.1}
|
||||||
|
//
|
||||||
|
// invalid value "256.0.0.1" for flag -ip: invalid IP address: 256.0.0.1
|
||||||
|
// Usage of ExampleTextVar:
|
||||||
|
// -ip IP address
|
||||||
|
// IP address to parse (default 192.168.0.100)
|
||||||
|
// {ip: <nil>}
|
||||||
|
}
|
||||||
|
|
@ -68,6 +68,7 @@
|
||||||
package flag
|
package flag
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -278,6 +279,43 @@ func (d *durationValue) Get() any { return time.Duration(*d) }
|
||||||
|
|
||||||
func (d *durationValue) String() string { return (*time.Duration)(d).String() }
|
func (d *durationValue) String() string { return (*time.Duration)(d).String() }
|
||||||
|
|
||||||
|
// -- encoding.TextUnmarshaler Value
|
||||||
|
type textValue struct{ p encoding.TextUnmarshaler }
|
||||||
|
|
||||||
|
func newTextValue(val encoding.TextMarshaler, p encoding.TextUnmarshaler) textValue {
|
||||||
|
ptrVal := reflect.ValueOf(p)
|
||||||
|
if ptrVal.Kind() != reflect.Ptr {
|
||||||
|
panic("variable value type must be a pointer")
|
||||||
|
}
|
||||||
|
defVal := reflect.ValueOf(val)
|
||||||
|
if defVal.Kind() == reflect.Ptr {
|
||||||
|
defVal = defVal.Elem()
|
||||||
|
}
|
||||||
|
if defVal.Type() != ptrVal.Type().Elem() {
|
||||||
|
panic(fmt.Sprintf("default type does not match variable type: %v != %v", defVal.Type(), ptrVal.Type().Elem()))
|
||||||
|
}
|
||||||
|
ptrVal.Elem().Set(defVal)
|
||||||
|
return textValue{p}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v textValue) Set(s string) error {
|
||||||
|
return v.p.UnmarshalText([]byte(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v textValue) Get() interface{} {
|
||||||
|
return v.p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v textValue) String() string {
|
||||||
|
if m, ok := v.p.(encoding.TextMarshaler); ok {
|
||||||
|
if b, err := m.MarshalText(); err == nil {
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- func Value
|
||||||
type funcValue func(string) error
|
type funcValue func(string) error
|
||||||
|
|
||||||
func (f funcValue) Set(s string) error { return f(s) }
|
func (f funcValue) Set(s string) error { return f(s) }
|
||||||
|
|
@ -838,6 +876,24 @@ func Duration(name string, value time.Duration, usage string) *time.Duration {
|
||||||
return CommandLine.Duration(name, value, usage)
|
return CommandLine.Duration(name, value, usage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextVar defines a flag with a specified name, default value, and usage string.
|
||||||
|
// The argument p must be a pointer to a variable that will hold the value
|
||||||
|
// of the flag, and p must implement encoding.TextUnmarshaler.
|
||||||
|
// If the flag is used, the flag value will be passed to p's UnmarshalText method.
|
||||||
|
// The type of the default value must be the same as the type of p.
|
||||||
|
func (f *FlagSet) TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
|
||||||
|
f.Var(newTextValue(value, p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TextVar defines a flag with a specified name, default value, and usage string.
|
||||||
|
// The argument p must be a pointer to a variable that will hold the value
|
||||||
|
// of the flag, and p must implement encoding.TextUnmarshaler.
|
||||||
|
// If the flag is used, the flag value will be passed to p's UnmarshalText method.
|
||||||
|
// The type of the default value must be the same as the type of p.
|
||||||
|
func TextVar(p encoding.TextUnmarshaler, name string, value encoding.TextMarshaler, usage string) {
|
||||||
|
CommandLine.Var(newTextValue(value, p), name, usage)
|
||||||
|
}
|
||||||
|
|
||||||
// Func defines a flag with the specified name and usage string.
|
// Func defines a flag with the specified name and usage string.
|
||||||
// Each time the flag is seen, fn is called with the value of the flag.
|
// Each time the flag is seen, fn is called with the value of the flag.
|
||||||
// If fn returns a non-nil error, it will be treated as a flag value parsing error.
|
// If fn returns a non-nil error, it will be treated as a flag value parsing error.
|
||||||
|
|
|
||||||
|
|
@ -212,8 +212,7 @@ var depsRules = `
|
||||||
|
|
||||||
# Misc packages needing only FMT.
|
# Misc packages needing only FMT.
|
||||||
FMT
|
FMT
|
||||||
< flag,
|
< html,
|
||||||
html,
|
|
||||||
mime/quotedprintable,
|
mime/quotedprintable,
|
||||||
net/internal/socktest,
|
net/internal/socktest,
|
||||||
net/url,
|
net/url,
|
||||||
|
|
@ -230,6 +229,8 @@ var depsRules = `
|
||||||
< encoding/binary
|
< encoding/binary
|
||||||
< encoding/base32, encoding/base64;
|
< encoding/base32, encoding/base64;
|
||||||
|
|
||||||
|
FMT, encoding < flag;
|
||||||
|
|
||||||
fmt !< encoding/base32, encoding/base64;
|
fmt !< encoding/base32, encoding/base64;
|
||||||
|
|
||||||
FMT, encoding/base32, encoding/base64
|
FMT, encoding/base32, encoding/base64
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue