Module: Mixlib::CLI

Defined in:
lib/mixlib/cli.rb,
lib/mixlib/cli/version.rb

Overview

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, and ClassMethods#banner, which defines the “usage” banner.

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.

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

VERSION =
"1.3.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

Banner for the option parser. If the option parser is printed, e.g., by ‘puts opt_parser`, this string will be used as the first line.



133
134
135
# File 'lib/mixlib/cli.rb', line 133

def banner
  @banner
end

#configObject

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.



121
122
123
# File 'lib/mixlib/cli.rb', line 121

def config
  @config
end

#default_configObject

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.



129
130
131
# File 'lib/mixlib/cli.rb', line 129

def default_config
  @default_config
end

#opt_parserObject

The option parser generated from the mixlib-cli DSL. Set to nil on initialize; when #parse_options is called opt_parser is set to an instance of OptionParser. opt_parser can be used to print a help message including the banner and any CLI options via ‘puts opt_parser`.



139
140
141
# File 'lib/mixlib/cli.rb', line 139

def opt_parser
  @opt_parser
end

#optionsObject

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.



108
109
110
# File 'lib/mixlib/cli.rb', line 108

def options
  @options
end

Class Method Details

.included(receiver) ⇒ Object



256
257
258
# File 'lib/mixlib/cli.rb', line 256

def self.included(receiver)
  receiver.extend(Mixlib::CLI::ClassMethods)
end

Instance Method Details

#build_option_arguments(opt_setting) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/mixlib/cli.rb', line 241

def build_option_arguments(opt_setting)
  arguments = Array.new

  arguments << opt_setting[:short] if opt_setting.has_key?(:short)
  arguments << opt_setting[:long] if opt_setting.has_key?(:long)

  if opt_setting.has_key?(:description)
    description = opt_setting[:description]
    description << " (required)" if opt_setting[:required]
    arguments << description
  end

  arguments
end

#initialize(*args) ⇒ Object

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 :)



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/mixlib/cli.rb', line 148

def initialize(*args)
  @options = Hash.new
  @config  = Hash.new
  @default_config = Hash.new
  @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

    if config_opts.has_key?(:default)
      defaults_container[config_key] = config_opts[:default]
    end
  end

  super(*args)
end

#parse_options(argv = ARGV) ⇒ Object

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.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/mixlib/cli.rb', line 192

def parse_options(argv=ARGV)
  argv = argv.dup
  @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] = (opt_val[:proc] && opt_val[:proc].call(c)) || c
          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
  @opt_parser.parse!(argv)

  # Deal with any required values
  options.each do |opt_key, opt_value|
    if opt_value[:required] && !config.has_key?(opt_key)
      reqarg = opt_value[:short] || opt_value[:long]
      puts "You must supply #{reqarg}!"
      puts @opt_parser
      exit 2
    end
  end

  argv
end