Package args
import "gitlab.com/zoralab/cerigo/os/args"
Package args is an extended command line interface processor from the standard library’s flag package. It uses the standard library’s “os.Args” as the primary input.
DIFFERENCES
the Manager object is completely discardable after argument parsing.
Help (-h, –help) is not run by default, allowing one to customize accordingly.
Support flag with multiple argument labels like “-h”, “–help”, “help”.
SUPPORTED DATA TYPES
args package has limited data type conversion which is strictly towards the basic types. It does not use Go’s reflect package for code clarity reason. They are:
- int, int8, int16, int32, int64
- uint, uint8, uint16, uint32, uint64
- float32, float64
- bool
- []byte, *[]byte
- string
If you need to support some custom definition type, you need to convert it on your own. Any unsupported data types will be ignored in the conversion steps.
Important Note: You need to supply these data types' variable pointer into Flag’s Value element. Example, to support variable a that is int type, you fill in the Flag’s Value as &a instead. Here is an example: var a int f := Flag { … Value: &a, … }
UNSUPPORTED DATA TYPES
These are the data types that were confirmed not to be supported to keep the package sane to use. They are:
- any forms of array
- any forms of maps
Rationale: It is hard to track all permutations and combinations without using reflect package. Also, each time when array or maps occurs, it is use-case specific and can’t be generalized without complicated algorithms.
Hence, for these cases, user is advised to parse the entire list as string and then perform the splitting on your side.
Example
ackage args
import (
"fmt"
)
type exampleMyConfig struct {
actionstring
aint
bint
}
func (c *exampleMyConfig) Add() int {
return c.a + c.b
}
func Example() {
var err error
// ...you have your own configuration variables...
c := exampleMyConfig{}
// 1. create a manager
m := NewManager()
m.Name = "My Program Title"
m.Description = `
This is a long single paragraph description about the program. You can write
it this way using Go's raw string. Unicode is supported.
`
m.Version = "0.2.0"
m.Examples = []string{"",
"call for help: $ ./program --help",
"set A : $ ./prgoram --set-a 123",
"set B : $ ./program --set-b 123",
}
m.ShowFlagExamples = true
// 2. add your flags accordingly
err = m.Add(&Flag{
Name:"help",
Label:[]string{"-h", "--help", "help"},
Value:&c.action,
Help:"to print help",
HelpExamples: []string{"",
"$ ./program -h",
"$ ./program --help",
"$ ./program help",
},
})
if err != nil {
// handle error
return
}
err = m.Add(&Flag{
Name:"set A",
Label:[]string{"-sa", "--set-a"},
Value:&c.a,
Help:"to add",
HelpExamples: []string{"",
"$ ./program -sa 123",
"$ ./program --set-a 123",
},
})
if err != nil {
// handle error
return
}
err = m.Add(&Flag{
Name:"set B",
Label:[]string{"-sb", "--set-b"},
Value:&c.b,
Help:"to add",
HelpExamples: []string{"",
"$ ./program -sb 123",
"$ ./program --set-b 123",
},
})
if err != nil {
// handle error
return
}
// 3. parse the flags
m.Parse()
// 4. execute based on your configs
switch c.action {
case "-h":
fallthrough
case "--help":
fallthrough
case "help":
// 5. generate help output from config
help := m.PrintHelp()
fmt.Printf("%s", help)
default:
fmt.Printf("total: %v\n", c.Add())
}
}
// Output CLI:
//
// u0:gosandbox$ ./main help
// MY PROGRAM TITLE (0.2.0)
// ββββββββββββββββββββββββ
// This is a long single paragraph description about the program. You can write
// it this way using Go's raw string. Unicode is supported.
//
//
// USAGES
// ββββββ
// 1) call for help: $ ./program --help
// 2) set A : $ ./prgoram --set-a 123
// 3) set B : $ ./program --set-b 123
//
//
// ARGUMENTS
// βββββββββ
// -h, --help, help to print help
// EXAMPLES
// 1) $ ./program -h
// 2) $ ./program --help
// 3) $ ./program help
//
// -sa, --set-a to add
// EXAMPLES
// 1) $ ./program -sa 123
// 2) $ ./program --set-a 123
//
// -sb, --set-b to add
// EXAMPLES
// 1) $ ./program -sb 123
// 2) $ ./program --set-b 123
// u0:gosandbox$
// u0:gosandbox$ ./main -sa 43 -sb 123
// total: 166
// u0:gosandbox$
Constants
const (
// ErrorMissingFlag is the error message for missing flag
// object
ErrorMissingFlag = "missing flag"
// ErrorConflictedFlag is the error message for flag with
// conflicted labels
ErrorConflictedFlag = "detected conflicted label"
)
Flag
type Flag struct {
Name string
Label []string
ValueLabel string
Value interface{}
Help string
HelpExamples []string
DisableHelp bool
ExampleLabel string
// contains filtered or unexported fields
}
Flag is the data structure for each of the argument types. It is safe to create using the conventional structure{} method. Flag needs the following minimum elements to work properly.
- Name
- Label
- Value
- Help
Once done, you can use the Manager’s Add(…) function to register the Flag object. If you encounter panics, usually that means there is a critical issue (e.g. conflicted Label) requires your attention.
ELEMENTS SPECIFICATIONS
- Name
Name is the element strictly for internal reference only. This is for code developers to reference or to search a particular flag based on the name without going through the Label slices.
This is compulsory to fill in.
- Label
These are the argument “flags” (e.g. -h, –help, help) saved in a string slice. A flag is only specific to one purpose but has the ability to offer different styles of inputs.
This is compulsory to fill in.
- ValueLabel
This is for labeling the value part of the value-taking arguments (e.g. –add [ VALUE ]). It only affects printing help statement and not the parsing algorithms. Example:
- If set to “number”, the help printout would be: “-h, –help, help [ NUMBER ]”
- If set to empty (""), the help printout would be: “-h, –help, help”
- If set to “εε”, the help printout would be: “-h, –help, help [ εε ]”
This is optional to fill in.
- Value
This is the variable pointer field for Flag to parse the results into. The value for this field MUST be a supported data types (see SUPPORTED DATA TYPES section) variable pointer. Otherwise, the parsed value will be discarded.
Passing a full variable (not a pointer) will not work for this field.
This is compulsory to fill in.
- Help
The argument help description. This single paragraph string holds the short explainations about the flag / arguments (usually printed to the right).
This package uses a word-wrap algorithm to style the output. Hence, if you pass a multi-paragraphs (are you mad?) string into this field, it will be wrapped into a single paragraph instead.
This is compulsory to fill in.
- Help Examples
This is for printing examples of use for the flag / arguments. It is meant for printing help statement. It is a string slice so you can supply as many as you want. Flag does automatic numbering so you do not need to do it manually. If the list is empty, it is treated as no examples. Example:
CASE 1 - If set to:
[]string{} OR nil
The argument help output would be:
-a, --append [ VALUE ] to append a round number into the
inputs. This can be a very long value
and can be a very long description.
CASE 2 - If set to:
[]string{"$ ./program -a 123",
"$ ./program --append 123",
"$ ./program -append '123'",
}
The argument help output would be:
-a, --append [ VALUE ] to append a round number into the
inputs. This can be a very long value
and can be a very long description.
EXAMPLES
1) $ ./program -a 123
2) $ ./program --append 123
3) $ ./program -append '123'
This is optional to fill in.
- DisableHelp
This is a switch to tell the manager to discard the printout for this flag while processng the arguments help output. The default is false (off).
This is optional to fill in.
- ExampleLabel
This is the string that alters the “EXAMPLES” text for the HelpExamples. It is offered explicitly to facilitate i18n. By default, it uses English word “Examples”.
This is optional to fill in.
Manager
type Manager struct {
// program metadata
Name string
Description string
Version interface{}
Examples []string
ShowFlagExamples bool
// label texts for i18n
ArgumentLabel string
UsageLabel string
// contains filtered or unexported fields
}
Manager is the core arguments structure that holds all the flags and processes them accordingly.
This structure contains important private data elements so use NewManager() function to create one instead of the conventional structure{} method. Without doing so can cause unforseenable fatal error or panics.
ELEMENTS SPECIFICATIONS
- Name
Name is the program name where the field is used to print the overall help output in PrintHelp(…) function.
This is compulsory to fill in.
- Description
Description is a short explanation (limit it to 1 short paragraph) explaining the program. It is used to print the overall help output in PrintHelp(…) function. Unicode is supported.
This is compulsory to fill in.
- Version
Version is the version number of the program usually in the form of string or number types used to print the overall help output in PrintHelp(…) function.
This is optional to fill in.
- Examples
This is the “how-to” examples for using the program. It is a string slice offering the program “usage”, allowing users to quickly learn to use. Manager does automatic numbering so you do not need to do it manually. If the list is empty, it is treated as no examples. Example: CASE 1 - If set to: []string{} OR nil The argument help output would be: MY PROGRAM (0.2.0) ββββββββββββββββββ η»΄ζ€εθ²ι»θ²θεζΆεθθΏζ―θ―θ―η»΄ζ€εθ²ι»θ²θεζΆεθθΏζ―θ― θθΏζ―θ― θ―η»΄ζ€εθ² ι»θ²θε ζΆεθ θΏζ―θ―θ― η»΄ζ€ε ι»θ²θεζΆεθθΏ ζ―θ―θ―η»΄ζ€εθ²ι» θ²θ
ARGUMENTS
βββββββββ
...
CASE 2 - If set to:
[]string{"",
"$ ./program --help",
"$ ./program --list",
}
The argument help output would be:
MY PROGRAM (0.2.0)
ββββββββββββββββββ
η»΄ζ€εθ²ι»θ²θεζΆεθθΏζ―θ―θ―η»΄ζ€εθ²ι»θ²θεζΆεθθΏζ―θ―
θθΏζ―θ― θ―η»΄ζ€εθ² ι»θ²θε ζΆεθ θΏζ―θ―θ― η»΄ζ€ε
ι»θ²θεζΆεθθΏ ζ―θ―θ―η»΄ζ€εθ²ι» θ²θ
USAGES
ββββββ
1) $ ./program --help
2) $ ./program --list
ARGUMENTS
βββββββββ
...
This is optional to fill in.
- ShowFlagExamples
This is the master switch to show all flag respective examples. By default, it is false (off).
This is optional to fill in.
- ArgumentLabel
This is the string that alters the ARGUMENT title in the help printout. It is offered explicitly to facilitate i18n. By default, it uses English word “ARGUMENTS”.
This is optional to fill in.
- UsageLabel
This is the string that alters the USAGE title in the help printout. It is offered explicitly to facilitate i18n. By default, it uses English word “USAGES”.
Func NewManager() *Manager
NewManager creates and initializes the Manager structure ready for use.
Func (m *Manager) Add(f *Flag) error
Add takes a Flag object and registers into the manager.
It returns:
- nil - successful register
- err - error occurred (e.g. missing flag)
- panic - critical error requires upfront attention (e.g. conflicted labels)
Func (m *Manager) Parse()
Parse starts the argument parsing process.
Func (m *Manager) PrintHelp() (out string)
PrintHelp creates the help menu based on the given flags and manager’s data. It will output the final formatted string with help contents ready for printout.
It returns:
- string - the help statement