param

package
v5.19.4 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2023 License: MIT Imports: 19 Imported by: 3

Documentation

Overview

Package param is used for setting the starting parameters for an application. It allows developers to define parameters in their packages and then in main() they can call Parse and command line parameters will be compared against the defined parameters and the corresponding values will be set.

You can add parameters to the set of params to be checked with the Add function and you can add alternative names with AltNames which returns an option function that will add the alternative names to the set of ways that a parameter can be referenced. Similarly the GroupName function allows you to group related parameters together so that they will be shown together in the usage message.

The way to use this package is to create a PSet and then to add parameters to it and when you've set all the parameters you want, you call Parse on the PSet. You can create a PSet with the NewSet function but it is more convenient to use the convenience function from the paramset package:

paramset.NewOrPanic(...)

this will automatically set the mandatory helper to the Standard helper. It will Panic if any errors are detected. This allows you to test that no errors were detected when the parameters were added while still ensuring that your program will fail early if any parameters are specified incorrectly.

The standard helper adds some parameters to the PSet. These allow the user to request a usage message and to specify in detail exactly how much help to show. This gives a consistent interface to your command line tools and access to many useful features that will make your tools easier to use.

When adding a new parameter you need to choose the Setter that you want it to use. The psetter package provides a lot of standard ones but you can write your own if you have a package where you want to instantiate a parameter that is not covered by the standard setters.

Optionally you can choose to provide actions to be performed once the parameter has been seen. The paction package provides some standard actions but you can write your own. These can be useful to set parameters where if one is set it implies that another should take a certain value. Actions can also be used to record how many of a group of parameters have been set so that you could, for instance, check that only one of a group of mutually exclusive parameters has been set.

Similarly you can specify final functions to be run after all parameter processing is complete but before Parse returns to the caller. These final functions can check that the parameters have been set correctly. For instance you can use these final functions to make sure that a sensible combination of parameters has been set.

Example (SetDirectly)

Example_setDirectly shows how to use the param package. It is generally advisable to have the parameter setting grouped into separate functions (see the typicalUse example) but in order to show the use of the param funcs we have added the new parameters in line after constructing the new PSet.

Note that the parameter names are given without any leading dashes. This is because they can be passed on the command line or through parameter files or environment variables where the leading dash is not used.

package main

import (
	"fmt"

	"github.com/nickwells/param.mod/v5/param"
	"github.com/nickwells/param.mod/v5/param/paramset"
	"github.com/nickwells/param.mod/v5/param/psetter"
)

func main() {
	var example1 bool
	var example2 int64

	ps := paramset.NewOrPanic(
		param.SetProgramDescription("what this program does"),
	)

	ps.Add("example1",
		psetter.Bool{Value: &example1},
		"here is where you would describe the parameter",
		// optional additional settings
		param.AltNames("e1"))

	ps.Add("example2",
		psetter.Int64{Value: &example2},
		"the description of the parameter",
		// optional additional settings
		param.AltNames("e2"))

	fmt.Println("example1:", example1)
	fmt.Println("example2:", example2)

	// For the purposes of the example we are passing the parameters in as a
	// slice. In practice you would almost always pass nothing in which case
	// Parse will use the command line arguments.
	ps.Parse([]string{
		"-e1",            // this uses the alternative name for the parameter
		"-example2", "3", // this parameter expects a following value
	})
	fmt.Println("example1:", example1)
	fmt.Println("example2:", example2)

}
Output:

example1: false
example2: 0
example1: true
example2: 3
Example (TypicalUse)

Example_typicalUse shows how you would typically use the param package. Construct the PSet, adding any parameters through AddParam functions either from the main package or else package specific parameter setters. Set some description of the program. Then just call Parse with no parameters so that it will use the command line parameters

package main

import (
	"github.com/nickwells/param.mod/v5/param"
	"github.com/nickwells/param.mod/v5/param/paramset"
	"github.com/nickwells/param.mod/v5/param/psetter"
)

const (
	groupNameTypicalExample = "my-groupname"
	paramNameExample1       = "example1"
	paramNameExample2       = "example2"
)

// progExampleTypicalUse holds configuration values and any other
// program-wide values.
type progExampleTypicalUse struct {
	tuExample1 bool

	tuExample2 int64
}

// tuAddParams1 takes a prog pointer and returns a function which will add
// the parameters to the PSet. This allows you to avoid having global
// variables for your parameter values and still allows you to group the
// parameter setup in a separate function.
func tuAddParams1(prog *progExampleTypicalUse) param.PSetOptFunc {
	return func(ps *param.PSet) error {
		// we must set the group description before we can use the group name.
		// Parameters which don't explicitly set the group name are put in the
		// pre-declared "cmd" group
		ps.SetGroupDescription(groupNameTypicalExample,
			"The parameters for my command")

		ps.Add(paramNameExample1,
			psetter.Bool{Value: &prog.tuExample1},
			"here is where you would describe the parameter",
			// Here we add alternative parameter names
			param.AltNames("e1"),
			// Here we set the name of the group of parameters. This grouping
			// is used to shape the help message delivered
			param.GroupName(groupNameTypicalExample),
			// Here we add a reference to the other parameter. This will
			// appear in the parameter help text. It is an error if the named
			// parameter does not exist.
			param.SeeAlso(paramNameExample2),
		)

		return nil
	}
}

// tuAddParams2 takes a prog pointer and returns a function which will add
// the parameters to the PSet.
func tuAddParams2(prog *progExampleTypicalUse) param.PSetOptFunc {
	return func(ps *param.PSet) error {
		// add the example2 parameter to the set. Note that we don't set any
		// groupname and so this will be in the default group for the command
		// ("cmd")
		ps.Add(paramNameExample2,
			psetter.Int64{Value: &prog.tuExample2},
			"the description of the parameter",
			param.AltNames("e2"),
			param.SeeAlso(paramNameExample1),
		)

		return nil
	}
}

// Example_typicalUse shows how you would typically use the param
// package. Construct the PSet, adding any parameters through AddParam
// functions either from the main package or else package specific parameter
// setters. Set some description of the program. Then just call Parse with no
// parameters so that it will use the command line parameters
func main() {
	prog := &progExampleTypicalUse{}
	ps := paramset.NewOrPanic(
		tuAddParams1(prog),
		tuAddParams2(prog),
		param.SetProgramDescription("what this program does"))
	ps.Parse()

	// the rest of your program goes here
}
Output:

