module Mixlib::CLI
Mixlib::CLI
¶ ↑
Adds a DSL for defining command line options and methods for parsing those options to the including class.
Mixlib::CLI
does some setup in initialize, so the including class must call `super()` if it defines a custom initializer.
DSL¶ ↑
When included, Mixlib::CLI
also extends the including class with its ClassMethods
, which define the DSL. The primary methods of the DSL are ClassMethods#option
, which defines a command line option; ClassMethods#banner
, which defines the “usage” banner; and ClassMethods#deprecated_option
, which defines a deprecated command-line option.
Parsing¶ ↑
Command line options are parsed by calling the instance method parse_options
. After calling this method, the attribute config
will contain a hash of `:option_name => value` pairs.
Constants
- VERSION
Attributes
Any arguments which were not parsed and placed in “config”–the leftovers.
A Hash containing the values supplied by command line options.
The behavior and contents of this Hash vary depending on whether ClassMethods#use_separate_default_options
is enabled.
use_separate_default_options disabled¶ ↑
After initialization, config
will contain any default values defined via the mixlib-config DSL. When parse_options
is called, user-supplied values (from ARGV) will be merged in.
use_separate_default_options enabled¶ ↑
After initialization, this will be an empty hash. When parse_options
is called, config
is populated only with user-supplied values.
If ClassMethods#use_separate_default_options
is enabled, this will be a Hash containing key value pairs of `:option_name => default_value` (populated during object initialization).
If use_separate_default_options is disabled, it will always be an empty hash.
Gives the command line options definition as configured in the DSL. These are used by parse_options
to generate the option parsing code. To get the values supplied by the user, see config
.
Public Class Methods
# File lib/mixlib/cli.rb, line 448 def self.included(receiver) receiver.extend(Mixlib::CLI::ClassMethods) receiver.extend(Mixlib::CLI::InheritMethods) end
Create a new Mixlib::CLI
class. If you override this, make sure you call super!
Parameters¶ ↑
- *args<Array>
-
The array of arguments passed to the initializer
Returns¶ ↑
- object<Mixlib::Config>
-
Returns an instance of whatever you wanted :)
# File lib/mixlib/cli.rb, line 260 def initialize(*args) @options = {} @config = {} @default_config = {} @opt_parser = nil # Set the banner @banner = self.class.banner # Dupe the class options for this instance klass_options = self.class.options klass_options.keys.inject(@options) { |memo, key| memo[key] = klass_options[key].dup; memo } # If use_separate_defaults? is on, default values go in @default_config defaults_container = if self.class.use_separate_defaults? @default_config else @config end # Set the default configuration values for this instance @options.each do |config_key, config_opts| config_opts[:on] ||= :on config_opts[:boolean] ||= false config_opts[:required] ||= false config_opts[:proc] ||= nil config_opts[:show_options] ||= false config_opts[:exit] ||= nil config_opts[:in] ||= nil if config_opts.key?(:default) defaults_container[config_key] = config_opts[:default] end end super(*args) end
Public Instance Methods
# File lib/mixlib/cli.rb, line 432 def build_option_arguments(opt_setting) arguments = [] arguments << opt_setting[:short] if opt_setting[:short] arguments << opt_setting[:long] if opt_setting[:long] if opt_setting.key?(:description) description = opt_setting[:description].dup description << " (required)" if opt_setting[:required] description << " (valid options: #{Formatter.friendly_opt_list(opt_setting[:in])})" if opt_setting[:in] opt_setting[:description] = description arguments << description end arguments end
Iterates through options declared as deprecated, maps values to their replacement options, and prints deprecation warnings.
@return NilClass
# File lib/mixlib/cli.rb, line 394 def handle_deprecated_options(show_deprecations) merge_in_values = {} config.each_key do |opt_key| opt_cfg = options[opt_key] # Deprecated entries do not have defaults so no matter what # separate_default_options are set, if we see a 'config' # entry that contains a deprecated indicator, then the option was # explicitly provided by the caller. # # opt_cfg may not exist if an inheriting application # has directly inserted values info config. next unless opt_cfg && opt_cfg[:deprecated] replacement_key = opt_cfg[:replacement] if replacement_key # This is the value passed into the deprecated flag. We'll use # the declared value mapper (defaults to return the same value if caller hasn't # provided a mapper). deprecated_val = config[opt_key] # We can't modify 'config' since we're iterating it, apply updates # at the end. merge_in_values[replacement_key] = opt_cfg[:value_mapper].call(deprecated_val) config.delete(opt_key) unless opt_cfg[:keep] end # Warn about the deprecation. if show_deprecations # Description is also the deprecation message. display_name = CLI::Formatter.combined_option_display_name(opt_cfg[:short], opt_cfg[:long]) puts "#{display_name}: #{opt_cfg[:description]}" end end config.merge!(merge_in_values) nil end
The option parser generated from the mixlib-cli DSL. opt_parser
can be used to print a help message including the banner and any CLI
options via `puts opt_parser
`.
Returns¶ ↑
opt_parser
<OptionParser>-
The option parser object.
# File lib/mixlib/cli.rb, line 344 def opt_parser @opt_parser ||= OptionParser.new do |opts| # Set the banner opts.banner = banner # Create new options options.sort { |a, b| a[0].to_s <=> b[0].to_s }.each do |opt_key, opt_val| opt_args = build_option_arguments(opt_val) opt_method = case opt_val[:on] when :on :on when :tail :on_tail when :head :on_head else raise ArgumentError, "You must pass :on, :tail, or :head to :on" end parse_block = Proc.new do |c| config[opt_key] = if opt_val[:proc] if opt_val[:proc].arity == 2 # New hotness to allow for reducer-style procs. opt_val[:proc].call(c, config[opt_key]) else # Older single-argument proc. opt_val[:proc].call(c) end else # No proc. c end puts opts if opt_val[:show_options] exit opt_val[:exit] if opt_val[:exit] end full_opt = [ opt_method ] opt_args.inject(full_opt) { |memo, arg| memo << arg; memo } full_opt << parse_block opts.send(*full_opt) end end end
Parses an array, by default ARGV, for command line options (as configured at the class level).
Parameters¶ ↑
- argv<Array>
-
The array of arguments to parse; defaults to ARGV
Returns¶ ↑
- argv<Array>
-
Returns any un-parsed elements.
# File lib/mixlib/cli.rb, line 304 def parse_options(argv = ARGV, show_deprecations: true) argv = argv.dup opt_parser.parse!(argv) # Do this before our custom validations, so that custom # validations apply to any converted deprecation values; # but after parse! so that everything is populated. handle_deprecated_options(show_deprecations) # Deal with any required values options.each do |opt_key, opt_config| if opt_config[:required] && !config.key?(opt_key) reqarg = opt_config[:short] || opt_config[:long] puts "You must supply #{reqarg}!" puts @opt_parser exit 2 end if opt_config[:in] unless opt_config[:in].is_a?(Array) raise(ArgumentError, "Options config key :in must receive an Array") end if config[opt_key] && !opt_config[:in].include?(config[opt_key]) reqarg = Formatter.combined_option_display_name(opt_config[:short], opt_config[:long]) puts "#{reqarg}: #{config[opt_key]} is not one of the allowed values: #{Formatter.friendly_opt_list(opt_config[:in])}" # TODO - get rid of this. nobody wants to be spammed with a ton of information, particularly since we just told them the exact problem and how to fix it. puts @opt_parser exit 2 end end end @cli_arguments = argv argv end