mixlib-cli 1.2.2 → 1.3.0.rc.0

Sign up to get free protection for your applications and to get access to all the features.
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
-