Example (WithEnvVar)

Example_withEnvVar shows how to use the param package using environment variables to set the parameter values

package main

import (
	"fmt"
	"os"

	"github.com/nickwells/param.mod/v5/param"
	"github.com/nickwells/param.mod/v5/param/paramset"
	"github.com/nickwells/param.mod/v5/param/psetter"
)

// Example_withEnvVar shows how to use the param package using environment
// variables to set the parameter values
func main() {
	wevExample1 = false
	wevExample2 = 0

	ps := paramset.NewOrPanic(
		wevAddParams1,
		wevAddParams2,
		param.SetProgramDescription("what this program does"))
	ps.SetEnvPrefix("GOLEM_PARAM_TEST_")
	ps.AddEnvPrefix("golem_param_test2_")

	os.Setenv("GOLEM_PARAM_TEST_"+"example1", "")
	os.Setenv("golem_param_test2_"+"example2", "3")

	fmt.Println("example1:", wevExample1)
	fmt.Println("example2:", wevExample2)
	// For the purposes of the example we are passing a slice of
	// strings. This is just to prevent the Parse func from setting any
	// values (and complaining about invalid parameters) from the command
	// line (the os.Args slice).
	ps.Parse([]string{})
	fmt.Println("example1:", wevExample1)
	fmt.Println("example2:", wevExample2)

}

const wevExampleGroupName = "groupname"

var (
	wevExample1 bool

	wevExample2 int64
)

// wevAddParams1 will set the "example1" parameter in the PSet
func wevAddParams1(ps *param.PSet) error {
	ps.SetGroupDescription(wevExampleGroupName,
		"The parameters for my command")

	ps.Add("example1",
		psetter.Bool{Value: &wevExample1},
		"here is where you would describe the parameter",
		param.AltNames("e1"),
		param.GroupName(wevExampleGroupName))

	return nil
}

// wevAddParams2 will set the "example2" parameter in the PSet
func wevAddParams2(ps *param.PSet) error {
	ps.Add("example2",
		psetter.Int64{Value: &wevExample2},
		"the description of the parameter",
		param.AltNames("e2"),
		param.GroupName(wevExampleGroupName))

	return nil
}
Output:

example1: false
example2: 0
example1: true
example2: 3

Index

Examples

Constants

View Source
const (
	SrcCommandLine   = "command line"
	SrcConfigFilePfx = "config file"
	SrcEnvironment   = "environment"
)

These constants are the location values used to show where parameters are set

View Source
const DfltGroupName = "cmd"

DfltGroupName is the parameter group name that a parameter will have if no explicit group name is given. It is expected that parameters specific to the command will be in this group.

View Source
const DfltProgName = "PROGRAM NAME UNKNOWN"

DfltProgName is the program name that will be returned if Parse has not yet been called

View Source
const DfltTerminalParam = "--"

DfltTerminalParam is the default value of the parameter that will stop command-line parameters from being processed. Any parameters found after this value will be available through the Remainder() func. This default value can be overridden through the SetTerminalParam func

Variables

This section is empty.

Functions

func ConfigFileActionFunc

func ConfigFileActionFunc(_ location.L, p *ByName, paramVals []string) error

ConfigFileActionFunc can be called as an action func and will take the second entry in the paramVals (which is expected to exist) as the name of a config file from which to take parameters.

func ConvertEnvVarNameToParamName

func ConvertEnvVarNameToParamName(name string) string

ConvertEnvVarNameToParamName converts an environment variable name to a parameter name. Any environment variable prefix (as added by AddEnvPrefix) should have been stripped off first. It should have the opposite effect to the ConvertParamNameToEnvVarName function

func ConvertParamNameToEnvVarName

func ConvertParamNameToEnvVarName(name string) string

ConvertParamNameToEnvVarName converts a parameter name to a valid environment variable name. Note that in order to be recognised it will need to be prefixed by a recognised environment variable prefix as added by AddEnvPrefix. It should have the opposite effect to the ConvertEnvVarNameToParamName function

func DontExitOnParamSetupErr

func DontExitOnParamSetupErr(ps *PSet) error

DontExitOnParamSetupErr turns off the standard behaviour of exiting if an error is detected while initialising the param set. The error is reported in either case

func GroupNameCheck

func GroupNameCheck(name string) error

GroupNameCheck checks that the group name is valid and returns an error if not

func SetAsTerminal

func SetAsTerminal(bp *ByPos) error

SetAsTerminal is a function which can be passed as a PosOptFunc. It sets the flag on the positional parameter indicating that it is terminal. Only the last positional parameter can be terminal; this is checked separately later.

func SuggestGroups

func SuggestGroups(ps *PSet, s string) []string

SuggestGroups finds those group names the shortest distance from the passed value and returns them

func SuggestNotes

func SuggestNotes(ps *PSet, s string) []string

SuggestNotes finds those note names the shortest distance from the passed value and returns them

func SuggestParams

func SuggestParams(ps *PSet, s string) []string

SuggestParams finds those parameter names the shortest distance from the passed value and returns them

Types

type ActionFunc

type ActionFunc func(loc location.L, p *ByName, paramValues []string) error

ActionFunc is the type of a function to be called when the ByName parameter is encountered.

loc gives details on where the param was seen, this includes a description of the source (for instance "command line")

param is the parameter which was matched.

paramValues will have one or possibly two entries: the name used to match the param and (possibly) the value string.

type Attributes

type Attributes int32

Attributes records various flags that can be set on a ByName parameter

