mixlib-cli 1.2.2 → 1.3.0.rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- require 'rake/gempackagetask'
2
+ require 'rubygems/package_task'
3
3
  require 'rspec/core/rake_task'
4
4
  require 'rdoc/task'
5
5
 
@@ -12,7 +12,7 @@ end
12
12
 
13
13
  gem_spec = eval(File.read("mixlib-cli.gemspec"))
14
14
 
15
- Rake::GemPackageTask.new(gem_spec) do |pkg|
15
+ Gem::PackageTask.new(gem_spec) do |pkg|
16
16
  pkg.gem_spec = gem_spec
17
17
  end
18
18
 
@@ -6,9 +6,9 @@
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
8
8
  # You may obtain a copy of the License at
9
- #
9
+ #
10
10
  # http://www.apache.org/licenses/LICENSE-2.0
11
- #
11
+ #
12
12
  # Unless required by applicable law or agreed to in writing, software
13
13
  # distributed under the License is distributed on an "AS IS" BASIS,
14
14
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -19,8 +19,37 @@
19
19
  require 'optparse'
20
20
 
21
21
  module Mixlib
22
+
23
+ # == Mixlib::CLI
24
+ # Adds a DSL for defining command line options and methods for parsing those
25
+ # options to the including class.
26
+ #
27
+ # Mixlib::CLI does some setup in #initialize, so the including class must
28
+ # call `super()` if it defines a custom initializer.
29
+ #
30
+ # === DSL
31
+ # When included, Mixlib::CLI also extends the including class with its
32
+ # ClassMethods, which define the DSL. The primary methods of the DSL are
33
+ # ClassMethods#option, which defines a command line option, and
34
+ # ClassMethods#banner, which defines the "usage" banner.
35
+ #
36
+ # === Parsing
37
+ # Command line options are parsed by calling the instance method
38
+ # #parse_options. After calling this method, the attribute #config will
39
+ # contain a hash of `:option_name => value` pairs.
22
40
  module CLI
23
- module ClassMethods
41
+ module ClassMethods
42
+
43
+ # When this setting is set to +true+, default values supplied to the
44
+ # mixlib-cli DSL will be stored in a separate Hash
45
+ def use_separate_default_options(true_or_false)
46
+ @separate_default_options = true_or_false
47
+ end
48
+
49
+ def use_separate_defaults?
50
+ @separate_default_options || false
51
+ end
52
+
24
53
  # Add a command line option.
25
54
  #
26
55
  # === Parameters
@@ -33,7 +62,7 @@ module Mixlib
33
62
  raise(ArgumentError, "Option name must be a symbol") unless name.kind_of?(Symbol)
34
63
  @options[name.to_sym] = args
35
64
  end
36
-
65
+
37
66
  # Get the hash of current options.
38
67
  #
39
68
  # === Returns
@@ -42,7 +71,7 @@ module Mixlib
42
71
  @options ||= {}
43
72
  @options
44
73
  end
45
-
74
+
46
75
  # Set the current options hash
47
76
  #
48
77
  # === Parameters
@@ -54,13 +83,13 @@ module Mixlib
54
83
  raise(ArgumentError, "Options must recieve a hash") unless val.kind_of?(Hash)
55
84
  @options = val
56
85
  end
57
-
86
+
58
87
  # Change the banner. Defaults to:
59
88
  # Usage: #{0} (options)
60
89
  #
61
90
  # === Parameters
62
91
  # bstring<String>:: The string to set the banner to
63
- #
92
+ #
64
93
  # === Returns
65
94
  # @banner<String>:: The current banner
66
95
  def banner(bstring=nil)
@@ -72,9 +101,43 @@ module Mixlib
72
101
  end
73
102
  end
74
103
  end
