envconfig
envconfig copied to clipboard
Feature Request: Make usage available in machine processable format
Feature
This goes into a very similar direction as #97. I would like to be able to get the usage info in form that can easily be processes by other parts of my program.
Reasons
I think it is a good idea to give developers more control how to inform the user about usage information. I can think of the following scenarios that currently are hard to implement:
- Showing the usage information in some sort of graphical user interface (native or web)
- Logging the usage information through an existing logging framework
- This might be favorable because
- The logging framework might apply specific formatting that is hard/tedious to replicate with a template
- The logging output location, format, etc. might be user-configurable. Replicating the effect of these options for envconfig would most likely not make sense from a maintainability point of view
- This might be favorable because
Workaround
Currently I use a template which outputs the usage information as JSON, which can then be parsed again. But this is a really hacky solution requiring additional code, which would be unnecessary if envconfig had a way to get this info directly.
For anyone who might have a similar problem: Here is my code to do that:
// Variable describes one possible environment variable
type Variable struct {
Name string `json:"name"`
Type string `json:"type"`
Default string `json:"default"`
Required bool `json:"required"`
Description string `json:"description"`
}
// usageFormat is used by getUsage to print the usage info from envconfig as a json
const usageFormat = `{{ define "dec" }}{{ len (slice (printf "%*s" . "") 1) }}{{ end -}}
{{$length := len . -}}
[
{{range $idx, $val := .}} {
"name": "{{usage_key $val}}",
"type": "{{usage_type $val}}",
"default": "{{usage_default $val}}",
"required": {{if usage_required $val -}} true {{- else -}} false {{- end}},
"description": "{{usage_description $val}}"
}{{if not (eq $idx (len (slice (printf "%*s" $length "") 1)))}},{{end}}{{/* If not last element print comma */}}
{{end}}]
`
// getUsage gets the usage information from envconfig, parses it and returns it as a array of Variables
func getUsage(config interface{}) ([]Variable, error) {
var buff bytes.Buffer
var vars []Variable
if err := envconfig.Usagef(PREFIX, config, io.Writer(&buff), usageFormat); err != nil {
return vars, errors.New(err)
}
if err := json.Unmarshal(buff.Bytes(), &vars); err != nil {
return vars, errors.New(err)
}
return vars, nil
}