const (
	// CommandLineOnly means that the parameter can only be set on the
	// command line. Note that this also includes being set through values
	// passed to the Parse func as a slice of strings. You might want to set
	// this attribute on parameters which would always be different between
	// command invocations or where setting it would make the program
	// terminate. For instance, it is set on the standard help attributes as
	// setting these in a configuration file would never allow the program to
	// execute.
	CommandLineOnly Attributes = 1 << iota
	// MustBeSet means that the parameter must be given - it cannot be
	// omitted
	MustBeSet
	// SetOnlyOnce means that only the first time it is set will have any
	// effect and any subsequent attempts to set it will be ignored. You can
	// control the behaviour when multiple attempts are made through a
	// SetterFunc (see the SetOnce type in the paction package). You might
	// want to set this on a parameter that you want to set for all users in
	// a global configuration file that only the system administrator can
	// edit. This would allow you to set a system-wide policy.
	SetOnlyOnce
	// DontShowInStdUsage means that the parameter name will be suppressed
	// when the usage message is printed unless the expanded usage message
	// has been requested
	DontShowInStdUsage
	// IsTerminalParam means that when this parameter is encountered
	// command-line parameter processing will stop. Any further parameters
	// will be ignored and added to the slice of remaining params for
	// subsequent processing by the application. Setting it will also set the
	// CommandLineOnly attribute.
	IsTerminalParam
)

type ByName

type ByName struct {
	// contains filtered or unexported fields
}

ByName represents a parameter which is set by matching a name - it includes details such as:

- the parameter name

- any alternate names by which it can be set

- the name of the group to which it belongs

- the action to take when it is observed (typically setting a value)

- the description (used in the help message)

- the attributes

- the place(s) where it has been set - the last one takes precedence

This should not be created directly. The Add method on the PSet will generate a ByName and add it to the set of program parameters, A pointer to the ByName is returned.

Most of the values and methods on this are for the purposes of generating the help message and enforcing usage restrictions when parsing the program parameters.

For anyone not writing a bespoke help class the only useful methods on this class are the HasBeenSet and WhereSet methods. You can record the ByName pointer returned by the PSet.Add method and then in a FinalCheck function you can test whether or not this and other parameters were set and confirm that the combination of parameters is allowed. See the PSet.AddFinalCheck method.

func (ByName) AltNames

func (p ByName) AltNames() []string

AltNames returns a copy of the alternative names of the ByName parameter

func (ByName) AttrIsSet

func (p ByName) AttrIsSet(attr Attributes) bool

AttrIsSet will return true if the supplied attribute is set on the param. Multiple attributes may be given in which case they must all be set

func (ByName) Description

func (p ByName) Description() string

Description returns the description of the ByName parameter

func (ByName) ErrWriter

func (p ByName) ErrWriter() io.Writer

ErrWriter returns the error writer of the PSet that this parameter belongs to

func (ByName) GroupName

func (p ByName) GroupName() string

GroupName returns the groupName of the ByName parameter

func (ByName) HasBeenSet

func (p ByName) HasBeenSet() bool

HasBeenSet will return true if the parameter has been set.

func (ByName) InitialValue

func (p ByName) InitialValue() string

InitialValue returns the initialValue of the ByName parameter

func (ByName) Name

func (p ByName) Name() string

Name returns the name of the ByName parameter

func (ByName) PSet

func (p ByName) PSet() *PSet

PSet returns the parameter set to which the ByName parameter belongs

func (ByName) SeeAlso added in v5.1.0

func (p ByName) SeeAlso() []string

SeeAlso returns a sorted list of references to other parameters

func (ByName) SeeNotes added in v5.7.0

func (p ByName) SeeNotes() []string

SeeNotes returns a sorted list of references to notes

func (ByName) Setter

func (p ByName) Setter() Setter

Setter returns the setter

func (ByName) StdWriter

func (p ByName) StdWriter() io.Writer

StdWriter returns the standard writer of the PSet that this parameter belongs to

func (ByName) ValueName added in v5.6.0

func (p ByName) ValueName() string

ValueName returns the parameter's bespoke value name

func (ByName) WhereSet

func (p ByName) WhereSet() []string

WhereSet returns a copy of the list of places where the ByName parameter has been set

type ByPos

type ByPos struct {
	// contains filtered or unexported fields
}

ByPos represents a positional parameter. There are numerous strict rules about how this can be used. A positional parameter will only be checked on the command line (or a slice of strings); it cannot be set by an environment variable or in a config file. There must be enough command line arguments for all the positional parameters to be set. Only the last parameter can be a terminal parameter (a terminal parameter ends the parsing and returns).

Having a parameter as a terminal parameter will allow any following parameters to be parsed with different parameter sets. So, for instance, the programmer can switch on the value of the positional parameters and choose a different PSet for parsing the remaining parameters. This allows support for tools with an interface like 'git' or the 'go' command itself.

func (ByPos) Description

func (bp ByPos) Description() string

Description returns the parameter description

func (ByPos) ErrWriter

func (bp ByPos) ErrWriter() io.Writer

ErrWriter returns the error writer of the PSet that this parameter belongs to

func (ByPos) InitialValue

func (bp ByPos) InitialValue() string

InitialValue returns the initialValue of the ByPos parameter

func (ByPos) IsTerminal

func (bp ByPos) IsTerminal() bool

IsTerminal returns true if the ByPos parameter is marked as terminal

func (ByPos) Name

func (bp ByPos) Name() string

Name returns the parameter name

func (ByPos) Setter

func (bp ByPos) Setter() Setter

Setter returns the setter

func (ByPos) StdWriter

func (bp ByPos) StdWriter() io.Writer

StdWriter returns the standard writer of the PSet that this parameter belongs to

type ConfigFileDetails

type ConfigFileDetails struct {
	Name         string
	CfConstraint filecheck.Exists
	// contains filtered or unexported fields
}

ConfigFileDetails records the details of a configuration file. Specifically its name and details about whether or not it must exist

func (ConfigFileDetails) ParamsMustExist

func (cfd ConfigFileDetails) ParamsMustExist() bool

ParamsMustExist will return true if the existence rule for the file is set to paramMustExist, that is, if the file should only contain valid parameters

func (ConfigFileDetails) String

func (cfd ConfigFileDetails) String() string

String returns a string describing the ConfigFileDetails

type ErrMap

type ErrMap errutil.ErrMap

ErrMap is the type used to store the errors recorded when parsing the parameters. Each map entry represents a parameter for which errors were detected; all the errors for that parameter are stored in a slice. Errors not related to any individual parameter are stored in the map entry with a key of an empty string.

type Example

type Example struct {
	Ex   string
	Desc string
}

Example records a sample usage and a description for the "Examples" section of the help message

type FinalCheckFunc

type FinalCheckFunc func() error

FinalCheckFunc is the type of a function to be called after all the parameters have been set

type Group