75
-
76
- attr_accessor :options, :config, :banner, :opt_parser
77
-
104
+
105
+ # Gives the command line options definition as configured in the DSL. These
106
+ # are used by #parse_options to generate the option parsing code. To get
107
+ # the values supplied by the user, see #config.
108
+ attr_accessor :options
109
+
110
+ # A Hash containing the values supplied by command line options.
111
+ #
112
+ # The behavior and contents of this Hash vary depending on whether
113
+ # ClassMethods#use_separate_default_options is enabled.
114
+ # ==== use_separate_default_options *disabled*
115
+ # After initialization, +config+ will contain any default values defined
116
+ # via the mixlib-config DSL. When #parse_options is called, user-supplied
117
+ # values (from ARGV) will be merged in.
118
+ # ==== use_separate_default_options *enabled*
119
+ # After initialization, this will be an empty hash. When #parse_options is
120
+ # called, +config+ is populated *only* with user-supplied values.
121
+ attr_accessor :config
122
+
123
+ # If ClassMethods#use_separate_default_options is enabled, this will be a
124
+ # Hash containing key value pairs of `:option_name => default_value`
125
+ # (populated during object initialization).
126
+ #
127
+ # If use_separate_default_options is disabled, it will always be an empty
128
+ # hash.
129
+ attr_accessor :default_config
130
+
131
+ # Banner for the option parser. If the option parser is printed, e.g., by
132
+ # `puts opt_parser`, this string will be used as the first line.
133
+ attr_accessor :banner
134
+
135
+ # The option parser generated from the mixlib-cli DSL. Set to nil on
136
+ # initialize; when #parse_options is called +opt_parser+ is set to an
137
+ # instance of OptionParser. +opt_parser+ can be used to print a help
138
+ # message including the banner and any CLI options via `puts opt_parser`.
139
+ attr_accessor :opt_parser
140
+
78
141
  # Create a new Mixlib::CLI class. If you override this, make sure you call super!
79
142
  #
80
143
  # === Parameters
@@ -85,14 +148,23 @@ module Mixlib
85
148
  def initialize(*args)
86
149
  @options = Hash.new
87
150
  @config = Hash.new
88
-
151
+ @default_config = Hash.new
152
+ @opt_parser = nil
153
+
89
154
  # Set the banner
90
155
  @banner = self.class.banner
91
-
156
+
92
157
  # Dupe the class options for this instance
93
158
  klass_options = self.class.options
94
159
  klass_options.keys.inject(@options) { |memo, key| memo[key] = klass_options[key].dup; memo }
95
-
160
+
161
+ # If use_separate_defaults? is on, default values go in @default_config
162
+ defaults_container = if self.class.use_separate_defaults?
163
+ @default_config
164
+ else
165
+ @config
166
+ end
167
+
96
168
  # Set the default configuration values for this instance
97
169
  @options.each do |config_key, config_opts|
98
170
  config_opts[:on] ||= :on
@@ -101,16 +173,16 @@ module Mixlib
101
173
  config_opts[:proc] ||= nil
102
174
  config_opts[:show_options] ||= false
103
175
  config_opts[:exit] ||= nil
104
-
176
+
105
177
  if config_opts.has_key?(:default)
106
- @config[config_key] = config_opts[:default]
178
+ defaults_container[config_key] = config_opts[:default]
107
179
  end
108
180
  end
109
-
181
+
110
182
  super(*args)
111
183
  end
112
-
113
- # Parses an array, by default ARGV, for command line options (as configured at
184
+
185
+ # Parses an array, by default ARGV, for command line options (as configured at
114
186
  # the class level).
115
187
  # === Parameters
116
188
  # argv<Array>:: The array of arguments to parse; defaults to ARGV
@@ -119,14 +191,14 @@ module Mixlib
119
191
  # argv<Array>:: Returns any un-parsed elements.
120
192
  def parse_options(argv=ARGV)
121
193
  argv = argv.dup
122
- @opt_parser = OptionParser.new do |opts|
194
+ @opt_parser = OptionParser.new do |opts|
123
195
  # Set the banner
124
- opts.banner = banner
125
-
196
+ opts.banner = banner
197
+
126
198
  # Create new options
127
- options.sort { |a, b| a[0].to_s <=> b[0].to_s }.each do |opt_key, opt_val|
199
+ options.sort { |a, b| a[0].to_s <=> b[0].to_s }.each do |opt_key, opt_val|
128
200
  opt_args = build_option_arguments(opt_val)
129
-
201
+
130
202
  opt_method = case opt_val[:on]
131
203
  when :on
132
204
  :on
@@ -137,14 +209,14 @@ module Mixlib
137
209
  else
138
210
  raise ArgumentError, "You must pass :on, :tail, or :head to :on"
139
211
  end
140
-
212
+
141
213
  parse_block =
142
214
  Proc.new() do |c|
143
215
  config[opt_key] = (opt_val[:proc] && opt_val[:proc].call(c)) || c
144
216
  puts opts if opt_val[:show_options]
145
217
  exit opt_val[:exit] if opt_val[:exit]
146
218
  end
147
-
219
+
148
220
  full_opt = [ opt_method ]
149
221
  opt_args.inject(full_opt) { |memo, arg| memo << arg; memo }
150
222
  full_opt << parse_block
@@ -152,7 +224,7 @@ module Mixlib
152
224
  end
153
225
  end
154
226
  @opt_parser.parse!(argv)
155
-
227
+
156
228
  # Deal with any required values
157
229
  options.each do |opt_key, opt_value|
158
230
  if opt_value[:required] && !config.has_key?(opt_key)
@@ -162,28 +234,28 @@ module Mixlib
162
234
  exit 2
163
235
  end
164
236
  end
165
-
237
+
166
238
  argv
167
239
  end
168
-
169
- def build_option_arguments(opt_setting)
240
+
241
+ def build_option_arguments(opt_setting)
170
242
  arguments = Array.new
171
-
243
+
172
244
  arguments << opt_setting[:short] if opt_setting.has_key?(:short)
173
245
  arguments << opt_setting[:long] if opt_setting.has_key?(:long)
174
-
246
+
175
247
  if opt_setting.has_key?(:description)
176
248
  description = opt_setting[:description]
177
249
  description << " (required)" if opt_setting[:required]
178
250
  arguments << description
179
251
  end
180
-
252
+
181
253
  arguments
182
254
  end
183
-
255
+
184
256
  def self.included(receiver)
185
257
  receiver.extend(Mixlib::CLI::ClassMethods)
186
258
  end
187
-
259
+
188
260
  end
189
261
  end
@@ -1,6 +1,6 @@
1
1
  module Mixlib
2
2
  module CLI
3
- VERSION = "1.2.2"
3
+ VERSION = "1.3.0.rc.0"
4
4
  end
5
5
  end
6
6
 
@@ -6,9 +6,9 @@
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
8
8
  # You may obtain a copy of the License at
9
- #
9
+ #
10
10
  # http://www.apache.org/licenses/LICENSE-2.0
11
- #
11
+ #
12
12
  # Unless required by applicable law or agreed to in writing, software
13
13
  # distributed under the License is distributed on an "AS IS" BASIS,
14
14
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -18,56 +18,56 @@
18
18
 
19
19
  require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
20
20
 
21
- describe Mixlib::CLI do
21
+ describe Mixlib::CLI do
22
22
  after(:each) do
23
23
  TestCLI.options = {}
24
24
  TestCLI.banner("Usage: #{$0} (options)")
25
25
  end
26
-
26
+
27
27
  describe "class method" do
28
28
  describe "option" do
29
29
  it "should allow you to set a config option with a hash" do
30
30
  TestCLI.option(:config_file, :short => '-c CONFIG').should == { :short => '-c CONFIG' }
31
31
  end
32
32
  end
33
-
33
+
34
34
  describe "options" do
35
35
  it "should return the current options hash" do
36
36
  TestCLI.option(:config_file, :short => '-c CONFIG')
37
37
  TestCLI.options.should == { :config_file => { :short => '-c CONFIG' } }
38
38
  end
39
39
  end
40
-
40
+
41
41
  describe "options=" do
42
42
  it "should allow you to set the full options with a single hash" do
43
43
  TestCLI.options = { :config_file => { :short => '-c CONFIG' } }
44
44
  TestCLI.options.should == { :config_file => { :short => '-c CONFIG' } }
45
45
  end
46
46
  end
47
-
47
+
48
48
  describe "banner" do
49
49
  it "should have a default value" do
50
50
  TestCLI.banner.should =~ /^Usage: (.+) \(options\)$/
51
51
  end
52
-
52
+
53
53
  it "should allow you to set the banner" do
54
54
  TestCLI.banner("Usage: foo")
55
55
  TestCLI.banner.should == "Usage: foo"
56
56
  end
57
57
  end
58
58
  end
59
-
60
- describe "instance methods" do
61
-
59
+
60
+ context "when configured with default single-config-hash behavior" do
61
+
62
62
  before(:each) do
63
63
  @cli = TestCLI.new
64
64
  end
