mixlib-cli 1.5.0 → 1.6.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.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/NOTICE +6 -7
- data/README.md +109 -0
- data/Rakefile +19 -9
- data/lib/mixlib/cli.rb +67 -17
- data/lib/mixlib/cli/version.rb +1 -2
- data/mixlib-cli.gemspec +27 -0
- data/spec/mixlib/cli_spec.rb +91 -17
- data/spec/spec_helper.rb +9 -3
- metadata +40 -24
- data/README.rdoc +0 -84
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2d8c52004fea1ccbbacc8cc9eb27c90319169a7
|
4
|
+
data.tar.gz: 02c491e6efbd0311e961fabdfa5104cac182f906
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0ebca3acd4ff265dc86b78ad542b2400260167345d6d05334359e2e4e575160d26ccaa905e42cc36e8eaecf373ed5f7b6eafc6d0f0e72c8dd9541d6749e4cda
|
7
|
+
data.tar.gz: 08c9482a936d10feea1f968effa75beba3f7f0911fa63dbf16755da7d0f674df9f64622f2941050ea7a16ed71efd4b963b7715956b819f67362469668b0d7d71
|
data/Gemfile
ADDED
data/NOTICE
CHANGED
@@ -1,27 +1,26 @@
|
|
1
1
|
Mixin::CLI NOTICE
|
2
2
|
=================
|
3
3
|
|
4
|
-
Developed at
|
4
|
+
Developed at Chef (http://www.chef.io).
|
5
5
|
|
6
|
-
|
6
|
+
|
7
|
+
* Copyright 2009-2016, Chef Software, Inc. <legal@chef.io>
|
7
8
|
|
8
9
|
Mixin::CLI incorporates code from Chef. The Chef notice file follows:
|
9
10
|
|
10
11
|
Chef NOTICE
|
11
12
|
===========
|
12
13
|
|
13
|
-
Developed at
|
14
|
+
Developed at Chef (http://www.chef.io).
|
14
15
|
|
15
16
|
Contributors and Copyright holders:
|
16
17
|
|
17
|
-
* Copyright 2008, Adam Jacob <adam@
|
18
|
+
* Copyright 2008, Adam Jacob <adam@chef.io>
|
18
19
|
* Copyright 2008, Arjuna Christensen <aj@hjksolutions.com>
|
19
20
|
* Copyright 2008, Bryan McLellan <btm@loftninjas.org>
|
20
21
|
* Copyright 2008, Ezra Zygmuntowicz <ezra@engineyard.com>
|
21
22
|
* Copyright 2009, Sean Cribbs <seancribbs@gmail.com>
|
22
|
-
* Copyright 2009, Christopher Brown <cb@
|
23
|
+
* Copyright 2009, Christopher Brown <cb@chef.io>
|
23
24
|
* Copyright 2009, Thom May <thom@clearairturbulence.org>
|
24
25
|
|
25
26
|
Chef incorporates code modified from Open4 (http://www.codeforpeople.com/lib/ruby/open4/), which was written by Ara T. Howard.
|
26
|
-
|
27
|
-
Chef incorporates code modified from Merb (http://www.merbivore.com), which is Copyright (c) 2008 Engine Yard.
|
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Mixlib::CLI
|
2
|
+
|
3
|
+
[](https://travis-ci.org/chef/mixlib-cli) [](https://badge.fury.io/rb/mixlib-cli)
|
4
|
+
|
5
|
+
Mixlib::CLI provides a class-based command line option parsing object, like the one used in Chef, Ohai and Relish. To use in your project:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require 'rubygems'
|
9
|
+
require 'mixlib/cli'
|
10
|
+
|
11
|
+
class MyCLI
|
12
|
+
include Mixlib::CLI
|
13
|
+
|
14
|
+
option :config_file,
|
15
|
+
:short => "-c CONFIG",
|
16
|
+
:long => "--config CONFIG",
|
17
|
+
:default => 'config.rb',
|
18
|
+
:description => "The configuration file to use"
|
19
|
+
|
20
|
+
option :log_level,
|
21
|
+
:short => "-l LEVEL",
|
22
|
+
:long => "--log_level LEVEL",
|
23
|
+
:description => "Set the log level (debug, info, warn, error, fatal)",
|
24
|
+
:required => true,
|
25
|
+
:in => ['debug', 'info', 'warn', 'error', 'fatal'],
|
26
|
+
:proc => Proc.new { |l| l.to_sym }
|
27
|
+
|
28
|
+
option :help,
|
29
|
+
:short => "-h",
|
30
|
+
:long => "--help",
|
31
|
+
:description => "Show this message",
|
32
|
+
:on => :tail,
|
33
|
+
:boolean => true,
|
34
|
+
:show_options => true,
|
35
|
+
:exit => 0
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# ARGV = [ '-c', 'foo.rb', '-l', 'debug' ]
|
40
|
+
cli = MyCLI.new
|
41
|
+
cli.parse_options
|
42
|
+
cli.config[:config_file] # 'foo.rb'
|
43
|
+
cli.config[:log_level] # :debug
|
44
|
+
```
|
45
|
+
|
46
|
+
If you are using this in conjunction with Mixlib::Config, you can do something like this (building on the above definition):
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
class MyConfig
|
50
|
+
extend(Mixlib::Config)
|
51
|
+
|
52
|
+
log_level :info
|
53
|
+
config_file "default.rb"
|
54
|
+
end
|
55
|
+
|
56
|
+
class MyCLI
|
57
|
+
def run(argv=ARGV)
|
58
|
+
parse_options(argv)
|
59
|
+
MyConfig.merge!(config)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
c = MyCLI.new
|
64
|
+
# ARGV = [ '-l', 'debug' ]
|
65
|
+
c.run
|
66
|
+
MyConfig[:log_level] # :debug
|
67
|
+
```
|
68
|
+
|
69
|
+
Available arguments to 'option':
|
70
|
+
|
71
|
+
- `:short`: The short option, just like from optparse. Example: "-l LEVEL"
|
72
|
+
- `:long`: The long option, just like from optparse. Example: "--level LEVEL"
|
73
|
+
- `:description`: The description for this item, just like from optparse.
|
74
|
+
- `:default`: A default value for this option
|
75
|
+
- `:required`: Prints a message informing the user of the missing requirement, and exits. Default is false.
|
76
|
+
- `:on`: Set to :tail to appear at the end, or `:head`: to appear at the top.
|
77
|
+
- `:boolean:`: If this option takes no arguments, set this to true.
|
78
|
+
- `:show_options`: If you want the option list printed when this option is called, set this to true.
|
79
|
+
- `:exit`: Exit your program with the exit code when this option is specified. Example: 0
|
80
|
+
- `:proc`: If set, the configuration value will be set to the return value of this proc.
|
81
|
+
- `:in`: An array containing the list of accepted values
|
82
|
+
|
83
|
+
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).
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
# ARGV = [ '-c', 'foo.rb', '-l', 'debug', 'file1', 'file2', 'file3' ]
|
87
|
+
cli = MyCLI.new
|
88
|
+
cli.parse_options
|
89
|
+
cli.cli_arguments # [ 'file1', 'file2', 'file3' ]
|
90
|
+
```
|
91
|
+
|
92
|
+
## LICENSE:
|
93
|
+
|
94
|
+
- Copyright:: Copyright (c) 2008-2016 Chef Software, Inc.
|
95
|
+
- License:: Apache License, Version 2.0
|
96
|
+
|
97
|
+
```text
|
98
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
99
|
+
you may not use this file except in compliance with the License.
|
100
|
+
You may obtain a copy of the License at
|
101
|
+
|
102
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
103
|
+
|
104
|
+
Unless required by applicable law or agreed to in writing, software
|
105
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
106
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
107
|
+
See the License for the specific language governing permissions and
|
108
|
+
limitations under the License.
|
109
|
+
```
|
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
require "bundler"
|
2
|
+
require "rubygems"
|
3
|
+
require "rubygems/package_task"
|
4
|
+
require "rdoc/task"
|
5
|
+
require "rspec/core/rake_task"
|
6
6
|
|
7
7
|
Bundler::GemHelper.install_tasks
|
8
8
|
|
@@ -10,14 +10,24 @@ task :default => :spec
|
|
10
10
|
|
11
11
|
desc "Run specs"
|
12
12
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
13
|
-
spec.pattern =
|
13
|
+
spec.pattern = "spec/**/*_spec.rb"
|
14
14
|
end
|
15
15
|
|
16
16
|
gem_spec = eval(File.read("mixlib-cli.gemspec"))
|
17
17
|
|
18
18
|
RDoc::Task.new do |rdoc|
|
19
|
-
rdoc.rdoc_dir =
|
19
|
+
rdoc.rdoc_dir = "rdoc"
|
20
20
|
rdoc.title = "mixlib-cli #{gem_spec.version}"
|
21
|
-
rdoc.rdoc_files.include(
|
22
|
-
rdoc.rdoc_files.include(
|
21
|
+
rdoc.rdoc_files.include("README*")
|
22
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
23
|
+
end
|
24
|
+
|
25
|
+
begin
|
26
|
+
require "chefstyle"
|
27
|
+
require "rubocop/rake_task"
|
28
|
+
RuboCop::RakeTask.new(:style) do |task|
|
29
|
+
task.options += ["--display-cop-names", "--no-color"]
|
30
|
+
end
|
31
|
+
rescue LoadError
|
32
|
+
puts "chefstyle/rubocop is not available. gem install chefstyle to do style checking."
|
23
33
|
end
|
data/lib/mixlib/cli.rb
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
# limitations under the License.
|
17
17
|
#
|
18
18
|
|
19
|
-
require
|
19
|
+
require "optparse"
|
20
20
|
|
21
21
|
module Mixlib
|
22
22
|
|
@@ -38,8 +38,46 @@ module Mixlib
|
|
38
38
|
# #parse_options. After calling this method, the attribute #config will
|
39
39
|
# contain a hash of `:option_name => value` pairs.
|
40
40
|
module CLI
|
41
|
-
module ClassMethods
|
42
41
|
|
42
|
+
module InheritMethods
|
43
|
+
def inherited(receiver)
|
44
|
+
receiver.options = deep_dup(self.options)
|
45
|
+
receiver.extend(Mixlib::CLI::InheritMethods)
|
46
|
+
end
|
47
|
+
|
48
|
+
# object:: Instance to clone
|
49
|
+
# This method will return a "deep clone" of the provided
|
50
|
+
# `object`. If the provided `object` is an enumerable type the
|
51
|
+
# contents will be iterated and cloned as well.
|
52
|
+
def deep_dup(object)
|
53
|
+
cloned_object = object.respond_to?(:dup) ? object.dup : object
|
54
|
+
if cloned_object.kind_of?(Enumerable)
|
55
|
+
if cloned_object.kind_of?(Hash)
|
56
|
+
new_hash = cloned_object.class.new
|
57
|
+
cloned_object.each do |key, value|
|
58
|
+
cloned_key = deep_dup(key)
|
59
|
+
cloned_value = deep_dup(value)
|
60
|
+
new_hash[cloned_key] = cloned_value
|
61
|
+
end
|
62
|
+
cloned_object.replace(new_hash)
|
63
|
+
else
|
64
|
+
cloned_object.map! do |shallow_instance|
|
65
|
+
deep_dup(shallow_instance)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
cloned_object
|
70
|
+
rescue TypeError
|
71
|
+
# Symbol will happily provide a `#dup` method even though
|
72
|
+
# attempts to clone it will result in an exception (atoms!).
|
73
|
+
# So if we run into an issue of TypeErrors, just return the
|
74
|
+
# original object as we gave our "best effort"
|
75
|
+
object
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
module ClassMethods
|
43
81
|
# When this setting is set to +true+, default values supplied to the
|
44
82
|
# mixlib-cli DSL will be stored in a separate Hash
|
45
83
|
def use_separate_default_options(true_or_false)
|
@@ -47,7 +85,7 @@ module Mixlib
|
|
47
85
|
end
|
48
86
|
|
49
87
|
def use_separate_defaults?
|
50
|
-
@separate_default_options
|
88
|
+
@separate_default_options ||= false
|
51
89
|
end
|
52
90
|
|
53
91
|
# Add a command line option.
|
@@ -92,7 +130,7 @@ module Mixlib
|
|
92
130
|
#
|
93
131
|
# === Returns
|
94
132
|
# @banner<String>:: The current banner
|
95
|
-
def banner(bstring=nil)
|
133
|
+
def banner(bstring = nil)
|
96
134
|
if bstring
|
97
135
|
@banner = bstring
|
98
136
|
else
|
@@ -149,7 +187,7 @@ module Mixlib
|
|
149
187
|
@opt_parser = nil
|
150
188
|
|
151
189
|
# Set the banner
|
152
|
-
@banner
|
190
|
+
@banner = self.class.banner
|
153
191
|
|
154
192
|
# Dupe the class options for this instance
|
155
193
|
klass_options = self.class.options
|
@@ -170,6 +208,7 @@ module Mixlib
|
|
170
208
|
config_opts[:proc] ||= nil
|
171
209
|
config_opts[:show_options] ||= false
|
172
210
|
config_opts[:exit] ||= nil
|
211
|
+
config_opts[:in] ||= nil
|
173
212
|
|
174
213
|
if config_opts.has_key?(:default)
|
175
214
|
defaults_container[config_key] = config_opts[:default]
|
@@ -186,7 +225,7 @@ module Mixlib
|
|
186
225
|
#
|
187
226
|
# === Returns
|
188
227
|
# argv<Array>:: Returns any un-parsed elements.
|
189
|
-
def parse_options(argv=ARGV)
|
228
|
+
def parse_options(argv = ARGV)
|
190
229
|
argv = argv.dup
|
191
230
|
opt_parser.parse!(argv)
|
192
231
|
|
@@ -198,13 +237,23 @@ module Mixlib
|
|
198
237
|
puts @opt_parser
|
199
238
|
exit 2
|
200
239
|
end
|
240
|
+
if opt_value[:in]
|
241
|
+
unless opt_value[:in].kind_of?(Array)
|
242
|
+
raise(ArgumentError, "Options config key :in must receive an Array")
|
243
|
+
end
|
244
|
+
if !opt_value[:in].include?(config[opt_key])
|
245
|
+
reqarg = opt_value[:short] || opt_value[:long]
|
246
|
+
puts "#{reqarg}: #{config[opt_key]} is not included in the list ['#{opt_value[:in].join("', '")}'] "
|
247
|
+
puts @opt_parser
|
248
|
+
exit 2
|
249
|
+
end
|
250
|
+
end
|
201
251
|
end
|
202
252
|
|
203
253
|
@cli_arguments = argv
|
204
254
|
argv
|
205
255
|
end
|
206
256
|
|
207
|
-
|
208
257
|
# The option parser generated from the mixlib-cli DSL. +opt_parser+ can be
|
209
258
|
# used to print a help message including the banner and any CLI options via
|
210
259
|
# `puts opt_parser`.
|
@@ -220,15 +269,15 @@ module Mixlib
|
|
220
269
|
opt_args = build_option_arguments(opt_val)
|
221
270
|
|
222
271
|
opt_method = case opt_val[:on]
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
272
|
+
when :on
|
273
|
+
:on
|
274
|
+
when :tail
|
275
|
+
:on_tail
|
276
|
+
when :head
|
277
|
+
:on_head
|
278
|
+
else
|
279
|
+
raise ArgumentError, "You must pass :on, :tail, or :head to :on"
|
280
|
+
end
|
232
281
|
|
233
282
|
parse_block =
|
234
283
|
Proc.new() do |c|
|
@@ -250,10 +299,10 @@ module Mixlib
|
|
250
299
|
|
251
300
|
arguments << opt_setting[:short] if opt_setting.has_key?(:short)
|
252
301
|
arguments << opt_setting[:long] if opt_setting.has_key?(:long)
|
253
|
-
|
254
302
|
if opt_setting.has_key?(:description)
|
255
303
|
description = opt_setting[:description]
|
256
304
|
description << " (required)" if opt_setting[:required]
|
305
|
+
description << " (included in ['#{opt_setting[:in].join("', '")}'])" if opt_setting[:in]
|
257
306
|
arguments << description
|
258
307
|
end
|
259
308
|
|
@@ -262,6 +311,7 @@ module Mixlib
|
|
262
311
|
|
263
312
|
def self.included(receiver)
|
264
313
|
receiver.extend(Mixlib::CLI::ClassMethods)
|
314
|
+
receiver.extend(Mixlib::CLI::InheritMethods)
|
265
315
|
end
|
266
316
|
|
267
317
|
end
|
data/lib/mixlib/cli/version.rb
CHANGED
data/mixlib-cli.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__) + "/lib")
|
2
|
+
require "mixlib/cli/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "mixlib-cli"
|
6
|
+
s.version = Mixlib::CLI::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.has_rdoc = true
|
9
|
+
s.extra_rdoc_files = ["README.md", "LICENSE", "NOTICE"]
|
10
|
+
s.summary = "A simple mixin for CLI interfaces, including option parsing"
|
11
|
+
s.description = s.summary
|
12
|
+
s.author = "Chef Software, Inc."
|
13
|
+
s.email = "info@chef.io"
|
14
|
+
s.homepage = "https://www.chef.io"
|
15
|
+
s.license = "Apache-2.0"
|
16
|
+
|
17
|
+
# Uncomment this to add a dependency
|
18
|
+
#s.add_dependency "mixlib-log"
|
19
|
+
s.add_development_dependency "rake", "< 11.0"
|
20
|
+
s.add_development_dependency "rspec", "~> 2.14"
|
21
|
+
s.add_development_dependency "rdoc"
|
22
|
+
s.add_development_dependency "chefstyle", "~> 0.3"
|
23
|
+
|
24
|
+
s.require_path = "lib"
|
25
|
+
s.files = %w{LICENSE README.md Gemfile Rakefile NOTICE} + Dir.glob("*.gemspec") +
|
26
|
+
Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
27
|
+
end
|
data/spec/mixlib/cli_spec.rb
CHANGED
@@ -27,21 +27,21 @@ describe Mixlib::CLI do
|
|
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
|
-
TestCLI.option(:config_file, :short =>
|
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
|
-
TestCLI.option(:config_file, :short =>
|
37
|
-
TestCLI.options.should == { :config_file => { :short =>
|
36
|
+
TestCLI.option(:config_file, :short => "-c CONFIG")
|
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
|
-
TestCLI.options = { :config_file => { :short =>
|
44
|
-
TestCLI.options.should == { :config_file => { :short =>
|
43
|
+
TestCLI.options = { :config_file => { :short => "-c CONFIG" } }
|
44
|
+
TestCLI.options.should == { :config_file => { :short => "-c CONFIG" } }
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -79,8 +79,9 @@ describe Mixlib::CLI do
|
|
79
79
|
:required => false,
|
80
80
|
:proc => nil,
|
81
81
|
:show_options => false,
|
82
|
-
:exit => nil
|
83
|
-
|
82
|
+
:exit => nil,
|
83
|
+
:in => nil,
|
84
|
+
},
|
84
85
|
}
|
85
86
|
end
|
86
87
|
|
@@ -134,8 +135,8 @@ describe Mixlib::CLI do
|
|
134
135
|
it "should set the corresponding config value for non-boolean arguments" do
|
135
136
|
TestCLI.option(:config_file, :short => "-c CONFIG")
|
136
137
|
@cli = TestCLI.new
|
137
|
-
@cli.parse_options([
|
138
|
-
@cli.config[:config_file].should ==
|
138
|
+
@cli.parse_options([ "-c", "foo.rb" ])
|
139
|
+
@cli.config[:config_file].should == "foo.rb"
|
139
140
|
end
|
140
141
|
|
141
142
|
it "should set the corresponding config value according to a supplied proc" do
|
@@ -151,14 +152,14 @@ describe Mixlib::CLI do
|
|
151
152
|
it "should set the corresponding config value to true for boolean arguments" do
|
152
153
|
TestCLI.option(:i_am_boolean, :short => "-i", :boolean => true)
|
153
154
|
@cli = TestCLI.new
|
154
|
-
@cli.parse_options([
|
155
|
+
@cli.parse_options([ "-i" ])
|
155
156
|
@cli.config[:i_am_boolean].should == true
|
156
157
|
end
|
157
158
|
|
158
159
|
it "should set the corresponding config value to false when a boolean is prefixed with --no" do
|
159
160
|
TestCLI.option(:i_am_boolean, :long => "--[no-]bool", :boolean => true)
|
160
161
|
@cli = TestCLI.new
|
161
|
-
@cli.parse_options([
|
162
|
+
@cli.parse_options([ "--no-bool" ])
|
162
163
|
@cli.config[:i_am_boolean].should == false
|
163
164
|
end
|
164
165
|
|
@@ -174,6 +175,32 @@ describe Mixlib::CLI do
|
|
174
175
|
lambda { @cli.parse_options([]) }.should raise_error(SystemExit)
|
175
176
|
end
|
176
177
|
|
178
|
+
it "should exit if option is not included in the list" do
|
179
|
+
TestCLI.option(:inclusion, :short => "-i val", :in => %w{one two})
|
180
|
+
@cli = TestCLI.new
|
181
|
+
lambda { @cli.parse_options(["-i", "three"]) }.should raise_error(SystemExit)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should raise ArgumentError if options key :in is not an array" do
|
185
|
+
TestCLI.option(:inclusion, :short => "-i val", :in => "foo")
|
186
|
+
@cli = TestCLI.new
|
187
|
+
lambda { @cli.parse_options(["-i", "three"]) }.should raise_error(ArgumentError)
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should not exit if option is included in the list" do
|
191
|
+
TestCLI.option(:inclusion, :short => "-i val", :in => %w{one two})
|
192
|
+
@cli = TestCLI.new
|
193
|
+
@cli.parse_options(["-i", "one"])
|
194
|
+
@cli.config[:inclusion].should == "one"
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should change description if :in key is specified" do
|
198
|
+
TestCLI.option(:inclusion, :short => "-i val", :in => %w{one two}, :description => "desc")
|
199
|
+
@cli = TestCLI.new
|
200
|
+
@cli.parse_options(["-i", "one"])
|
201
|
+
@cli.options[:inclusion][:description].should == "desc (included in ['one', 'two'])"
|
202
|
+
end
|
203
|
+
|
177
204
|
it "should not exit if a required option is specified" do
|
178
205
|
TestCLI.option(:require_me, :short => "-r", :boolean => true, :required => true)
|
179
206
|
@cli = TestCLI.new
|
@@ -199,17 +226,17 @@ describe Mixlib::CLI do
|
|
199
226
|
TestCLI.option(:config_file, :short => "-c CONFIG")
|
200
227
|
@cli = TestCLI.new
|
201
228
|
argv_old = ARGV.dup
|
202
|
-
ARGV.replace [
|
229
|
+
ARGV.replace ["-c", "foo.rb"]
|
203
230
|
@cli.parse_options()
|
204
|
-
ARGV.should == [
|
231
|
+
ARGV.should == ["-c", "foo.rb"]
|
205
232
|
ARGV.replace argv_old
|
206
233
|
end
|
207
234
|
|
208
235
|
it "should preserve and return any un-parsed elements" do
|
209
236
|
TestCLI.option(:party, :short => "-p LOCATION")
|
210
237
|
@cli = TestCLI.new
|
211
|
-
@cli.parse_options([
|
212
|
-
@cli.cli_arguments.should ==
|
238
|
+
@cli.parse_options([ "easy", "-p", "opscode", "hard" ]).should == %w{easy hard}
|
239
|
+
@cli.cli_arguments.should == %w{easy hard}
|
213
240
|
end
|
214
241
|
end
|
215
242
|
end
|
@@ -228,15 +255,62 @@ describe Mixlib::CLI do
|
|
228
255
|
end
|
229
256
|
|
230
257
|
it "sets parsed values on the `config` hash" do
|
231
|
-
@cli.parse_options(%w
|
258
|
+
@cli.parse_options(%w{-D not-default})
|
232
259
|
@cli.default_config[:defaulter].should == "this is the default"
|
233
260
|
@cli.config[:defaulter].should == "not-default"
|
234
261
|
end
|
235
262
|
|
236
263
|
end
|
237
264
|
|
238
|
-
|
265
|
+
context "when subclassed" do
|
266
|
+
before do
|
267
|
+
TestCLI.options = { :arg1 => { :boolean => true } }
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should retain previously defined options from parent" do
|
271
|
+
class T1 < TestCLI
|
272
|
+
option :arg2, :boolean => true
|
273
|
+
end
|
274
|
+
T1.options[:arg1].should be_a(Hash)
|
275
|
+
T1.options[:arg2].should be_a(Hash)
|
276
|
+
TestCLI.options[:arg2].should be_nil
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should not be able to modify parent classes options" do
|
280
|
+
class T2 < TestCLI
|
281
|
+
option :arg2, :boolean => true
|
282
|
+
end
|
283
|
+
T2.options[:arg1][:boolean] = false
|
284
|
+
T2.options[:arg1][:boolean].should be_false
|
285
|
+
TestCLI.options[:arg1][:boolean].should be_true
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should pass its options onto child" do
|
289
|
+
class T3 < TestCLI
|
290
|
+
option :arg2, :boolean => true
|
291
|
+
end
|
292
|
+
class T4 < T3
|
293
|
+
option :arg3, :boolean => true
|
294
|
+
end
|
295
|
+
3.times do |i|
|
296
|
+
T4.options["arg#{i + 1}".to_sym].should be_a(Hash)
|
297
|
+
end
|
298
|
+
end
|
239
299
|
|
300
|
+
it "should also work with an option that's an array" do
|
301
|
+
class T5 < TestCLI
|
302
|
+
option :arg2, :default => []
|
303
|
+
end
|
304
|
+
|
305
|
+
class T6 < T5
|
306
|
+
end
|
307
|
+
|
308
|
+
T6.options[:arg2].should be_a(Hash)
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
end
|
240
314
|
|
241
315
|
# option :config_file,
|
242
316
|
# :short => "-c CONFIG",
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
-
$TESTING=true
|
2
|
-
$:.push File.join(File.dirname(__FILE__),
|
1
|
+
$TESTING = true
|
2
|
+
$:.push File.join(File.dirname(__FILE__), "..", "lib")
|
3
3
|
|
4
|
-
require
|
4
|
+
require "mixlib/cli"
|
5
5
|
|
6
6
|
class TestCLI
|
7
7
|
include Mixlib::CLI
|
8
8
|
end
|
9
9
|
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.filter_run :focus => true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
config.warnings = true
|
15
|
+
end
|
metadata
CHANGED
@@ -1,76 +1,93 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixlib-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Chef Software, Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - "<"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '11.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - "<"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '11.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.14'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.14'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rdoc
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: chefstyle
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.3'
|
55
69
|
description: A simple mixin for CLI interfaces, including option parsing
|
56
|
-
email: info@
|
70
|
+
email: info@chef.io
|
57
71
|
executables: []
|
58
72
|
extensions: []
|
59
73
|
extra_rdoc_files:
|
60
|
-
- README.
|
74
|
+
- README.md
|
61
75
|
- LICENSE
|
62
76
|
- NOTICE
|
63
77
|
files:
|
78
|
+
- Gemfile
|
64
79
|
- LICENSE
|
65
|
-
- README.rdoc
|
66
|
-
- Rakefile
|
67
80
|
- NOTICE
|
68
|
-
-
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
69
83
|
- lib/mixlib/cli.rb
|
84
|
+
- lib/mixlib/cli/version.rb
|
85
|
+
- mixlib-cli.gemspec
|
70
86
|
- spec/mixlib/cli_spec.rb
|
71
87
|
- spec/spec_helper.rb
|
72
|
-
homepage:
|
73
|
-
licenses:
|
88
|
+
homepage: https://www.chef.io
|
89
|
+
licenses:
|
90
|
+
- Apache-2.0
|
74
91
|
metadata: {}
|
75
92
|
post_install_message:
|
76
93
|
rdoc_options: []
|
@@ -78,19 +95,18 @@ require_paths:
|
|
78
95
|
- lib
|
79
96
|
required_ruby_version: !ruby/object:Gem::Requirement
|
80
97
|
requirements:
|
81
|
-
- -
|
98
|
+
- - ">="
|
82
99
|
- !ruby/object:Gem::Version
|
83
100
|
version: '0'
|
84
101
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
102
|
requirements:
|
86
|
-
- -
|
103
|
+
- - ">="
|
87
104
|
- !ruby/object:Gem::Version
|
88
105
|
version: '0'
|
89
106
|
requirements: []
|
90
107
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.
|
108
|
+
rubygems_version: 2.4.5.1
|
92
109
|
signing_key:
|
93
110
|
specification_version: 4
|
94
111
|
summary: A simple mixin for CLI interfaces, including option parsing
|
95
112
|
test_files: []
|
96
|
-
has_rdoc: true
|
data/README.rdoc
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
== Mixlib::CLI
|
2
|
-
|
3
|
-
Mixlib::CLI provides a class-based command line option parsing object, like the one used in Chef, Ohai and Relish. To use in your project:
|
4
|
-
|
5
|
-
require 'rubygems'
|
6
|
-
require 'mixlib/cli'
|
7
|
-
|
8
|
-
class MyCLI
|
9
|
-
include Mixlib::CLI
|
10
|
-
|
11
|
-
option :config_file,
|
12
|
-
:short => "-c CONFIG",
|
13
|
-
:long => "--config CONFIG",
|
14
|
-
:default => 'config.rb',
|
15
|
-
:description => "The configuration file to use"
|
16
|
-
|
17
|
-
option :log_level,
|
18
|
-
:short => "-l LEVEL",
|
19
|
-
:long => "--log_level LEVEL",
|
20
|
-
:description => "Set the log level (debug, info, warn, error, fatal)",
|
21
|
-
:required => true,
|
22
|
-
:proc => Proc.new { |l| l.to_sym }
|
23
|
-
|
24
|
-
option :help,
|
25
|
-
:short => "-h",
|
26
|
-
:long => "--help",
|
27
|
-
:description => "Show this message",
|
28
|
-
:on => :tail,
|
29
|
-
:boolean => true,
|
30
|
-
:show_options => true,
|
31
|
-
:exit => 0
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
# ARGV = [ '-c', 'foo.rb', '-l', 'debug' ]
|
36
|
-
cli = MyCLI.new
|
37
|
-
cli.parse_options
|
38
|
-
cli.config[:config_file] # 'foo.rb'
|
39
|
-
cli.config[:log_level] # :debug
|
40
|
-
|
41
|
-
If you are using this in conjunction with Mixlib::Config, you can do something like this (building on the above definition):
|
42
|
-
|
43
|
-
class MyConfig
|
44
|
-
extend(Mixlib::Config)
|
45
|
-
|
46
|
-
log_level :info
|
47
|
-
config_file "default.rb"
|
48
|
-
end
|
49
|
-
|
50
|
-
class MyCLI
|
51
|
-
def run(argv=ARGV)
|
52
|
-
parse_options(argv)
|
53
|
-
MyConfig.merge!(config)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
c = MyCLI.new
|
58
|
-
# ARGV = [ '-l', 'debug' ]
|
59
|
-
c.run
|
60
|
-
MyConfig[:log_level] # :debug
|
61
|
-
|
62
|
-
Available arguments to 'option':
|
63
|
-
|
64
|
-
:short:: The short option, just like from optparse. Example: "-l LEVEL"
|
65
|
-
:long:: The long option, just like from optparse. Example: "--level LEVEL"
|
66
|
-
:description:: The description for this item, just like from optparse.
|
67
|
-
:default:: A default value for this option
|
68
|
-
:required:: Prints a message informing the user of the missing requirement, and exits. Default is false.
|
69
|
-
:on:: Set to :tail to appear at the end, or :head to appear at the top.
|
70
|
-
:boolean:: If this option takes no arguments, set this to true.
|
71
|
-
:show_options:: If you want the option list printed when this option is called, set this to true.
|
72
|
-
:exit:: Exit your program with the exit code when this option is specified. Example: 0
|
73
|
-
:proc:: If set, the configuration value will be set to the return value of this proc.
|
74
|
-
|
75
|
-
=== New in 1.2.2
|
76
|
-
|
77
|
-
:required works, and we now support Ruby-style boolean option negation
|
78
|
-
(e.g. '--no-cookie' will set 'cookie' to false if the option is boolean)
|
79
|
-
|
80
|
-
=== New in 1.2.0
|
81
|
-
|
82
|
-
We no longer destructively manipulate ARGV.
|
83
|
-
|
84
|
-
Have fun!
|