type Group struct {
	Name        string
	Desc        string
	Params      []*ByName
	HiddenCount int
	ConfigFiles []ConfigFileDetails
	// contains filtered or unexported fields
}

Group holds details about a group of parameters

func (Group) AllParamsHidden

func (g Group) AllParamsHidden() bool

AllParamsHidden returns true if all the parameters are marked as not to be shown in the standard usage message, false otherwise

func (*Group) SetHiddenCount

func (g *Group) SetHiddenCount() int

SetHiddenCount counts how many params have the DontShowInStdUsage attribute set and records this in the HiddenCount field. It also returns the value

type Helper

type Helper interface {
	ProcessArgs(ps *PSet)
	ErrorHandler(ps *PSet, errors ErrMap)
	Help(ps *PSet, messages ...string)
	AddParams(ps *PSet)
}

Helper is the interface that a helper object must implement. It should supply a set of default parameters to be added by the AddParams func and a func (called ProcessArgs) to be called after the parsing is complete which will operate on the default parameter values. There should be a Help func for reporting a help message and an error handler for reporting errors.

type Note

type Note struct {
	Headline   string
	Text       string
	Attributes NoteAttributes
	// contains filtered or unexported fields
}

Note records additional text to be attached to the help message which does not sit under any of the other parts

func (Note) AttrIsSet

func (n Note) AttrIsSet(attr NoteAttributes) bool

AttrIsSet will return true if the supplied attribute is set on the note. Multiple attributes may be given in which case they must all be set

func (Note) SeeNotes added in v5.7.0

func (n Note) SeeNotes() []string

SeeNotes returns a sorted list of the notes referenced by this note

func (Note) SeeParams added in v5.7.0

func (n Note) SeeParams() []string

SeeParams returns a sorted list of the params referenced by this note

type NoteAttributes

type NoteAttributes int32

NoteAttributes records various flags that can be set on a Note

const (
	// DontShowNoteInStdUsage means that the note will be suppressed when the
	// usage message is printed unless an expanded usage message has been
	// requested
	DontShowNoteInStdUsage NoteAttributes = 1 << iota
)

type NoteOptFunc

type NoteOptFunc func(n *Note) error

NoteOptFunc is the type of an option func used to set various flags etc on a note.

func NoteAttrs

func NoteAttrs(attrs NoteAttributes) NoteOptFunc

NoteAttrs returns a NoteOptFunc which will set the attributes of the note to The passed value.

func NoteSeeNote added in v5.7.0

func NoteSeeNote(notes ...string) NoteOptFunc

NoteSeeNote will add the names of notes to the list of notes to be referenced when showing the help message. They will be checked before the parameters are parsed to ensure that they are all valid names. Note that it is not possible to check the names as they are added since the referenced name might not have been added yet. It will return an error if the referenced name has already been used.

func NoteSeeParam added in v5.7.0

func NoteSeeParam(params ...string) NoteOptFunc

NoteSeeParam will add the names of parameters to the list of parameters to be referenced when showing the help message. They will be checked before the parameters are parsed to ensure that they are all valid names. Note that it is not possible to check the names as they are added since the referenced name might not have been added yet. It will return an error if the referenced name has already been used.

type NullRemHandler

type NullRemHandler struct{}

NullRemHandler is a type which can be set as a remainder handler if you wish to perform the remainder handling yourself after the parsing is complete.

func (NullRemHandler) HandleRemainder

func (rh NullRemHandler) HandleRemainder(_ *PSet, _ *location.L)

HandleRemainder does nothing, specifically it doesn't call the helper's ErrorHandler (which by default will terminate the program). If you set this as the RemHandler for the PSet then you will have to handle the remaining arguments after the program has been called by calling the Remainder method on the PSet.

type OptFunc

type OptFunc func(p *ByName) error

OptFunc is the type of a option func used to set various flags etc on a parameter.

func AltName deprecated

func AltName(altName string) OptFunc

AltName will attach an alternative name to the parameter. It will return an error if the alternative name has already been used.

Deprecated: use AltNames

func AltNames added in v5.8.0

func AltNames(altNames ...string) OptFunc

AltNames will attach multiple alternative names to the parameter. It will return an error if any alternative name has already been used

func Attrs

func Attrs(attrs Attributes) OptFunc

Attrs returns an OptFunc which will set the attributes of the parameter to the passed value. Note that if the IsTerminal attribute is set then the CommandLineOnly attribute is forced on as well.

func GroupName

func GroupName(name string) OptFunc

GroupName will set the parameter group name for the parameter. The group name is stripped of any leading or trailing white space and it is checked for validity; an error is returned if it is not valid. A parameter group can be used to collect related parameters together, this grouping will be reflected when the usage message is displayed

func PostAction

func PostAction(action ActionFunc) OptFunc

PostAction will return an option function which will add an action function to the list of functions to be called after the value has been set.

func SeeAlso added in v5.1.0

func SeeAlso(refs ...string) OptFunc

SeeAlso will add the names of parameters to the list of parameters to be referenced when showing the help message. They will be checked before the parameters are parsed to ensure that they are all valid names. Note that it is not possible to check the names as they are added since the referenced name might not have been added yet. It will return an error if the referenced name has already been used. A reference to the parameter itself will be ignored; this allows the same group of parameter names to be passed to each parameter in the group wihout self-reference.

func SeeNote added in v5.7.0

func SeeNote(notes ...string) OptFunc

SeeNote will add the names of parameters to the list of parameters to be referenced when showing the help message. They will be checked before the parameters are parsed to ensure that they are all valid names. Note that it is not possible to check the names as they are added since the referenced name might not have been added yet. It will return an error if the referenced name has already been used.

func ValueName added in v5.6.0

func ValueName(vName string) OptFunc

ValueName returns an OptFunc that will set the short value name used in the parameter summary (it follows the "=" after the parameter name). If this is not empty this will be used in preference to either the param setter's value description or the setter's type name. This allows a per-parameter value name to be given. It will return an error if the vName is the empty string.

type PSet

type PSet struct {
	pager.Writers
	// contains filtered or unexported fields
}

PSet represents a collection of parameters to be parsed together. A program will typically only have one PSet but having this makes it easier to retain control. You would create the PSet in main using the paramset.New func which will automatically set the standard help member. This lets you know precisely which parameters have been enabled before calling Parse

func NewSet

