flagx

package module
v0.0.0-...-c72608f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 5, 2022 License: Apache-2.0 Imports: 7 Imported by: 2

README

flagx - Helpers for the 'flag' package

GoDoc Travis-CI Go Report Card

Documentation

Latest (master): https://pkg.go.dev/github.com/dolmen-go/flagx

Your local copy: http://localhost:6060/pkg/github.com/dolmen-go/flagx

Status

Production ready. Parts are already used in production code.

The aim is code coverage of 100%. Check testsuite coverage and consider any code not covered by the testsuite as never tested and full of bugs.

See Also

License

Copyright 2017-2018 Olivier Mengué

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Documentation

Overview

Package flagx provides helpers/extensions for the 'flag' package of the stdlib.

Use those helpers with flag.Var() / flag.FlagSet.Var(). See https://golang.org/pkg/flag/#Var

Any type/function without documentation is considered work in progress and that part of the API may break. (But note that contributing high quality documentation and increasing code coverage by tests (including runnable examples) is a good way to fix that)

Example
package main

import (
	"encoding/hex"
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

type hexString []byte

func (h hexString) MarshalText() (text []byte, err error) {
	hx := make([]byte, hex.EncodedLen(len(h)))
	_ = hex.Encode(hx, h)
	return hx, nil
}

func (h *hexString) UnmarshalText(text []byte) error {
	tmp := make(hexString, hex.DecodedLen(len(text)))
	_, err := hex.Decode(tmp, text)
	if err != nil {
		return err
	}
	*h = tmp
	return nil
}

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var hx hexString
	flags.Var(flagx.Text(&hx), "hex", "hex string")

	flags.Parse([]string{"-hex", "1234"})

	fmt.Printf("%d\n", hx)

}
Output:

[18 52]

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BoolFunc

type BoolFunc func(b bool) error

BoolFunc wraps a function as a boolean flag.Value.

Example
package main

import (
	"flag"
	"fmt"
	"math/rand"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var n int

	// A flag that set the value of n
	flags.IntVar(&n, "value", 0, "set given value")
	// A flag that set n to a random value
	flags.Var(
		flagx.BoolFunc(
			func(b bool) error {
				n = rand.Int()
				return nil
			},
		),
		"rand", "set random value",
	)

	flags.Parse([]string{"-rand", "-value=5"})

	fmt.Println(n)

}
Output:

5

func (BoolFunc) Get

func (BoolFunc) Get() interface{}

func (BoolFunc) IsBoolFlag

func (BoolFunc) IsBoolFlag() bool

func (BoolFunc) Set

func (f BoolFunc) Set(s string) error

func (BoolFunc) String

func (BoolFunc) String() string

type Dummy

type Dummy struct{}

Dummy is a flag.Value that does nothing.

func (Dummy) Get

func (Dummy) Get() interface{}

func (Dummy) Set

func (Dummy) Set(s string) error

func (Dummy) String

func (Dummy) String() string

type Encoding

type Encoding interface {
	DecodeString(string) ([]byte, error)
	EncodeToString(src []byte) string
}

Encoding is an interface implemented by stdlib encoding/base32.Encoding and encoding/base64.Encoding.

type Func

type Func func(s string) error

Func wraps a function like flag.Value.Set as a flag.Value.

Example
package main

import (
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var all []string

	push := func(s string) error {
		all = append(all, s)
		return nil
	}

	// A flag that apppends the given value to slice all
	flags.Var(
		flagx.Func(push),
		"push", "push `value`",
	)

	flags.Parse([]string{"-push=a", "-push=b"})

	fmt.Println(all)

}
Output:

[a b]
Example (Hex)

Shows an hex encoded parameter

package main

import (
	"encoding/hex"
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	// Destination of the decoded parameter value
	var bin []byte

	// A flag that decodes value from hexadecimal
	flags.Var(
		flagx.Func(func(s string) (err error) {
			bin, err = hex.DecodeString(s)
			return
		}),
		"hex", "hex encoded `value`",
	)

	flags.Parse([]string{"-hex=68656c6c6f"})

	fmt.Printf("%q", bin)

}
Output:

"hello"

func (Func) Get

func (Func) Get() interface{}

func (Func) Set

func (f Func) Set(s string) error

func (Func) String

func (Func) String() string

type IntSlice

type IntSlice struct {
	Slice *[]int
}

func (IntSlice) Get

func (is IntSlice) Get() interface{}

func (IntSlice) Set

func (is IntSlice) Set(s string) (err error)

func (IntSlice) String

func (is IntSlice) String() string

type Time

type Time struct {
	Time     *time.Time
	Format   string // See time.ParseTime
	Location *time.Location
}

Time allows to define a flag that feeds a time.Time value.

Example
package main

import (
	"flag"
	"fmt"
	"time"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var t time.Time

	flags.Var(flagx.Time{
		Time:     &t,
		Format:   time.RFC3339,
		Location: time.UTC,
	}, "time", "time value")

	flags.Parse([]string{"-time=2006-01-02T15:04:05Z"})

	fmt.Println(t)

}
Output:

2006-01-02 15:04:05 +0000 UTC

func (Time) Get

func (t Time) Get() interface{}

func (Time) Set

func (t Time) Set(s string) (err error)

func (Time) String

func (t Time) String() string

type Value

type Value interface {
	String() string
	Set(string) error
	Get() interface{}
}

Value is like flag.Getter (which is a superset of flag.Value).

func Encoded

func Encoded(value *[]byte, encoding Encoding) Value

Encoded wraps a reference to a []byte as a flag.Value.

Example (Base64)
package main

import (
	"encoding/base64"
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var bin []byte
	// Bind parameter "-base64" to value bin above, with Base64 decoding
	flags.Var(flagx.Encoded(&bin, base64.RawStdEncoding), "base64", "hex string")

	flags.Parse([]string{"-base64", "aGVsbG8K"})

	fmt.Printf("%q\n", bin)

}
Output:

"hello\n"
Example (Hex)
package main

import (
	"encoding/hex"
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

type hexEncoding struct{}

func (hexEncoding) DecodeString(s string) ([]byte, error) {
	return hex.DecodeString(s)
}

func (hexEncoding) EncodeToString(src []byte) string {
	return hex.EncodeToString(src)
}

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var bin []byte
	// Bind parameter "-hex" to value bin above, with hex decoding
	flags.Var(flagx.Encoded(&bin, hexEncoding{}), "hex", "hex string")

	flags.Parse([]string{"-hex", "68656c6c6f"})

	fmt.Printf("%q\n", bin)

}
Output:

"hello"
Example (Rot13)
package main

import (
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

var rot13replacer [256]byte

func init() {
	for i := 0; i < 256; i++ {
		rot13replacer[i] = byte(i)
	}
	const lower = 'a' - 'A'
	for i := 'A'; i <= 'L'; i++ {
		rot13replacer[i] = byte(i + 13)
		rot13replacer[i+13] = byte(i)
		rot13replacer[i+lower] = byte(i + lower + 13)
		rot13replacer[i+lower+13] = byte(i + lower)
	}
}

type rot13 struct{}

func (rot13) EncodedLen(n int) int { return n }

func (rot13) Encode(dst, src []byte) {
	if len(src) == 0 {
		return
	}
	_ = dst[len(src)-1]
	for i := 0; i < len(src); i++ {
		dst[i] = rot13replacer[src[i]]
	}
}

// EncodeToString returns the rot13 encoding of src.
func (rot13) EncodeToString(src []byte) string {
	dst := make([]byte, len(src))
	rot13{}.Encode(dst, src)
	return string(dst)
}

func (rot13) DecodedLen(n int) int { return n }

func (rot13) Decode(dst, src []byte) (int, error) {
	rot13{}.Encode(dst, src)
	return len(src), nil
}

func (rot13) DecodeString(src string) ([]byte, error) {
	dst := make([]byte, len(src))
	for i := 0; i < len(src); i++ {
		dst[i] = rot13replacer[src[i]]
	}
	return dst, nil
}

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var bin []byte
	// Bind parameter "-password" to value bin above, with ROT13 decoding
	flags.Var(flagx.Encoded(&bin, rot13{}), "password", "")

	flags.Parse([]string{"-password", "frperg"})

	fmt.Printf("Decoded: %q\n", bin)

}
Output:

Decoded: "secret"

func Env

func Env(key string, v Value) Value

Env wraps a flag.Value and initializes it with the value of the given environment variable if set. The lookup occurs immediately so it happens before command line parsing.

func Map

func Map(m interface{}, parseValue func(string) (interface{}, error)) Value

Map wraps any map to expose it as a flag.Value.

The value type of the map may implement flag.Value. In that case the Set() method will be called on the target element. The element type of the map may implement encoding.TextUnmarshaler. In that case the UnmarshalText() method will be called on the target element.

The parse func is optional. If it is set, it must return a value assignable to an element of the slice. If the returned value is a bare string, it will pass through Set() or UnmarshalText() if the type implements it (see above).

Example
package main

import (
	"flag"
	"fmt"
	"strconv"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	m := make(map[string]int)
	flags.Var(flagx.Map(m, func(s string) (interface{}, error) {
		return strconv.Atoi(s)
	}), "define", "define key=value pairs")

	flags.Parse([]string{"-define", "x=4", "-define", "y=5"})

	if len(m) == 0 {
		fmt.Println("not initialised")
	} else {
		fmt.Printf("x=%d, y=%d\n", m["x"], m["y"])
	}

}
Output:

x=4, y=5

func NullString

func NullString(value **string) Value

NullString allow to define string flags when you want to distinguish the case where the flag is never set from when it is set to an empty string

Example
package main

import (
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	var value *string
	flags.Var(flagx.NullString(&value), "value", "value")

	flags.Parse([]string{"-value", "hello"})

	if value == nil {
		fmt.Println("not initialised")
	} else {
		fmt.Printf("%q\n", *value)
	}

}
Output:

"hello"

func Slice

func Slice(sl interface{}, separator string, parse func(string) (interface{}, error)) Value

Slice wraps any pointer to a slice to expose it as a flag.Value.

The element type of the slice may implement flag.Value. In that case the Set() method will be called on the target element. The element type of the slice may implement encoding.TextUnmarshaler. In that case the UnmarshalText() method will be called on the target element.

The parse func is optional. If it is set, it must return a value assignable to an element of the slice. If the returned value is a bare string, it will pass through Set() or UnmarshalText() if the type implements it (see above).

func Text

func Text(v interface {
	// See [encoding.TextMarshaler].
	MarshalText() (text []byte, err error)
	// See [encoding.TextUnmarshaler].
	UnmarshalText(text []byte) error
}) Value

Text wraps an encoding.TextUnmarshaler + encoding.TextMarshaler as a flag.Getter which can then be passed to flag.Var / flag.FlagSet.Var.

Note: you might prefer to use flag.TextVar which is available since Go 1.19.

func YesNo

func YesNo(b *bool) Value

YesNo returns a flag.Value for a boolean value, but accepting "yes"/"y"/"no"/"n" in addition to strconv.ParseBool values.

Example
package main

import (
	"flag"
	"fmt"

	"github.com/dolmen-go/flagx"
)

func main() {
	flags := flag.NewFlagSet("test", flag.PanicOnError) // Usually flag.CommandLine

	b1 := false
	b2 := true
	flags.Var(flagx.YesNo(&b1), "opt1", "boolean option")
	flags.Var(flagx.YesNo(&b2), "opt2", "boolean option")

	flags.Parse([]string{"-opt1=yes", "-opt2=no"})

	fmt.Println(b1)
	fmt.Println(b2)

}
Output:

true
false

Directories

Path Synopsis
flagfile module
flagnet module
flagtrace module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL