项目作者: xitonix

项目描述 :
Command line flags library
高级语言: Go
项目地址: git://github.com/xitonix/flags.git
创建时间: 2019-05-07T23:22:50Z
项目社区:https://github.com/xitonix/flags

开源协议:Apache License 2.0

下载


GitHub tag (latest SemVer pre-release)
GoDoc
Go Report Card
Build Status
codecov

Flags

Package flags is a POSIX/GNU compliant flags library providing a simple, yet fully flexible API to manage command line arguments.

The value of each flag can be provided by different sources. Two built-in value providers are command line argument and environment variable sources, with the former at the beginning of the chain, meaning the values parsed by the command line argument source will override the values provided by environment variables. The package also provides the API to add new custom sources to the chain with a desired priority. For example, you may have your own implementation of the Source interface to read from a YAML or JSON file.

The API is packed with a full set of standard built-in flag types, from int to IP address and many more. But you can also build a flag for your custom types and ask the library to pass them through the processing pipeline, the same way it treats the pre-built flags.

NOTE

The pre-release API may still be subject to breaking changes.

Features

  • Fully tested with 3K+ unit tests
  • Built-in flag types

    • bool and []bool
    • byte
    • CIDR and []CIDR
    • Counter
    • Duration and []Duration
    • Datetime/Date/Timestamp
    • float32/float64/[]float64
    • int/int8/int16/int32/int64/[]int
    • IP address and []IP
    • string and []string
    • map[string]string
    • uint/uint8/uint16/uint32/uint64/[]uint
    • verbosity
  • Ability to mark the flags as Hidden, Deprecated and Required

  • Pre-built command line argument and environment variable sources

  • Automatic key generation (For environment variables and other custom sources)

  • Flag value validation through callbacks and providing a list of acceptable values

  • API extendability to read the flag values from custom sources

  • Fully customisable help formatter

  • Built-in predicates to control the order in which the flags will be printed in the help output

    • Long name (ASC/DESC)
    • Short name (ASC/DESC)
    • Key (ASC/DESC)
    • Usage (ASC/DESC)
    • Sort by Required
    • Sort by Deprecated
  • Ability to register your own Comparer to gain full control over the sorting behaviour

  • Support for the following command line argument formats:

  1. # Boolean flags
  2. --bool --bool=true --bool=false --bool=1 --bool=0
  3. -b -b=true -b=false -b=1 -b=0
  4. # Numeric flags (Integers or floating point numbers)
  5. --num=[+/-]10
  6. --num [+/-]10
  7. -n=[+/-]10
  8. -n [+/-]10
  9. -n[+/-]10
  10. # Mixed short forms
  11. -n[+/-]10m # result: n=+/-10, m=0
  12. -n[+/-]10m[+/-]20 # result: n=+/-10, m=+/-20
  13. -n[+/-]10m [+/-]20 # result: n=+/-10, m=+/-20
  14. # Non numeric flags
  15. --key="value" --key "value" --key value
  16. -k="value" -k "value" -k value

Installation

  1. go get github.com/xitonix/flags