func NewSet(psof ...PSetOptFunc) (*PSet, error)

NewSet creates a new PSet with the various maps and slices initialised. Generally you would be better off creating a PSet through the paramset.New function which will automatically set the default helper

func (*PSet) Add

func (ps *PSet) Add(name string, setter Setter, desc string, opts ...OptFunc,
) *ByName

Add will add a new named parameter to the set that will be recognised. The setter defines the function that should be performed when the parameter is processed and will typically be a parameter setter from the psetter package that will set the value of an associated variable.

Any leading or trailing spaces are silently removed. Add will panic if the parameter has already been used. Add will also panic if the name doesn't start with a letter or if it contains any other character than a letter, a digit or a dash.

Various other features of the parameter can be set by the OptFuncs which may be passed after the description.

Example

ExamplePSet_Add shows the usage of the Add method of the PSet. This is used to add new parameters into the set. This, most simple, use of the Add function will add a parameter to the parameter set in the default group, with no alternative names that can be used and the parameter will appear in the standard usage message.

package main

import (
	"github.com/nickwells/param.mod/v5/param/paramset"
	"github.com/nickwells/param.mod/v5/param/psetter"
)

func main() {
	ps := paramset.NewOrPanic()

	var f float64

	ps.Add("param-name", psetter.Float64{Value: &f},
		"a parameter description for the usage message")
}
Output:

Example (WithExtras)

ExamplePSet_Add_withExtras shows the usage of the Add method of the PSet. This is used to add new parameters into the set. This example shows the use of the additional options that can be passed to the Add call.

package main

import (
	"fmt"

	"github.com/nickwells/param.mod/v5/param"
	"github.com/nickwells/param.mod/v5/param/paction"
	"github.com/nickwells/param.mod/v5/param/paramset"
	"github.com/nickwells/param.mod/v5/param/psetter"
)

func main() {
	ps := paramset.NewOrPanic()

	var f float64
	var fHasBeenSet bool

	// We only capture the return value so that we can report the settings
	// below.
	p := ps.Add("param-name", psetter.Float64{Value: &f},
		"a parameter description for the usage message",
		// The following parameters are optional - a list of zero or more
		// functions that set some of the extra features of the parameter

		// This next line returns a function that sets the group name of the
		// parameter. All parameters with the same group name will be shown
		// together in the usage message.
		param.GroupName("test.group"),
		// This sets flags on the parameter:
		//
		// DontShowInStdUsage: the parameter will not be shown in the default
		//                     help message. This can be useful for less
		//                     commonly useful parameters.
		//
		// MustBeSet: it is an error that Parse will report if the parameter
		//            is not given when Parse is called
		param.Attrs(param.DontShowInStdUsage|param.MustBeSet),
		// This gives alternative strings that can be used to set the
		// parameter value. Each parameter name must be unique; the param
		// package will panic if any duplicate names are used.
		param.AltNames("pn", "p-n"),
		// This provides a function to be called immediately after the
		// parameter has been set. It uses an action function from the
		// paction package that will set the fHasBeenSet variable to
		// true. This can also be found by the HasBeenSet method on the
		// ByName parameter.
		param.PostAction(paction.SetVal(&fHasBeenSet, true)),
	)

	fmt.Printf("param (f) value:   %3.1f\n", f)
	fmt.Printf("fHasBeenSet value: %v\n", fHasBeenSet)
	fmt.Printf("param HasBeenSet?: %v\n", p.HasBeenSet())
	fmt.Printf("group name: %s\n", p.GroupName())
	fmt.Printf("param name: %s\n", p.Name())
	fmt.Printf("CommandLineOnly:    %t\n", p.AttrIsSet(param.CommandLineOnly))
	fmt.Printf("MustBeSet:          %t\n", p.AttrIsSet(param.MustBeSet))
	fmt.Printf("SetOnlyOnce:        %t\n", p.AttrIsSet(param.SetOnlyOnce))
	fmt.Printf("DontShowInStdUsage: %t\n", p.AttrIsSet(param.DontShowInStdUsage))

}
Output:

param (f) value:   0.0
fHasBeenSet value: false
param HasBeenSet?: false
group name: test.group
param name: param-name
CommandLineOnly:    false
MustBeSet:          true
SetOnlyOnce:        false
DontShowInStdUsage: true

func (*PSet) AddByPos

func (ps *PSet) AddByPos(name string, setter Setter,
	desc string, opts ...PosOptFunc,
) *ByPos

AddByPos will add a new positional parameter to the set of parameters. The setter defines the function that should be performed when the parameter is processed and will typically be a parameter setter from the paramSetter package that will set the value of an associated variable

Various other features of the parameter can be set by the OptFuncs which may be passed after the description.

Unlike with the ByName parameter the name given here is purely for documentation purposes and should be a very short value just used as a hint at the intended purpose. The name should be expanded and explained by the description.

func (*PSet) AddConfigFile

func (ps *PSet) AddConfigFile(fName string, c filecheck.Exists)

AddConfigFile adds an additional config file which will also be checked for existence and read from. Files are processed in the order they are added.

This can be used to set a system-wide config file and a per-user config file that can be used to provide personal preferences.

func (*PSet) AddConfigFileStrict

func (ps *PSet) AddConfigFileStrict(fName string, c filecheck.Exists)

AddConfigFileStrict behaves as for AddConfigFile except that parameters given in the file must exist for the given program. This is suitable for program-specific config files where it can be expected that any parameter given in the config file will exist and so it should be reported as an error if it does not.

func (*PSet) AddEnvPrefix

func (ps *PSet) AddEnvPrefix(prefix string)

AddEnvPrefix adds a new prefix to the list of environment variable prefixes. If the new prefix is empty or a substring of any of the existing prefixes or vice versa then it panics

func (*PSet) AddErr

func (ps *PSet) AddErr(name string, err ...error)

AddErr adds the errors to the named entry in the Error Map

func (*PSet) AddExample

func (ps *PSet) AddExample(ex, desc string)

AddExample adds an example to the set of examples on the PSet. Note that there is no validation of the given example

func (*PSet) AddFinalCheck

func (ps *PSet) AddFinalCheck(fcf FinalCheckFunc)