65
-
65
+
66
66
  describe "initialize" do
67
67
  it "should set the banner to the class defined banner" do
68
68
  @cli.banner.should == TestCLI.banner
69
69
  end
70
-
70
+
71
71
  it "should set the options to the class defined options, plus defaults" do
72
72
  TestCLI.option(:config_file, :short => "-l LOG")
73
73
  cli = TestCLI.new
@@ -83,27 +83,27 @@ describe Mixlib::CLI do
83
83
  }
84
84
  }
85
85
  end
86
-
86
+
87
87
  it "should set the default config value for any options that include it" do
88
88
  TestCLI.option(:config_file, :short => "-l LOG", :default => :debug)
89
89
  @cli = TestCLI.new
90
90
  @cli.config[:config_file].should == :debug
91
91
  end
92
92
  end
93
-
93
+
94
94
  describe "parse_options" do
95
95
  it "should set the banner in opt_parse" do
96
96
  @cli.parse_options([])
97
97
  @cli.opt_parser.banner.should == @cli.banner
98
98
  end
99
-
99
+
100
100
  it "should present the arguments in the banner" do
101
101
  TestCLI.option(:config_file, :short => "-l LOG")
102
102
  @cli = TestCLI.new
103
103
  @cli.parse_options([])
104
104
  @cli.opt_parser.to_s.should =~ /-l LOG/
105
105
  end
106
-
106
+
107
107
  it "should honor :on => :tail options in the banner" do
108
108
  TestCLI.option(:config_file, :short => "-l LOG")
109
109
  TestCLI.option(:help, :short => "-h", :boolean => true, :on => :tail)
@@ -111,7 +111,7 @@ describe Mixlib::CLI do
111
111
  @cli.parse_options([])
112
112
  @cli.opt_parser.to_s.split("\n").last.should =~ /-h/
113
113
  end
114
-
114
+
115
115
  it "should honor :on => :head options in the banner" do
116
116
  TestCLI.option(:config_file, :short => "-l LOG")
117
117
  TestCLI.option(:help, :short => "-h", :boolean => true, :on => :head)
@@ -119,11 +119,11 @@ describe Mixlib::CLI do
119
119
  @cli.parse_options([])
120
120
  @cli.opt_parser.to_s.split("\n")[1].should =~ /-h/
121
121
  end
122
-
122
+
123
123
  it "should present the arguments in alphabetical order in the banner" do
124
124
  TestCLI.option(:alpha, :short => "-a ALPHA")
125
125
  TestCLI.option(:beta, :short => "-b BETA")
126
- TestCLI.option(:zeta, :short => "-z ZETA")
126
+ TestCLI.option(:zeta, :short => "-z ZETA")
127
127
  @cli = TestCLI.new
128
128
  @cli.parse_options([])
129
129
  output_lines = @cli.opt_parser.to_s.split("\n")
@@ -131,31 +131,31 @@ describe Mixlib::CLI do
131
131
  output_lines[2].should =~ /-b BETA/
132
132
  output_lines[3].should =~ /-z ZETA/
133
133
  end
134
-
134
+
135
135
  it "should set the corresponding config value for non-boolean arguments" do
136
136
  TestCLI.option(:config_file, :short => "-c CONFIG")
137
137
  @cli = TestCLI.new
138
138
  @cli.parse_options([ '-c', 'foo.rb' ])
139
139
  @cli.config[:config_file].should == 'foo.rb'
140
- end
141
-
140
+ end
141
+
142
142
  it "should set the corresponding config value according to a supplied proc" do
