envconfig icon indicating copy to clipboard operation
envconfig copied to clipboard

Feature Request: Make usage available in machine processable format

Open neumantm opened this issue 3 years ago • 0 comments

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

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
}

neumantm avatar Jul 31 '22 13:07 neumantm