AddFinalCheck will add a function to the list of functions to be called after all the parameters have been set. Note that multiple functions can be set and they will be called in the order that they are added. Each function should return an error (or nil) to be added to the list of errors detected. All the checks will be called even if one of them returns an error

func (*PSet) AddGroup

func (ps *PSet) AddGroup(name, desc string)

AddGroup will add a new param group to the PSet and set the descriptive text. It will panic if the description has already been set - this is to ensure that the group name is distinct. This description is shown when the usage message is printed. If the short-form description is chosen then the group name is shown instead so it's worth making it a useful value.

A suggested standard for group names is to have parameters specific to a command in a group called 'cmd'. This is the default group name if none is set explicitly.

Or for parameters specific to a package to use the package name prefixed with

'pkg.'

for instance: 'pkg.param'

If you have several groups for the same package or command then you can add an additional suffix after a separating dash.

for instance: 'cmd-formatting' or 'pkg.param-help'

The group name will have any leading and trailing spaces deleted before use.

func (*PSet) AddGroupConfigFile

func (ps *PSet) AddGroupConfigFile(gName, fName string, c filecheck.Exists)

AddGroupConfigFile adds an additional config file for the named group.

func (*PSet) AddNote

func (ps *PSet) AddNote(headline, text string, opts ...NoteOptFunc) *Note

AddNote adds an note to the set of notes on the PSet. The headline of the note must be unique

func (*PSet) AddReference

func (ps *PSet) AddReference(name, desc string)

AddReference adds a reference to the set of references on the PSet

func (*PSet) AreSet

func (ps *PSet) AreSet() bool

AreSet will return true if Parse has been called or false otherwise

func (*PSet) ConfigFiles

func (ps *PSet) ConfigFiles() []ConfigFileDetails

ConfigFiles returns a copy of the current config file details.

func (*PSet) ConfigFilesForGroup

func (ps *PSet) ConfigFilesForGroup(gName string) []ConfigFileDetails

ConfigFilesForGroup returns a copy of the current config file details for the given group name.

func (*PSet) CountByPosParams

func (ps *PSet) CountByPosParams() int

CountByPosParams will return the number of positional parameters

func (*PSet) EnvPrefixes

func (ps *PSet) EnvPrefixes() []string

EnvPrefixes returns a copy of the current environment prefixes

func (PSet) Errors

func (ps PSet) Errors() ErrMap

Errors returns the map of errors for the param set

func (*PSet) Examples

func (ps *PSet) Examples() []Example

Examples returns a copy of the current set of examples.

func (PSet) FindMatchingGroups added in v5.10.0

func (ps PSet) FindMatchingGroups(pattern string) ([]string, error)

FindMatchingGroups returns a, possibly empty, slice of group names which match the pattern and an error which will only be non-nil if the pattern is malformed.

func (PSet) FindMatchingNamedParams added in v5.10.0

func (ps PSet) FindMatchingNamedParams(pattern string) ([]string, error)

FindMatchingNamedParams returns a, possibly empty, slice of parameter names which match the pattern and an error which will only be non-nil if the pattern is malformed.

func (PSet) FindMatchingNotes added in v5.10.0

func (ps PSet) FindMatchingNotes(pattern string) ([]string, error)

FindMatchingNotes returns a, possibly empty, slice of note names which match the pattern and an error which will only be non-nil if the pattern is malformed.

func (PSet) GetGroupByName

func (ps PSet) GetGroupByName(name string) *Group

GetGroupByName returns a pointer to the details for the named Group. If the name is not recognised then the pointer will be nil

func (*PSet) GetGroupDesc

func (ps *PSet) GetGroupDesc(grpName string) string

GetGroupDesc returns the description for the named group or the empty string if the group does not exist.

func (*PSet) GetGroups

func (ps *PSet) GetGroups() []*Group

GetGroups returns a slice of Groups sorted by group name. Each Group element has a slice of ByName parameters and these are sorted by the primary parameter name.

func (*PSet) GetNote

func (ps *PSet) GetNote(headline string) (*Note, error)

GetNote returns a copy of the named note, error will be non-nil if there is no such note.

func (*PSet) GetParamByName

func (ps *PSet) GetParamByName(name string) (p *ByName, err error)

GetParamByName will return the named parameter if it can be found. The error will be set if not

func (*PSet) GetParamByPos

func (ps *PSet) GetParamByPos(idx int) (p *ByPos, err error)

GetParamByPos will return the positional parameter if it exists. The error will be set if not.

func (PSet) HasAltSources

func (ps PSet) HasAltSources() bool

HasAltSources returns true if there are any alternative sources (configuration files, either general or group-specific, or environment variable prefixes) false otherwise

func (PSet) HasEnvPrefixes

func (ps PSet) HasEnvPrefixes() bool

HasEnvPrefixes returns true if there are any environment variable prefixes for this program, false otherwise

func (*PSet) HasExamples

func (ps *PSet) HasExamples() bool

HasExamples returns true if the PSet has any entries in the set of examples

func (PSet) HasGlobalConfigFiles

func (ps PSet) HasGlobalConfigFiles() bool

HasGlobalConfigFiles returns true if there are any non-group-specific config files for this program, false otherwise

func (*PSet) HasGroupName

func (ps *PSet) HasGroupName(grpName string) bool

HasGroupName returns true if the PSet has a group with the given name, false otherwise

func (*PSet) HasNotes

func (ps *PSet) HasNotes() bool

HasNotes returns true if the PSet has any entries in the set of notes

func (*PSet) HasReferences

func (ps *PSet) HasReferences() bool

HasReferences returns true if the PSet has any references

func (*PSet) Help

func (ps *PSet) Help(message ...string)

Help will call the helper's Help function

func (*PSet) Notes

func (ps *PSet) Notes() map[string]*Note

Notes returns a copy of the current set of notes.

func (*PSet) Parse

func (ps *PSet) Parse(args ...[]string) ErrMap

Parse will initialise the parameter values

It will first look in the configuration files (if any filenames have been set using the SetConfigFile function).

Next it will look in the environment (if any environment prefix strings have been set using the SetEnvPrefix function).

Lastly it will process the command line arguments.

It takes zero or more arguments each of which is a slice of strings. If no arguments are given then it uses the command line parameters (excluding the first which is used to set the program name). If any argument is passed then all the slices are concatenated together and that is parsed.