143
- TestCLI.option(:number,
144
- :short => "-n NUMBER",
143
+ TestCLI.option(:number,
144
+ :short => "-n NUMBER",
145
145
  :proc => Proc.new { |config| config.to_i + 2 }
146
146
  )
147
147
  @cli = TestCLI.new
148
148
  @cli.parse_options([ "-n", "2" ])
149
149
  @cli.config[:number].should == 4
150
150
  end
151
-
151
+
152
152
  it "should set the corresponding config value to true for boolean arguments" do
153
153
  TestCLI.option(:i_am_boolean, :short => "-i", :boolean => true)
154
154
  @cli = TestCLI.new
155
155
  @cli.parse_options([ '-i' ])
156
156
  @cli.config[:i_am_boolean].should == true
157
157
  end
158
-
158
+
159
159
  it "should set the corresponding config value to false when a boolean is prefixed with --no" do
160
160
  TestCLI.option(:i_am_boolean, :long => "--[no-]bool", :boolean => true)
161
161
  @cli = TestCLI.new
@@ -213,23 +213,44 @@ describe Mixlib::CLI do
213
213
  end
214
214
  end
215
215
  end
216
-
216
+
217
+ context "when configured to separate default options" do
218
+ before do
219
+ TestCLI.use_separate_default_options true
220
+ TestCLI.option(:defaulter, :short => "-D SOMETHING", :default => "this is the default")
221
+ @cli = TestCLI.new
222
+ end
223
+
224
+ it "sets default values on the `default` hash" do
225
+ @cli.parse_options([])
226
+ @cli.default_config[:defaulter].should == "this is the default"
227
+ @cli.config[:defaulter].should be_nil
228
+ end
229
+
230
+ it "sets parsed values on the `config` hash" do
231
+ @cli.parse_options(%w[-D not-default])
232
+ @cli.default_config[:defaulter].should == "this is the default"
233
+ @cli.config[:defaulter].should == "not-default"
234
+ end
235
+
236
+ end
237
+
217
238
  end
218
239
 
219
240
 
220
- # option :config_file,
241
+ # option :config_file,
221
242
  # :short => "-c CONFIG",
222
243
  # :long => "--config CONFIG",
223
244
  # :default => 'config.rb',
224
245
  # :description => "The configuration file to use"
225
- #
226
- # option :log_level,
246
+ #
247
+ # option :log_level,
227
248
  # :short => "-l LEVEL",
228
249
  # :long => "--log_level LEVEL",
229
250
  # :description => "Set the log level (debug, info, warn, error, fatal)",
230
251
  # :required => true,
231
252
  # :proc => nil
232
- #
253
+ #
233
254
  # option :help,
234
255
  # :short => "-h",
235
256
  # :long => "--help",
metadata CHANGED
@@ -1,35 +1,25 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mixlib-cli
3
- version: !ruby/object:Gem::Version
4
- hash: 27
5
- prerelease:
6
- segments:
7
- - 1
8
- - 2
9
- - 2
10
- version: 1.2.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.0.rc.0
5
+ prerelease: 6
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Opscode, Inc.
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-09-08 00:00:00 -07:00
19
- default_executable:
12
+ date: 2013-01-10 00:00:00.000000000 Z
20
13
  dependencies: []
21
-
22
14
  description: A simple mixin for CLI interfaces, including option parsing
23
15
  email: info@opscode.com
24
16
  executables: []
25
-
26
17
  extensions: []
27
-
28
- extra_rdoc_files:
18
+ extra_rdoc_files:
29
19
  - README.rdoc
30
20
  - LICENSE
31
21
  - NOTICE
32
- files:
22
+ files:
33
23
  - LICENSE
34
24
  - README.rdoc
35
25
  - Rakefile
@@ -38,39 +28,28 @@ files:
38
28
  - lib/mixlib/cli.rb
39
29
  - spec/mixlib/cli_spec.rb
40
30
  - spec/spec_helper.rb
41
- has_rdoc: true
42
31
  homepage: http://www.opscode.com
43
32
  licenses: []
44
-
45
33
  post_install_message:
46
34
  rdoc_options: []
47
-
48
- require_paths:
35
+ require_paths:
49
36
  - lib
50
- required_ruby_version: !ruby/object:Gem::Requirement
37
+ required_ruby_version: !ruby/object:Gem::Requirement
51
38
  none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- hash: 3
56
- segments:
57
- - 0
58
- version: "0"
59
- required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
44
  none: false
61
- requirements:
62
- - - ">="
63
- - !ruby/object:Gem::Version
64
- hash: 3
65
- segments:
66
- - 0
67
- version: "0"
45
+ requirements:
46
+ - - ! '>'
47
+ - !ruby/object:Gem::Version
48
+ version: 1.3.1
68
49
  requirements: []
69
-
70
50
  rubyforge_project:
71
- rubygems_version: 1.6.2
51
+ rubygems_version: 1.8.23
72
52
  signing_key:
73
53
  specification_version: 3
74
54
  summary: A simple mixin for CLI interfaces, including option parsing
75
55
  test_files: []
76
-