mixlib-cli 1.7.0 → 2.0.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 +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
|