Before any further processing the helper's ProcessArgs method is called. This is expected to act on any helper parameters and to report any errors.

Finally it will process any remaining parameters - these are any parameters following a positional parameter that has been marked as terminal or any parameters following the terminal parameter (which is "--" by default). If no trailing arguments are expected and no handler has been set for handling them then the default handler is called which will record an error and call the helper.ErrorHandler method.

It will return a map of errors: mapping parameter name to a slice of all the errors seen for that parameter. In order to make sensible use of this the report-errors and exit-on-errors flags should be turned off - there are functions which allow the caller to do this (or they can be set through the StdHelp command-line flags) but they should be called before Parse is called. The default behaviour is to report any errors and exit. This means that you can sensibly ignore the return value unless you want to handle the errors yourself.

It will panic if it is called twice.

func (*PSet) ProgBaseName

func (ps *PSet) ProgBaseName() string

ProgBaseName returns the base name of the program - the program name with any leading directories stripped off. Note that this should be called only after the arguments are already parsed - before that it will only give the default value

func (*PSet) ProgDesc

func (ps *PSet) ProgDesc() string

ProgDesc returns the program description

func (*PSet) ProgName

func (ps *PSet) ProgName() string

ProgName returns the name of the program - the value of the zeroth argument. Note that this should be called only after the arguments are already parsed - before that it will only give the default value

func (*PSet) References

func (ps *PSet) References() []Reference

References returns a copy of the current set of references.

func (*PSet) Remainder

func (ps *PSet) Remainder() []string

Remainder returns any arguments that come after the terminal parameter.

func (*PSet) SetConfigFile

func (ps *PSet) SetConfigFile(fName string, c filecheck.Exists)

SetConfigFile will set the list of config files from which to read parameter values to just the value given. If it is used with the AddConfigFile method below then it should be the first method called.

The config file name may start with ~/ to refer to the home directory of the user.

The config file should contain parameter names and values separated by an equals sign. Any surrounding space around the parameter name and value are stripped off. For instance the following lines will have the same effect of setting the value of the myParam attribute to 42:

myParam  = 42
myParam=42

The parameter name can be preceded by a comma-separated list of program names and a slash in which case the parameter will only be applied when the config file is being parsed by one of the listed programs. The match is applied to the basename of the program (the part after the last pathname separator). This is particularly useful if there is a config file which is shared amongst a number of different programs. It could also be used to give different default behaviour when a given program has several different names (one binary with different names linked to it). As for the parameter name and value any surrounding whitespace is stripped from the program name before comparison. For instance:

myProg/myProgParam = 99

Parameters which don't take a value should appear on a line on their own, without an equals character following. As with parameters which take a value any surrounding white space is removed and ignored.

Since a parameter file might be shared between several programs, a parameter in a config file which is not found in the set of parameters for that program is not reported as an error as it might be targeted at a different program. This is not the case for parameters which are marked as being for specific programs by having a list of program names before the parameter name. Similarly for parameters in files which are for a particular parameter group, the parameter must be recognised or else it is reported as an error.

The config file supports the features of a file parsed by the fileparse.FP such as comments and include files.

func (*PSet) SetConfigFileStrict

func (ps *PSet) SetConfigFileStrict(fName string, c filecheck.Exists)

SetConfigFileStrict behaves as for SetConfigFile except that parameters given in the file must exist for the given program. This is suitable for program-specific config files where it can be expected that any parameter given in the config file will exist and so it should be reported as an error if it does not.

func (*PSet) SetEnvPrefix

func (ps *PSet) SetEnvPrefix(prefix string)

SetEnvPrefix will set the prefix for environment variables that are to be considered as potential parameters. This prefix is stripped from the name and any underscores are replaced with dashes before the environment variable name is passed on for matching against parameters

func (*PSet) SetGroupConfigFile

func (ps *PSet) SetGroupConfigFile(gName, fName string, c filecheck.Exists)

SetGroupConfigFile sets the config file for the named group. Group config files have several constraints: the parameters in the file must only be for the named group and it is an error if any parameter in the file is not recognised.

Additionally, the param group must already exist.

func (*PSet) SetGroupDescription deprecated

func (ps *PSet) SetGroupDescription(name, desc string)

SetGroupDescription will call AddGroup

Deprecated: use AddGroup

func (*PSet) SetNamedRemHandler

func (ps *PSet) SetNamedRemHandler(rh RemHandler, name string) error

SetNamedRemHandler calls SetRemHandler to set the remainder handler and if that succeeds it will set the text to be used for the remaining arguments. This name will be used in the help message

func (*PSet) SetProgramDescription

func (ps *PSet) SetProgramDescription(desc string)

SetProgramDescription sets the program description

func (*PSet) SetRemHandler

func (ps *PSet) SetRemHandler(rh RemHandler) error

SetRemHandler sets the value of the remainder handler to be used by the parameter set. Note that the handler must be set and so you cannot pass nil. The default behaviour is for an error to be reported if there are any unprocessed parameters. If you expect additional arguments after either a terminal positional parameter or after an explicit end-of-parameters parameter (see the TerminalParam method) then you have two choices. You can set the remainder handler to the NullRemHandler and process the remainder yourself in the body of the program. Alternatively you can pass a RemHandler that will handle the remainder in the Parse method.

If this is not set the default behaviour is to report any extra parameters after the TerminalParam as errors

func (*PSet) SetTerminalParam

func (ps *PSet) SetTerminalParam(s string)

SetTerminalParam sets the value of the parameter that is used to terminate the processing of parameters. This can be used to override the default value which is set to DfltTerminalParam

func (*PSet) TerminalParam

func (ps *PSet) TerminalParam() string

TerminalParam will return the current value of the terminal parameter. This is the parameter which can be given to indicate that any following parameters should be handled by the RemHandler (see SetRemHandler and SetNamedRemHandler). Unless SetTerminalParam has been called this will return the default value: DfltTerminalParam

func (*PSet) TrailingParamsExpected

func (ps *PSet) TrailingParamsExpected() bool

TrailingParamsExpected returns true if a remainder handler has been set successfully and false otherwise

func (*PSet) TrailingParamsName

func (ps *PSet) TrailingParamsName() string

TrailingParamsName returns the name that has been given to the trailing parameters (if any)

func (*PSet) UnusedParams

