Documentation ¶
Overview ¶
Package file provides a flagr.Parser that is able to read config files and set the appropriate flags.
Example ¶
package main import ( "encoding/json" "encoding/xml" "errors" "os" "github.com/flga/flagr" "github.com/flga/flagr/file" ) func main() { var fs flagr.Set _ = flagr.Add(&fs, "child.flagName", flagr.Int(1), "usage") configFile := flagr.Add(&fs, "config", flagr.String("config.json"), "usage") if err := fs.Parse( os.Args[1:], file.Parse( file.Static("config.json"), // uses the static file "config.json" as a source file.Mux{ ".json": json.Unmarshal, // tells the parser how to handler ".json" files }, file.IgnoreMissingFile(), // makes the file optional, if it does not exist it is not considered an error file.WithFS(nil), // uses the given fs.FS to lookup the file file.WithMapper(file.NoopMapper), // map flag names to jsonpath (root.child.leaf) using the given mapper, since the flags are already in dot notation no mapping is necessary ), file.Parse( configFile, // this time, use a dynamic config file file.Mux{ ".json": json.Unmarshal, ".xml": xml.Unmarshal, // we're able to parse xml now too }, ), ); err != nil { if errors.Is(err, flagr.ErrHelp) { os.Exit(2) } os.Exit(1) } }
Output:
Index ¶
Examples ¶
Constants ¶
const KeyPathSeparator = "."
KeyPathSeparator is the value used to separate sub paths in path expressions. A typical KeyPath will look something like "root.inner.prop".
Variables ¶
This section is empty.
Functions ¶
func Parse ¶ added in v0.4.0
Parse returns a flagr.FlagParser that parses the file stored in path and assigns the results to any flags that have not yet been set.
Flags cannot have complex values, only primitive values are allowed: strings, bools, ints etc. An exception is made for slices as flags can be repeatable.
This is a valid JSON declaration for a flag named "foo".
{ "foo": 42 }
So is this (assuming that foo is repeatable, otherwise it will be set to the last value of the array):
{ "foo": [1, 2, 3] }
But this is not, as there is no way to map a json object to a flag value:
{ "foo": {"bar": 42} }
The file contents are read and decoded using the decoder mapped to the file's extension. If decoding fails it returns ErrDecode, if no suitable decoder is found it returns ErrUnsupported.
File decoding is controlled by Mux. At least one mapping must be provided.
If the file cannot be read an error is returned. If it cannot be found and IgnoreMissingFile has been set, the error is omitted and parsing stops.
After decoding, we will go trough all the flags that have not yet been set, and try to find their values in the decoded result. Mapping flag names to the decoded properties is done using the given Mapper. If no Mapper is provided it'll use NoopMapper.
If no corresponding value can be found, the flag will remain unset. If a value is found it is converted back to a string and fed trough flag.Value.Set, if this fails we will return the error. If we are unable to convert the value to a string (for example, if it's an object) ErrVal will be returned containing the key that failed and the error.
Types ¶
type DecoderFunc ¶
DecoderFunc is a function that deserializes data into v. Functions like json.Unmarshal conform to this type.
type ErrDecode ¶
type ErrDecode struct {
Err error
}
ErrDecode is returned if deserialization fails.
type ErrUnsupported ¶
ErrUnsupported is returned when we could not find a DecoderFunc in the given Mux with the provided file's extension.
func (ErrUnsupported) Error ¶
func (e ErrUnsupported) Error() string
type Extension ¶
type Extension string
Extension represents a file extension. Values must include the leading dot.
type KeyPath ¶
type KeyPath string
KeyPath represents a path expression which is used to walk the values produced by the decoding of the config file. It is akin to jsonpath but we only support dot notation.
func NoopMapper ¶ added in v0.4.0
NoopMapper returns the given flag name as is.
type Mapper ¶ added in v0.4.0
Mapper converts a flag name into a KeyPath.
Sub paths must be separated by KeyPathSeparator and are not allowed to contain it within them.
Given a flag name like "api_http_address" and a json config file structured as
{ "api": { "http": { "address": "0.0.0.0" } } }
the corresponding KeyPath should be "api.http.address".
If the json file were flat, no mapping would be necessary as long as the field name and the flag name are equal:
{ "api_http_address": "0.0.0.0" }
the corresponding KeyPath should be "api_http_address".
type Mux ¶
type Mux map[Extension]DecoderFunc
Mux maps Extension to DecoderFunc, it is valid for the same DecoderFunc to be used for multiple Extension. For example, if unmarshaling yaml it is encouraged to map both ".yaml" and ".yml" to yaml.Unmarshal.
type Option ¶
type Option func(*Options)
Option is a function that mutates Options.
func IgnoreMissingFile ¶
func IgnoreMissingFile() Option
IgnoreMissingFile makes it so that if the provided file doesn't exist, it is not considered an error.
type Options ¶
type Options struct { Mapper Mapper // Maps flag names to property paths IgnoreMissingFile bool // If true, we don't treat [fs.ErrNotExist] as an error. FS fs.FS // If provided, this will be used instead of the primary filesystem. }
Options contains all the options used to parse a config file.