Usage

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/xitonix/flags"
  6. "github.com/xitonix/flags/by"
  7. )
  8. func main() {
  9. // Enabling auto key generation
  10. flags.EnableAutoKeyGeneration()
  11. // You can optionally set a prefix for all the automatically generated
  12. // or explicitly defined flag keys.
  13. flags.SetKeyPrefix("PFX")
  14. // Customising the indicator for deprecated and required flags.
  15. // The markers will be used in the help output to draw the users' attention
  16. flags.SetDeprecationMark("**DEPRECATED**")
  17. flags.SetRequiredFlagMark("**")
  18. // Changing the sort order.
  19. // You can use pre-built sort predicates or pass your own Comparer to change the
  20. // order in which the flags will be printed in the help output.
  21. flags.SetSortOrder(by.LongNameDescending)
  22. // Each flag must have a mandatory long form (ie. --file-path) and
  23. // an OPTIONAL short form (i.e. -F)
  24. port := flags.Int("port-number", "Port number").WithShort("p")
  25. // You can ask the package to set the flag to the specified default value whenever
  26. // it's not explicitly provided by any available Sources.
  27. // You may also use the Var() function with each flag to access the pointer to
  28. // the underlying variable instead of calling the Get() function to read the falg value.
  29. log := flags.String("log-file", "The path to the log file").WithDefault("/var/log/service.log").Var()
  30. // You have full control over the acceptable values for each flag. You can either provide
  31. // a list of allowed values using WithValidRange method:
  32. weekend := flags.StringSlice("weekends", "Weekends").WithValidRange(true, "Sat, Sun")
  33. // or set a fully customisable validator using WithValidationCallback method:
  34. numRange := flags.Int8("number", "A flag with validation callback").
  35. WithValidationCallback(func(in int8) error {
  36. if in > 10 {
  37. return errors.New("--number must be less than 10")
  38. }
  39. return nil
  40. })
  41. // CIDR and IP address
  42. net := flags.CIDR("network", "Network definition. Example 192.168.1.1/16")
  43. endpoint := flags.IPAddress("endpoint", "The IP address of the remote server")
  44. // Deprecated flags will be marked in the help output
  45. // using a customisable indicator to draw user's attention
  46. _ = flags.Int("port", "Legacy port number. Use -p, --port-number instead").MarkAsDeprecated()
  47. // Required flags will be marked in the help output
  48. // using a customisable indicator to draw user's attention.
  49. // The user must explicitly provide value for a required flag.
  50. // Setting the default value of required flags will have zero effect.
  51. rate := flags.Float64("rate", "Conversion rate").Required()
  52. // Hidden flags will not be displayed in the help output.
  53. hidden := flags.Bool("enable-logging", "Secret flag").Hide()
  54. // You can explicitly define the key for each flag. These keys will override
  55. // their automatically generated counterparts.
  56. t := flags.Time("start-time", "Start time").WithKey("START")
  57. ttl := flags.Duration("ttl", "Time to live")
  58. // The value of Counter flags can be increased by repeating the short or the long form
  59. // for example -cc --counter --counter will the the counter flag to 4.
  60. counter := flags.Counter("counter", "Repeat counter")
  61. // Verbosity is an alias for Counter("verbose", "usage").WithShort("v")
  62. verbose := flags.Verbosity("Verbosity. Repeat -v for higher verbosity levels. Example -vv")
  63. // This callback function will be called before the flag value is being set by a source.
  64. preCallback := func(flag core.Flag, value string) error {
  65. fmt.Printf("%s will be set to %s\n", flag.LongName(), value)
  66. return nil
  67. }
  68. // This callback function will be called after the flag value has been set by a source.
  69. // postCallback will not get called if preCallback returns an error.
  70. postCallback := func(flag core.Flag, value string) error {
  71. fmt.Printf("%s has been set to %s\n", flag.LongName(), value)
  72. return nil
  73. }
  74. flags.SetPreSetCallback(preCallback)
  75. flags.SetPostSetCallback(postCallback)
  76. flags.Parse()
  77. // You can read the flag value by calling the Get() method
  78. fmt.Println("Port", port.Get())
  79. // or accessing the underlying pointer if Var() is used when creating the flag
  80. fmt.Println("Log", *log)
  81. fmt.Println("Weekend", weekend.Get())
  82. fmt.Println("Network", net.Get())
  83. fmt.Println("Endpoint", endpoint.Get())
  84. fmt.Println("Rate", rate.Get())
  85. fmt.Println("Hidden", hidden.Get())
  86. fmt.Println("Range", numRange.Get())
  87. fmt.Println("Time", t.Get())
  88. fmt.Println("TTL", ttl.Get())
  89. fmt.Println("Counter", counter.Get())
  90. fmt.Println("Verbosity", verbose.Get())
  91. // It's possible to navigate through all the registered flags
  92. for _, flag := range flags.DefaultBucket.Flags() {
  93. fmt.Printf("--%s (%s) %s\n", flag.LongName(), flag.Type(), flag.Usage())
  94. }
  95. }