func (ps *PSet) UnusedParams() map[string][]string

UnusedParams returns a copy of the map of unused parameter names. The map associates a parameter name with a slice of strings which records where the parameter has been set. Unused parameters are always from config files or environment variables; unrecognised parameters given on the command line are reported as errors.

type PSetOptFunc

type PSetOptFunc func(ps *PSet) error

PSetOptFunc is the type of a function that can be passed to NewSet. These functions can be used to set optional behaviour on the parameter set.

func SetErrWriter

func SetErrWriter(w io.Writer) PSetOptFunc

SetErrWriter returns a PSetOptFunc which can be passed to NewSet. It sets the Writer to which error messages are written

func SetHelper

func SetHelper(h Helper) PSetOptFunc

SetHelper returns a PSetOptFunc which can be passed to NewSet. This sets the value of the helper to be used by the parameter set and adds the parameters that the helper needs. Note that the helper must be set and so you must pass some such function. To avoid lots of duplicate code there are sensible defaults which can be used in the param/paramset package.

This can only be set once and this will return an error if the helper has already been set

func SetProgramDescription

func SetProgramDescription(desc string) PSetOptFunc

SetProgramDescription returns a PSetOptFunc which can be passed to NewSet. It will set the program description

func SetStdWriter

func SetStdWriter(w io.Writer) PSetOptFunc

SetStdWriter returns a PSetOptFunc which can be passed to NewSet. It sets the Writer to which standard messages are written

type PosOptFunc

type PosOptFunc func(bp *ByPos) error

PosOptFunc is the type of a option func used to set various flags on a positional parameter

type Reference

type Reference struct {
	Name string
	Desc string
}

Reference records a name and a description for the "See Also" section of the help message

type RemHandler

type RemHandler interface {
	HandleRemainder(ps *PSet, loc *location.L)
}

RemHandler describes how the remaining parameters should be handled. These are the parameters that remain after either a terminal positional parameter or else a terminal parameter (by default this is "--")

The HandleRemainder func is for specifying how to handle any remaining arguments after the standard parsing has been completed. It takes as an argument the PSet on which Parse has been called. The remaining parameters can be retrieved for further processing through the Remainder method on that PSet. The second argument to HandleRemainder is the location that the previous parser reached in the parameters it had been passed.

A typical way of using this mechanism might be to select a new pre-created PSet (or create a new one on the fly) based on the settings of any previous parameters by the previous Parse call. Then Parse can be called on the new PSet passing the remaining arguments given by the Remainder method on the original PSet. This would be a typical use case where a terminal positional parameter has been used; several common commands such as git and go itself use a similar style of command invocation.

In the case where a terminal parameter is given and there is a following list of parameters it is more likely that the extra parameters are not intended as flags to control the operation of the program. In this case the remaining parameters might be taken as a list of values to be processed and a different HandleRemainder function would be appropriate.

type Setter

type Setter interface {
	Set(string) error
	SetWithVal(string, string) error
	ValueReq() ValueReq
	AllowedValues() string
	CurrentValue() string
	CheckSetter(name string)
}

Setter is the interface that wraps the necessary methods for a parameter.

Set takes just the name of the parameter. If the value requirements are such that an argument is not needed then this can set the value or do whatever the Setter is supposed to do. Otherwise it should return an error.

SetWithVal takes the name of the parameter and the associated value. If the value requirements are such that an argument is needed or is optional then this can set the value or do whatever the Setter is supposed to do. Otherwise it should return an error.

ValueReq returns the ValueReq for the parameter: one of Mandatory, Optional or None. It is used when generating a help message.

AllowedValues returns a string documenting the parameters that a parameter value can take. It is used when generating a help message.

CurrentValue returns a string showing the current value of the parameter. It is called when the parameter is added, before any arguments have been parsed in order to get the initial value for use in help messages.

CheckSetter is called when the parameter is added, to ensure that the Setter has been correctly created, for instance that the pointer to the value is not nil or, if the pointer is to a map, that the map being pointed at has been created. Correct behaviour of this func is to panic if the Setter has not been properly set up.

When creating your own Setter implementation you may find it useful to use one of the ValueReq types as an embedded type. So, for instance, if your Setter must have a following value then you can embed the param.ValueReqMandatory struct in your struct. This will provide an appropriate ValueReq method and a Set method that will return an error; you only need to write the SetWithVal method. Similarly if your Setter must not have a following value embed the param.ValueReqNone struct and it will provide an appropriate ValueReq method and a SetWithVal method that will return an error; you only need to write the Set method. For examples of how this is done see the Setter instances in the psetter package.

type Source

type Source struct {
	From      string
	Loc       location.L
	ParamVals []string
	Param     *ByName
}

Source records where a parameter has been set

func (Source) Desc

func (pSrc Source) Desc() string

Desc describes where the param was set

func (Source) String

func (pSrc Source) String() string

String formats a Source into a string

type Sources

type Sources []Source

Sources is a slice of Source

func (Sources) String

func (pSrcs Sources) String() string

String formats a slice of Sources into a String

type SuggestionFunc

type SuggestionFunc func(ps *PSet, s string) []string

SuggestionFunc is the type of a function that returns a slice of suggested alternative names for the given string.

type ValueReq

type ValueReq int

ValueReq encodes whether or not a value is required after a parameter

const (
	Mandatory ValueReq = iota
	Optional
	None
)

Mandatory means that a value must follow the parameter.

Optional means that a value may follow the parameter but need not in which case the default value will be used.

None means that a value must not follow the parameter.

func (ValueReq) String

func (i ValueReq) String() string

Directories

Path Synopsis
Package paction collects together useful action functions that can be applied to params.
Package paction collects together useful action functions that can be applied to params.
Package paramset offers helper functions for creating a new param.PSet.
Package paramset offers helper functions for creating a new param.PSet.
Package pedit collects together useful editors that can be applied to parameters.
Package pedit collects together useful editors that can be applied to parameters.
Package phelp provides the standard help parameter handling which includes printing the standard help message and any error reporting.
Package phelp provides the standard help parameter handling which includes printing the standard help message and any error reporting.
Package psetter contains a collection of useful types that can be used to set parameter values of a program.
Package psetter contains a collection of useful types that can be used to set parameter values of a program.

Jump to

Keyboard shortcuts

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