diff options
author | Marc A. Paradise <marc.paradise@gmail.com> | 2019-06-04 16:04:11 -0400 |
---|---|---|
committer | Marc A. Paradise <marc.paradise@gmail.com> | 2019-06-06 12:50:47 -0400 |
commit | 145ba5f6cdccbb0775d5a65885b80705bc9fa87a (patch) | |
tree | 9826e068d6c14965dccd67406fbd656700b205d6 /README.md | |
parent | ae6e7e581520f81e048267f73d3ce43402886ba5 (diff) | |
download | mixlib-cli-145ba5f6cdccbb0775d5a65885b80705bc9fa87a.tar.gz |
[MIXLIB-CLI-63] Add deprecated_option support
This commit adds deprecated option support by exposing a
new ClassMethod, `deprecated_option`. It will generate a
corresponding deprecated option, and if that option is used it will
handle mapping of the old option to the new and issue a warning.
`deprecated_option` accepts a subset of the parameters that `option` accepts.
Most importantly, a deprecated option can't have a default value.
There's a practical reason for this and a philosophical one.
Practically, it makes it easy to track the situation where someone has
set `use_separate_defaults` to `false`. In that case, we currently
can't tell whether the user provided the flag, or it was set as a default.
This could have been addressed, but:
Philosphically it makes more sense to not have a default value on a
deprecated item. If it's deprecated, you want people to stop using it.
If it has a default, it's effectively forced in-use at all times.
See function docs for further accepted parameters.
To allow deprecated options without warnings, use parse_options as
`parse_options(ARGV, show_deprecations: false)`. By default, warnings
will be shown.
This also moves some formatting code into its own class -
it was causing methods to get mixed in that client classes didn't
need; and I reached the point where I needed to access the formatting
functions across methods in both Mixlib::CLI and
Mixlib::CLI::ClassMethods. It made more sense to move them outside of
the mixed-in bits, since it wasn't a concern of the caller that would be
inheriting those methods.
Signed-off-by: Marc A. Paradise <marc.paradise@gmail.com>
Diffstat (limited to 'README.md')
-rw-r--r-- | README.md | 134 |
1 files changed, 120 insertions, 14 deletions
@@ -73,19 +73,8 @@ c.run MyConfig[:log_level] # :debug ``` -Available arguments to 'option': - -- `:short`: The short option, just like from optparse. Example: "-l LEVEL" -- `:long`: The long option, just like from optparse. Example: "--level LEVEL" -- `:description`: The description for this item, just like from optparse. -- `:default`: A default value for this option -- `:required`: Prints a message informing the user of the missing requirement, and exits. Default is false. -- `:on`: Set to :tail to appear at the end, or `:head`: to appear at the top. -- `:boolean:`: If this option takes no arguments, set this to true. -- `:show_options`: If you want the option list printed when this option is called, set this to true. -- `:exit`: Exit your program with the exit code when this option is specified. Example: 0 -- `:proc`: If set, the configuration value will be set to the return value of this proc. -- `:in`: An array containing the list of accepted values +For supported arguments to `option`, see the function documentation in [lib/mixlib/cli.rb](lib/mixlib/cli.rb). + If you need access to the leftover options that aren't captured in the config, you can get at them through +cli_arguments+ (referring to the above definition of MyCLI). @@ -96,14 +85,131 @@ cli.parse_options cli.cli_arguments # [ 'file1', 'file2', 'file3' ] ``` +## Deprecating CLI Options + +mixlib-cli 2.1.0 and later supports declaring options as deprecated. Using a deprecated option +will result in a warning message being displayed. If a deprecated flag is supplied, +its value is assigned to the replacement flag. You can control this assignment by specifying a +`value_mapper` function in the arguments (see example below, and function docs) + + +Usage notes (see docs for arguments to `Mixlib::CLI::ClassMethods#deprecated_option` for more): + + * Define deprecated items last, after all non-deprecated items have been defined. + You will see errors if your deprecated item references a `replacement` that hasn't been defined yet. + * deprecated\_option only takes a subset of 'option' configuration. You can only specify `short`, `long` - these should + map to the short/long values of the option from before its deprecation. + * item description will automatically be generated along the lines of "-f/--flag is deprecated. Use -n/--new-flag instead." + * if the `replacement` argument is not given, item description will look like "-f/--flag is deprecated and will be removed in a future release" + +### Example + +Given the following example: + +```ruby + +# mycli.rb + +class MyCLI + include Mixlib::CLI + + + option :arg_not_required, + description: "This takes no argument.", + long: "--arg-not-required", + short: "-n" + + option :arg_required, + description: "This takes an argument.", + long: "--arg-required ARG", + short: "-a", + in: ["a", "b", "c"] + + deprecated_option :dep_one, + short: "-1", + long: "--dep-one", + # this deprecated option maps to the '--arg-not-required' option: + replacement: :arg_not_required, + # Do not keep 'dep_one' in `config` after parsing. + keep: false + + deprecated_option :dep_two, + short: "-2", + long: "--dep-two ARG", + replacement: :arg_required, + # will map the given value to a valid value for `--arg-required`. + value_mapper: Proc.new { |arg| + case arg + when "q"; "invalid" # We'll use this to show validation still works + when "z"; "a" + when "x"; "b" + else + "c" + end + } + +end + +c = MyCLI.new() +c.parse_options + +puts "arg_required: #{c.config[:arg_required]}" if c.config.key? :arg_required +puts "arg_not_required: #{c.config[:arg_not_required]}" if c.config.key? :arg_not_required +puts "dep_one: #{c.config[:dep_one]}" if c.config.key? :dep_one +puts "dep_two: #{c.config[:dep_two]}" if c.config.key? :dep_two + +``` + +In this example, --dep-one will be used. Note that dep_one will not have a value of its own in +`options` because `keep: false` was given to the deprecated option. + +```bash + +$ ruby mycli.rb --dep-one + +-1/--dep-one: This flag is deprecated. Use -n/--arg-not-required instead +arg_not_required: true + +``` + +In this example, the value provided to dep-two will be converted to a value +that --arg-required will accept,a nd populate `:arg\_required` with + +```bash + +$ ruby mycli.rb --dep-two z # 'q' maps to 'invalid' in the value_mapper proc above + +-2/--dep-two: This flag is deprecated. Use -a/--arg-required instead. + +arg_required: a # The value is mapped to its replacement using the function provided. +dep_two: z # the deprected value is kept by default +``` + +In this example, the value provided to dep-two will be converted to a value +that --arg-required will reject, showing how content rules are applied even when +the input is coming from a deprecated option: + +```bash +$ ruby mycli.rb --dep-two q + +-2/--dep-two: This flag is deprecated. Use -a/--arg-required instead. +-a/--arg-required: invalid is not one of the allowed values: 'a', 'b', or 'c' + +``` ## Documentation -All documentation is written using YARD. You can generate a by running: +Class and module documentation is maintained using YARD. You can generate it by running: ``` rake docs ``` +You can serve them locally with live refresh using: + +``` +bundle exec yard server --reload +``` + ## Contributing For information on contributing to this project please see our [Contributing Documentation](https://github.com/chef/chef/blob/master/CONTRIBUTING.md) |