mixlib-cli 1.7.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +25 -0
- data/NOTICE +1 -1
- data/README.md +35 -24
- data/Rakefile +19 -16
- data/lib/mixlib/cli.rb +11 -10
- data/lib/mixlib/cli/version.rb +1 -1
- data/mixlib-cli.gemspec +1 -9
- data/spec/mixlib/cli_spec.rb +145 -125
- data/spec/spec_helper.rb +13 -2
- metadata +5 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: eaf15af5ae6bced46dfe59d89fa37cd935573375fad4982bd1661815c1bdb9a6
|
4
|
+
data.tar.gz: c8ef97ee9a2236e29c3bcd7a6cafaf8564bfa5526972d582b7f4f5dc84305a83
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5d534599c887330bff589b7909b8f89199baa33f557363742b29ffe93a5b3d6bb036efa179ef1b3a4dbfb2391115e8152115bfe48619a1ac037dc4d69532dd8
|
7
|
+
data.tar.gz: d17c1d596c0aec0fdf3e53b7e8f7d7380a34872a8f16ae0cd680725b712ec22b0e77607b45dfa98b9948464c5e793e34a1db43c31d6c13c8b4311bd8d3da1054
|
data/Gemfile
CHANGED
@@ -1,3 +1,28 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
3
|
gemspec
|
4
|
+
|
5
|
+
group :docs do
|
6
|
+
gem "yard"
|
7
|
+
gem "redcarpet"
|
8
|
+
gem "github-markup"
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "master"
|
13
|
+
gem "rspec", "~> 3.0"
|
14
|
+
gem "rake"
|
15
|
+
end
|
16
|
+
|
17
|
+
group :development do
|
18
|
+
gem "pry"
|
19
|
+
gem "pry-byebug"
|
20
|
+
gem "pry-stack_explorer"
|
21
|
+
gem "rb-readline"
|
22
|
+
end
|
23
|
+
|
24
|
+
instance_eval(ENV["GEMFILE_MOD"]) if ENV["GEMFILE_MOD"]
|
25
|
+
|
26
|
+
# If you want to load debugging tools into the bundle exec sandbox,
|
27
|
+
# add these additional dependencies into Gemfile.local
|
28
|
+
eval_gemfile(__FILE__ + ".local") if File.exist?(__FILE__ + ".local")
|
data/NOTICE
CHANGED
data/README.md
CHANGED
@@ -5,34 +5,33 @@
|
|
5
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
6
|
|
7
7
|
```ruby
|
8
|
-
require
|
9
|
-
require 'mixlib/cli'
|
8
|
+
require "mixlib/cli"
|
10
9
|
|
11
10
|
class MyCLI
|
12
11
|
include Mixlib::CLI
|
13
12
|
|
14
13
|
option :config_file,
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
14
|
+
short: "-c CONFIG",
|
15
|
+
long: "--config CONFIG",
|
16
|
+
default: "config.rb",
|
17
|
+
description: "The configuration file to use"
|
19
18
|
|
20
19
|
option :log_level,
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
20
|
+
short: "-l LEVEL",
|
21
|
+
long: "--log_level LEVEL",
|
22
|
+
description: "Set the log level (debug, info, warn, error, fatal)",
|
23
|
+
required: true,
|
24
|
+
in: [:debug, :info, :warn, :error, :fatal],
|
25
|
+
proc: Proc.new { |l| l.to_sym }
|
27
26
|
|
28
27
|
option :help,
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
28
|
+
short: "-h",
|
29
|
+
long: "--help",
|
30
|
+
description: "Show this message",
|
31
|
+
on: :tail,
|
32
|
+
boolean: true,
|
33
|
+
show_options: true,
|
34
|
+
exit: 0
|
36
35
|
|
37
36
|
end
|
38
37
|
|
@@ -54,7 +53,7 @@ class MyConfig
|
|
54
53
|
end
|
55
54
|
|
56
55
|
class MyCLI
|
57
|
-
def run(argv=ARGV)
|
56
|
+
def run(argv = ARGV)
|
58
57
|
parse_options(argv)
|
59
58
|
MyConfig.merge!(config)
|
60
59
|
end
|
@@ -69,10 +68,10 @@ MyConfig[:log_level] # :debug
|
|
69
68
|
Available arguments to 'option':
|
70
69
|
|
71
70
|
- `:short`: The short option, just like from optparse. Example: "-l LEVEL"
|
72
|
-
- `:long`: The long option, just like from optparse.
|
71
|
+
- `:long`: The long option, just like from optparse. Example: "--level LEVEL"
|
73
72
|
- `:description`: The description for this item, just like from optparse.
|
74
73
|
- `:default`: A default value for this option
|
75
|
-
- `:required`: Prints a message informing the user of the missing requirement, and exits.
|
74
|
+
- `:required`: Prints a message informing the user of the missing requirement, and exits. Default is false.
|
76
75
|
- `:on`: Set to :tail to appear at the end, or `:head`: to appear at the top.
|
77
76
|
- `:boolean:`: If this option takes no arguments, set this to true.
|
78
77
|
- `:show_options`: If you want the option list printed when this option is called, set this to true.
|
@@ -89,9 +88,21 @@ cli.parse_options
|
|
89
88
|
cli.cli_arguments # [ 'file1', 'file2', 'file3' ]
|
90
89
|
```
|
91
90
|
|
92
|
-
##
|
91
|
+
## Documentation
|
93
92
|
|
94
|
-
|
93
|
+
All documentation is written using YARD. You can generate a by running:
|
94
|
+
|
95
|
+
```
|
96
|
+
rake docs
|
97
|
+
```
|
98
|
+
|
99
|
+
## Contributing
|
100
|
+
|
101
|
+
For information on contributing to this project please see our [Contributing Documentation](https://github.com/chef/chef/blob/master/CONTRIBUTING.md)
|
102
|
+
|
103
|
+
## License & Copyright
|
104
|
+
|
105
|
+
- Copyright:: Copyright (c) 2008-2018 Chef Software, Inc.
|
95
106
|
- License:: Apache License, Version 2.0
|
96
107
|
|
97
108
|
```text
|
data/Rakefile
CHANGED
@@ -1,27 +1,15 @@
|
|
1
|
-
require "bundler"
|
2
|
-
require "rubygems"
|
3
|
-
require "rubygems/package_task"
|
4
|
-
require "rdoc/task"
|
1
|
+
require "bundler/gem_tasks"
|
5
2
|
require "rspec/core/rake_task"
|
6
3
|
|
7
|
-
|
4
|
+
task default: [:style, :spec]
|
8
5
|
|
9
|
-
|
6
|
+
Bundler::GemHelper.install_tasks
|
10
7
|
|
11
8
|
desc "Run specs"
|
12
9
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
13
10
|
spec.pattern = "spec/**/*_spec.rb"
|
14
11
|
end
|
15
12
|
|
16
|
-
gem_spec = eval(File.read("mixlib-cli.gemspec"))
|
17
|
-
|
18
|
-
RDoc::Task.new do |rdoc|
|
19
|
-
rdoc.rdoc_dir = "rdoc"
|
20
|
-
rdoc.title = "mixlib-cli #{gem_spec.version}"
|
21
|
-
rdoc.rdoc_files.include("README*")
|
22
|
-
rdoc.rdoc_files.include("lib/**/*.rb")
|
23
|
-
end
|
24
|
-
|
25
13
|
begin
|
26
14
|
require "chefstyle"
|
27
15
|
require "rubocop/rake_task"
|
@@ -29,5 +17,20 @@ begin
|
|
29
17
|
task.options += ["--display-cop-names", "--no-color"]
|
30
18
|
end
|
31
19
|
rescue LoadError
|
32
|
-
puts "chefstyle/rubocop is not available.
|
20
|
+
puts "chefstyle/rubocop is not available. bundle install first to make sure all dependencies are installed."
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
require "yard"
|
25
|
+
YARD::Rake::YardocTask.new(:docs)
|
26
|
+
rescue LoadError
|
27
|
+
puts "yard is not available. bundle install first to make sure all dependencies are installed."
|
28
|
+
end
|
29
|
+
|
30
|
+
task :console do
|
31
|
+
require "irb"
|
32
|
+
require "irb/completion"
|
33
|
+
require "mixlib/cli"
|
34
|
+
ARGV.clear
|
35
|
+
IRB.start
|
33
36
|
end
|
data/lib/mixlib/cli.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
|
-
# Author:: Adam Jacob (<adam@
|
3
|
-
# Copyright:: Copyright (c) 2008
|
2
|
+
# Author:: Adam Jacob (<adam@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2008-2016 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -41,7 +41,7 @@ module Mixlib
|
|
41
41
|
|
42
42
|
module InheritMethods
|
43
43
|
def inherited(receiver)
|
44
|
-
receiver.options = deep_dup(
|
44
|
+
receiver.options = deep_dup(options)
|
45
45
|
receiver.extend(Mixlib::CLI::InheritMethods)
|
46
46
|
end
|
47
47
|
|
@@ -210,7 +210,7 @@ module Mixlib
|
|
210
210
|
config_opts[:exit] ||= nil
|
211
211
|
config_opts[:in] ||= nil
|
212
212
|
|
213
|
-
if config_opts.
|
213
|
+
if config_opts.key?(:default)
|
214
214
|
defaults_container[config_key] = config_opts[:default]
|
215
215
|
end
|
216
216
|
end
|
@@ -231,7 +231,7 @@ module Mixlib
|
|
231
231
|
|
232
232
|
# Deal with any required values
|
233
233
|
options.each do |opt_key, opt_value|
|
234
|
-
if opt_value[:required] && !config.
|
234
|
+
if opt_value[:required] && !config.key?(opt_key)
|
235
235
|
reqarg = opt_value[:short] || opt_value[:long]
|
236
236
|
puts "You must supply #{reqarg}!"
|
237
237
|
puts @opt_parser
|
@@ -241,7 +241,7 @@ module Mixlib
|
|
241
241
|
unless opt_value[:in].kind_of?(Array)
|
242
242
|
raise(ArgumentError, "Options config key :in must receive an Array")
|
243
243
|
end
|
244
|
-
if !opt_value[:in].include?(config[opt_key])
|
244
|
+
if config[opt_key] && !opt_value[:in].include?(config[opt_key])
|
245
245
|
reqarg = opt_value[:short] || opt_value[:long]
|
246
246
|
puts "#{reqarg}: #{config[opt_key]} is not included in the list ['#{opt_value[:in].join("', '")}'] "
|
247
247
|
puts @opt_parser
|
@@ -308,12 +308,13 @@ module Mixlib
|
|
308
308
|
def build_option_arguments(opt_setting)
|
309
309
|
arguments = Array.new
|
310
310
|
|
311
|
-
arguments << opt_setting[:short] if opt_setting.
|
312
|
-
arguments << opt_setting[:long] if opt_setting.
|
313
|
-
if opt_setting.
|
314
|
-
description = opt_setting[:description]
|
311
|
+
arguments << opt_setting[:short] if opt_setting.key?(:short)
|
312
|
+
arguments << opt_setting[:long] if opt_setting.key?(:long)
|
313
|
+
if opt_setting.key?(:description)
|
314
|
+
description = opt_setting[:description].dup
|
315
315
|
description << " (required)" if opt_setting[:required]
|
316
316
|
description << " (included in ['#{opt_setting[:in].join("', '")}'])" if opt_setting[:in]
|
317
|
+
opt_setting[:description] = description
|
317
318
|
arguments << description
|
318
319
|
end
|
319
320
|
|
data/lib/mixlib/cli/version.rb
CHANGED
data/mixlib-cli.gemspec
CHANGED
@@ -4,8 +4,6 @@ require "mixlib/cli/version"
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "mixlib-cli"
|
6
6
|
s.version = Mixlib::CLI::VERSION
|
7
|
-
s.platform = Gem::Platform::RUBY
|
8
|
-
s.has_rdoc = true
|
9
7
|
s.extra_rdoc_files = ["README.md", "LICENSE", "NOTICE"]
|
10
8
|
s.summary = "A simple mixin for CLI interfaces, including option parsing"
|
11
9
|
s.description = s.summary
|
@@ -13,13 +11,7 @@ Gem::Specification.new do |s|
|
|
13
11
|
s.email = "info@chef.io"
|
14
12
|
s.homepage = "https://www.chef.io"
|
15
13
|
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"
|
14
|
+
s.required_ruby_version = ">= 2.5"
|
23
15
|
|
24
16
|
s.require_path = "lib"
|
25
17
|
s.files = %w{LICENSE README.md Gemfile Rakefile NOTICE} + Dir.glob("*.gemspec") +
|
data/spec/mixlib/cli_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
|
-
# Author:: Adam Jacob (<adam@
|
3
|
-
# Copyright:: Copyright (c) 2008
|
2
|
+
# Author:: Adam Jacob (<adam@chef.io>)
|
3
|
+
# Copyright:: Copyright (c) 2008-2016 Chef Software, Inc.
|
4
4
|
# License:: Apache License, Version 2.0
|
5
5
|
#
|
6
6
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -26,33 +26,33 @@ describe Mixlib::CLI do
|
|
26
26
|
|
27
27
|
describe "class method" do
|
28
28
|
describe "option" do
|
29
|
-
it "
|
30
|
-
TestCLI.option(:config_file, :
|
29
|
+
it "allows you to set a config option with a hash" do
|
30
|
+
expect(TestCLI.option(:config_file, short: "-c CONFIG")).to eql({ short: "-c CONFIG" })
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
describe "options" do
|
35
|
-
it "
|
36
|
-
TestCLI.option(:config_file, :
|
37
|
-
TestCLI.options.
|
35
|
+
it "returns the current options hash" do
|
36
|
+
TestCLI.option(:config_file, short: "-c CONFIG")
|
37
|
+
expect(TestCLI.options).to eql({ config_file: { short: "-c CONFIG" } })
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
describe "options=" do
|
42
|
-
it "
|
43
|
-
TestCLI.options = { :
|
44
|
-
TestCLI.options.
|
42
|
+
it "allows you to set the full options with a single hash" do
|
43
|
+
TestCLI.options = { config_file: { short: "-c CONFIG" } }
|
44
|
+
expect(TestCLI.options).to eql({ config_file: { short: "-c CONFIG" } })
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
describe "banner" do
|
49
|
-
it "
|
50
|
-
TestCLI.banner.
|
49
|
+
it "has a default value" do
|
50
|
+
expect(TestCLI.banner).to match(/^Usage: (.+) \(options\)$/)
|
51
51
|
end
|
52
52
|
|
53
|
-
it "
|
53
|
+
it "allows you to set the banner" do
|
54
54
|
TestCLI.banner("Usage: foo")
|
55
|
-
TestCLI.banner.
|
55
|
+
expect(TestCLI.banner).to eql("Usage: foo")
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -64,189 +64,209 @@ describe Mixlib::CLI do
|
|
64
64
|
end
|
65
65
|
|
66
66
|
describe "initialize" do
|
67
|
-
it "
|
68
|
-
@cli.banner.
|
67
|
+
it "sets the banner to the class defined banner" do
|
68
|
+
expect(@cli.banner).to eql(TestCLI.banner)
|
69
69
|
end
|
70
70
|
|
71
|
-
it "
|
72
|
-
TestCLI.option(:config_file, :
|
71
|
+
it "sets the options to the class defined options, plus defaults" do
|
72
|
+
TestCLI.option(:config_file, short: "-l LOG")
|
73
73
|
cli = TestCLI.new
|
74
|
-
cli.options.
|
75
|
-
:
|
76
|
-
:
|
77
|
-
:
|
78
|
-
:
|
79
|
-
:
|
80
|
-
:
|
81
|
-
:
|
82
|
-
:
|
83
|
-
:
|
74
|
+
expect(cli.options).to eql({
|
75
|
+
config_file: {
|
76
|
+
short: "-l LOG",
|
77
|
+
on: :on,
|
78
|
+
boolean: false,
|
79
|
+
required: false,
|
80
|
+
proc: nil,
|
81
|
+
show_options: false,
|
82
|
+
exit: nil,
|
83
|
+
in: nil,
|
84
84
|
},
|
85
|
-
}
|
85
|
+
})
|
86
86
|
end
|
87
87
|
|
88
|
-
it "
|
89
|
-
TestCLI.option(:config_file, :
|
88
|
+
it "sets the default config value for any options that include it" do
|
89
|
+
TestCLI.option(:config_file, short: "-l LOG", default: :debug)
|
90
90
|
@cli = TestCLI.new
|
91
|
-
@cli.config[:config_file].
|
91
|
+
expect(@cli.config[:config_file]).to eql(:debug)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
95
|
describe "opt_parser" do
|
96
96
|
|
97
|
-
it "
|
98
|
-
@cli.opt_parser.banner.
|
97
|
+
it "sets the banner in opt_parse" do
|
98
|
+
expect(@cli.opt_parser.banner).to eql(@cli.banner)
|
99
99
|
end
|
100
100
|
|
101
|
-
it "
|
102
|
-
TestCLI.option(:config_file, :
|
101
|
+
it "presents the arguments in the banner" do
|
102
|
+
TestCLI.option(:config_file, short: "-l LOG")
|
103
103
|
@cli = TestCLI.new
|
104
|
-
@cli.opt_parser.to_s.
|
104
|
+
expect(@cli.opt_parser.to_s).to match(/-l LOG/)
|
105
105
|
end
|
106
106
|
|
107
|
-
it "
|
108
|
-
TestCLI.option(:config_file, :
|
109
|
-
TestCLI.option(:help, :
|
107
|
+
it "honors :on => :tail options in the banner" do
|
108
|
+
TestCLI.option(:config_file, short: "-l LOG")
|
109
|
+
TestCLI.option(:help, short: "-h", boolean: true, on: :tail)
|
110
110
|
@cli = TestCLI.new
|
111
|
-
@cli.opt_parser.to_s.split("\n").last.
|
111
|
+
expect(@cli.opt_parser.to_s.split("\n").last).to match(/-h/)
|
112
112
|
end
|
113
113
|
|
114
|
-
it "
|
115
|
-
TestCLI.option(:config_file, :
|
116
|
-
TestCLI.option(:help, :
|
114
|
+
it "honors :on => :head options in the banner" do
|
115
|
+
TestCLI.option(:config_file, short: "-l LOG")
|
116
|
+
TestCLI.option(:help, short: "-h", boolean: true, on: :head)
|
117
117
|
@cli = TestCLI.new
|
118
|
-
@cli.opt_parser.to_s.split("\n")[1].
|
118
|
+
expect(@cli.opt_parser.to_s.split("\n")[1]).to match(/-h/)
|
119
119
|
end
|
120
120
|
|
121
|
-
it "
|
122
|
-
TestCLI.option(:alpha, :
|
123
|
-
TestCLI.option(:beta, :
|
124
|
-
TestCLI.option(:zeta, :
|
121
|
+
it "presents the arguments in alphabetical order in the banner" do
|
122
|
+
TestCLI.option(:alpha, short: "-a ALPHA")
|
123
|
+
TestCLI.option(:beta, short: "-b BETA")
|
124
|
+
TestCLI.option(:zeta, short: "-z ZETA")
|
125
125
|
@cli = TestCLI.new
|
126
126
|
output_lines = @cli.opt_parser.to_s.split("\n")
|
127
|
-
output_lines[1].
|
128
|
-
output_lines[2].
|
129
|
-
output_lines[3].
|
127
|
+
expect(output_lines[1]).to match(/-a ALPHA/)
|
128
|
+
expect(output_lines[2]).to match(/-b BETA/)
|
129
|
+
expect(output_lines[3]).to match(/-z ZETA/)
|
130
130
|
end
|
131
131
|
|
132
132
|
end
|
133
133
|
|
134
134
|
describe "parse_options" do
|
135
|
-
it "
|
136
|
-
TestCLI.option(:config_file, :
|
135
|
+
it "sets the corresponding config value for non-boolean arguments" do
|
136
|
+
TestCLI.option(:config_file, short: "-c CONFIG")
|
137
137
|
@cli = TestCLI.new
|
138
138
|
@cli.parse_options([ "-c", "foo.rb" ])
|
139
|
-
@cli.config[:config_file].
|
139
|
+
expect(@cli.config[:config_file]).to eql("foo.rb")
|
140
140
|
end
|
141
141
|
|
142
|
-
it "
|
142
|
+
it "sets the corresponding config value according to a supplied proc" do
|
143
143
|
TestCLI.option(:number,
|
144
|
-
:
|
145
|
-
:
|
144
|
+
short: "-n NUMBER",
|
145
|
+
proc: Proc.new { |config| config.to_i + 2 }
|
146
146
|
)
|
147
147
|
@cli = TestCLI.new
|
148
148
|
@cli.parse_options([ "-n", "2" ])
|
149
|
-
@cli.config[:number].
|
149
|
+
expect(@cli.config[:number]).to eql(4)
|
150
150
|
end
|
151
151
|
|
152
|
-
it "
|
152
|
+
it "passes the existing value to two-argument procs" do
|
153
153
|
TestCLI.option(:number,
|
154
|
-
:
|
155
|
-
:
|
154
|
+
short: "-n NUMBER",
|
155
|
+
proc: Proc.new { |value, existing| existing ||= []; existing << value; existing }
|
156
156
|
)
|
157
157
|
@cli = TestCLI.new
|
158
158
|
@cli.parse_options([ "-n", "2", "-n", "3" ])
|
159
|
-
@cli.config[:number].
|
159
|
+
expect(@cli.config[:number]).to eql(%w{2 3})
|
160
160
|
end
|
161
161
|
|
162
|
-
it "
|
163
|
-
TestCLI.option(:i_am_boolean, :
|
162
|
+
it "sets the corresponding config value to true for boolean arguments" do
|
163
|
+
TestCLI.option(:i_am_boolean, short: "-i", boolean: true)
|
164
164
|
@cli = TestCLI.new
|
165
165
|
@cli.parse_options([ "-i" ])
|
166
|
-
@cli.config[:i_am_boolean].
|
166
|
+
expect(@cli.config[:i_am_boolean]).to be true
|
167
167
|
end
|
168
168
|
|
169
|
-
it "
|
170
|
-
TestCLI.option(:i_am_boolean, :
|
169
|
+
it "sets the corresponding config value to false when a boolean is prefixed with --no" do
|
170
|
+
TestCLI.option(:i_am_boolean, long: "--[no-]bool", boolean: true)
|
171
171
|
@cli = TestCLI.new
|
172
172
|
@cli.parse_options([ "--no-bool" ])
|
173
|
-
@cli.config[:i_am_boolean].
|
173
|
+
expect(@cli.config[:i_am_boolean]).to be false
|
174
174
|
end
|
175
175
|
|
176
|
-
it "
|
177
|
-
TestCLI.option(:i_am_exit, :
|
176
|
+
it "exits if a config option has :exit set" do
|
177
|
+
TestCLI.option(:i_am_exit, short: "-x", boolean: true, exit: 0)
|
178
178
|
@cli = TestCLI.new
|
179
|
-
lambda { @cli.parse_options(["-x"]) }.
|
179
|
+
expect(lambda { @cli.parse_options(["-x"]) }).to raise_error(SystemExit)
|
180
180
|
end
|
181
181
|
|
182
|
-
it "
|
183
|
-
TestCLI.option(:require_me, :
|
182
|
+
it "exits if a required option is missing" do
|
183
|
+
TestCLI.option(:require_me, short: "-r", boolean: true, required: true)
|
184
184
|
@cli = TestCLI.new
|
185
|
-
lambda { @cli.parse_options([]) }.
|
185
|
+
expect(lambda { @cli.parse_options([]) }).to raise_error(SystemExit)
|
186
186
|
end
|
187
187
|
|
188
|
-
it "
|
189
|
-
TestCLI.option(:inclusion, :
|
188
|
+
it "exits if option is not included in the list and required" do
|
189
|
+
TestCLI.option(:inclusion, short: "-i val", in: %w{one two}, required: true)
|
190
190
|
@cli = TestCLI.new
|
191
|
-
lambda { @cli.parse_options(["-i", "three"]) }.
|
191
|
+
expect(lambda { @cli.parse_options(["-i", "three"]) }).to raise_error(SystemExit)
|
192
192
|
end
|
193
193
|
|
194
|
-
it "
|
195
|
-
TestCLI.option(:inclusion, :
|
194
|
+
it "exits if option is not included in the list and not required" do
|
195
|
+
TestCLI.option(:inclusion, short: "-i val", in: %w{one two}, required: false)
|
196
196
|
@cli = TestCLI.new
|
197
|
-
lambda { @cli.parse_options(["-i", "three"]) }.
|
197
|
+
expect(lambda { @cli.parse_options(["-i", "three"]) }).to raise_error(SystemExit)
|
198
198
|
end
|
199
199
|
|
200
|
-
it "
|
201
|
-
TestCLI.option(:inclusion, :
|
200
|
+
it "doesn't exit if option is nil and not required" do
|
201
|
+
TestCLI.option(:inclusion, short: "-i val", in: %w{one two}, required: false)
|
202
|
+
@cli = TestCLI.new
|
203
|
+
expect do
|
204
|
+
expect(@cli.parse_options([])).to eql []
|
205
|
+
end.to_not raise_error
|
206
|
+
end
|
207
|
+
|
208
|
+
it "exit if option is nil and required" do
|
209
|
+
TestCLI.option(:inclusion, short: "-i val", in: %w{one two}, required: true)
|
210
|
+
@cli = TestCLI.new
|
211
|
+
expect(lambda { @cli.parse_options([]) }).to raise_error(SystemExit)
|
212
|
+
end
|
213
|
+
|
214
|
+
it "raises ArgumentError if options key :in is not an array" do
|
215
|
+
TestCLI.option(:inclusion, short: "-i val", in: "foo", required: true)
|
216
|
+
@cli = TestCLI.new
|
217
|
+
expect(lambda { @cli.parse_options(["-i", "three"]) }).to raise_error(ArgumentError)
|
218
|
+
end
|
219
|
+
|
220
|
+
it "doesn't exit if option is included in the list" do
|
221
|
+
TestCLI.option(:inclusion, short: "-i val", in: %w{one two}, required: true)
|
202
222
|
@cli = TestCLI.new
|
203
223
|
@cli.parse_options(["-i", "one"])
|
204
|
-
@cli.config[:inclusion].
|
224
|
+
expect(@cli.config[:inclusion]).to eql("one")
|
205
225
|
end
|
206
226
|
|
207
|
-
it "
|
208
|
-
TestCLI.option(:inclusion, :
|
227
|
+
it "changes description if :in key is specified" do
|
228
|
+
TestCLI.option(:inclusion, short: "-i val", in: %w{one two}, description: "desc", required: false)
|
209
229
|
@cli = TestCLI.new
|
210
230
|
@cli.parse_options(["-i", "one"])
|
211
|
-
@cli.options[:inclusion][:description].
|
231
|
+
expect(@cli.options[:inclusion][:description]).to eql("desc (included in ['one', 'two'])")
|
212
232
|
end
|
213
233
|
|
214
|
-
it "
|
215
|
-
TestCLI.option(:require_me, :
|
234
|
+
it "doesn't exit if a required option is specified" do
|
235
|
+
TestCLI.option(:require_me, short: "-r", boolean: true, required: true)
|
216
236
|
@cli = TestCLI.new
|
217
237
|
@cli.parse_options(["-r"])
|
218
|
-
@cli.config[:require_me].
|
238
|
+
expect(@cli.config[:require_me]).to be true
|
219
239
|
end
|
220
240
|
|
221
|
-
it "
|
222
|
-
TestCLI.option(:require_me, :
|
241
|
+
it "doesn't exit if a required boolean option is specified and false" do
|
242
|
+
TestCLI.option(:require_me, long: "--[no-]req", boolean: true, required: true)
|
223
243
|
@cli = TestCLI.new
|
224
244
|
@cli.parse_options(["--no-req"])
|
225
|
-
@cli.config[:require_me].
|
245
|
+
expect(@cli.config[:require_me]).to be false
|
226
246
|
end
|
227
247
|
|
228
|
-
it "
|
229
|
-
TestCLI.option(:require_me, :
|
248
|
+
it "doesn't exit if a required option is specified and empty" do
|
249
|
+
TestCLI.option(:require_me, short: "-r VALUE", required: true)
|
230
250
|
@cli = TestCLI.new
|
231
251
|
@cli.parse_options(["-r", ""])
|
232
|
-
@cli.config[:require_me].
|
252
|
+
expect(@cli.config[:require_me]).to eql("")
|
233
253
|
end
|
234
254
|
|
235
|
-
it "
|
236
|
-
TestCLI.option(:config_file, :
|
255
|
+
it "preserves all of the commandline arguments, ARGV" do
|
256
|
+
TestCLI.option(:config_file, short: "-c CONFIG")
|
237
257
|
@cli = TestCLI.new
|
238
258
|
argv_old = ARGV.dup
|
239
259
|
ARGV.replace ["-c", "foo.rb"]
|
240
260
|
@cli.parse_options()
|
241
|
-
ARGV.
|
261
|
+
expect(ARGV).to eql(["-c", "foo.rb"])
|
242
262
|
ARGV.replace argv_old
|
243
263
|
end
|
244
264
|
|
245
|
-
it "
|
246
|
-
TestCLI.option(:party, :
|
265
|
+
it "preserves and return any un-parsed elements" do
|
266
|
+
TestCLI.option(:party, short: "-p LOCATION")
|
247
267
|
@cli = TestCLI.new
|
248
|
-
@cli.parse_options([ "easy", "-p", "opscode", "hard" ]).
|
249
|
-
@cli.cli_arguments.
|
268
|
+
expect(@cli.parse_options([ "easy", "-p", "opscode", "hard" ])).to eql(%w{easy hard})
|
269
|
+
expect(@cli.cli_arguments).to eql(%w{easy hard})
|
250
270
|
end
|
251
271
|
end
|
252
272
|
end
|
@@ -254,68 +274,68 @@ describe Mixlib::CLI do
|
|
254
274
|
context "when configured to separate default options" do
|
255
275
|
before do
|
256
276
|
TestCLI.use_separate_default_options true
|
257
|
-
TestCLI.option(:defaulter, :
|
277
|
+
TestCLI.option(:defaulter, short: "-D SOMETHING", default: "this is the default")
|
258
278
|
@cli = TestCLI.new
|
259
279
|
end
|
260
280
|
|
261
281
|
it "sets default values on the `default` hash" do
|
262
282
|
@cli.parse_options([])
|
263
|
-
@cli.default_config[:defaulter].
|
264
|
-
@cli.config[:defaulter].
|
283
|
+
expect(@cli.default_config[:defaulter]).to eql("this is the default")
|
284
|
+
expect(@cli.config[:defaulter]).to be_nil
|
265
285
|
end
|
266
286
|
|
267
287
|
it "sets parsed values on the `config` hash" do
|
268
288
|
@cli.parse_options(%w{-D not-default})
|
269
|
-
@cli.default_config[:defaulter].
|
270
|
-
@cli.config[:defaulter].
|
289
|
+
expect(@cli.default_config[:defaulter]).to eql("this is the default")
|
290
|
+
expect(@cli.config[:defaulter]).to eql("not-default")
|
271
291
|
end
|
272
292
|
|
273
293
|
end
|
274
294
|
|
275
295
|
context "when subclassed" do
|
276
296
|
before do
|
277
|
-
TestCLI.options = { :
|
297
|
+
TestCLI.options = { arg1: { boolean: true } }
|
278
298
|
end
|
279
299
|
|
280
|
-
it "
|
300
|
+
it "retains previously defined options from parent" do
|
281
301
|
class T1 < TestCLI
|
282
|
-
option :arg2, :
|
302
|
+
option :arg2, boolean: true
|
283
303
|
end
|
284
|
-
T1.options[:arg1].
|
285
|
-
T1.options[:arg2].
|
286
|
-
TestCLI.options[:arg2].
|
304
|
+
expect(T1.options[:arg1]).to be_a(Hash)
|
305
|
+
expect(T1.options[:arg2]).to be_a(Hash)
|
306
|
+
expect(TestCLI.options[:arg2]).to be_nil
|
287
307
|
end
|
288
308
|
|
289
|
-
it "
|
309
|
+
it "isn't able to modify parent classes options" do
|
290
310
|
class T2 < TestCLI
|
291
|
-
option :arg2, :
|
311
|
+
option :arg2, boolean: true
|
292
312
|
end
|
293
313
|
T2.options[:arg1][:boolean] = false
|
294
|
-
T2.options[:arg1][:boolean].
|
295
|
-
TestCLI.options[:arg1][:boolean].
|
314
|
+
expect(T2.options[:arg1][:boolean]).to be false
|
315
|
+
expect(TestCLI.options[:arg1][:boolean]).to be true
|
296
316
|
end
|
297
317
|
|
298
|
-
it "
|
318
|
+
it "passes its options onto child" do
|
299
319
|
class T3 < TestCLI
|
300
|
-
option :arg2, :
|
320
|
+
option :arg2, boolean: true
|
301
321
|
end
|
302
322
|
class T4 < T3
|
303
|
-
option :arg3, :
|
323
|
+
option :arg3, boolean: true
|
304
324
|
end
|
305
325
|
3.times do |i|
|
306
|
-
T4.options["arg#{i + 1}".to_sym].
|
326
|
+
expect(T4.options["arg#{i + 1}".to_sym]).to be_a(Hash)
|
307
327
|
end
|
308
328
|
end
|
309
329
|
|
310
|
-
it "
|
330
|
+
it "also works with an option that's an array" do
|
311
331
|
class T5 < TestCLI
|
312
|
-
option :arg2, :
|
332
|
+
option :arg2, default: []
|
313
333
|
end
|
314
334
|
|
315
335
|
class T6 < T5
|
316
336
|
end
|
317
337
|
|
318
|
-
T6.options[:arg2].
|
338
|
+
expect(T6.options[:arg2]).to be_a(Hash)
|
319
339
|
end
|
320
340
|
|
321
341
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -8,8 +8,19 @@ class TestCLI
|
|
8
8
|
end
|
9
9
|
|
10
10
|
RSpec.configure do |config|
|
11
|
-
|
11
|
+
# Use documentation format
|
12
|
+
config.formatter = "doc"
|
13
|
+
|
14
|
+
# Use color in STDOUT
|
15
|
+
config.color = true
|
16
|
+
|
17
|
+
# Use color not only in STDOUT but also in pagers and files
|
18
|
+
config.tty = true
|
19
|
+
|
20
|
+
# run the examples in random order
|
21
|
+
config.order = :rand
|
22
|
+
|
23
|
+
config.filter_run focus: true
|
12
24
|
config.run_all_when_everything_filtered = true
|
13
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
25
|
config.warnings = true
|
15
26
|
end
|
metadata
CHANGED
@@ -1,71 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixlib-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.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:
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rake
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "<"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '11.0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "<"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '11.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rspec
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2.14'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2.14'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rdoc
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
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'
|
11
|
+
date: 2019-01-04 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
69
13
|
description: A simple mixin for CLI interfaces, including option parsing
|
70
14
|
email: info@chef.io
|
71
15
|
executables: []
|
@@ -97,7 +41,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
97
41
|
requirements:
|
98
42
|
- - ">="
|
99
43
|
- !ruby/object:Gem::Version
|
100
|
-
version: '
|
44
|
+
version: '2.5'
|
101
45
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
46
|
requirements:
|
103
47
|
- - ">="
|
@@ -105,7 +49,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
105
49
|
version: '0'
|
106
50
|
requirements: []
|
107
51
|
rubyforge_project:
|
108
|
-
rubygems_version: 2.
|
52
|
+
rubygems_version: 2.7.6
|
109
53
|
signing_key:
|
110
54
|
specification_version: 4
|
111
55
|
summary: A simple mixin for CLI interfaces, including option parsing
|