cri 2.5.0 → 2.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 +5 -13
- data/Gemfile +7 -0
- data/Gemfile.lock +29 -5
- data/NEWS.md +5 -0
- data/README.adoc +42 -2
- data/Rakefile +6 -26
- data/cri.gemspec +1 -3
- data/lib/cri.rb +3 -0
- data/lib/cri/command.rb +14 -5
- data/lib/cri/command_dsl.rb +47 -26
- data/lib/cri/command_runner.rb +2 -0
- data/lib/cri/core_ext/string.rb +1 -0
- data/lib/cri/help_renderer.rb +9 -0
- data/lib/cri/option_parser.rb +9 -3
- data/lib/cri/version.rb +3 -1
- data/test/helper.rb +8 -0
- data/test/test_command.rb +18 -1
- data/test/test_command_dsl.rb +58 -11
- data/test/test_command_runner.rb +32 -0
- data/test/test_option_parser.rb +13 -1
- metadata +14 -41
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MjkxMmY1ZDA1M2ExNDUxYmUxOTYyNjVjZTE3OWExM2Y1NmVhODg2Mg==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0b5c4be8a90bd61c37d60ee1a789c51147f3d096
|
4
|
+
data.tar.gz: 19f03a77cb1414c4c5ae591d47a93027642160db
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MWIwYWNlNzI4Njk3Y2JlYTFkNDI4NDkyNGQ0YmVhMWE5Mzk1YjFhM2VjZDBm
|
11
|
-
ZjMxZmYzMDVkMzM2MGQ1OTVhYmI4NDUxMTFiNWEyZDU5MGQ5ZWE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MmEwYjAzNDVhYzg0MWExM2MyODhmMzJlMDE1ZDkwY2U4Y2U2ZGFkNjYxZjk5
|
14
|
-
YjYxNGMxNTJlYjk5N2U0MDRkYzYyNDg3Mjc0NjlhODg5MDkyNGFmNWZlYTU2
|
15
|
-
YjRlY2EyNGU0NjlhYWM2NTMzZmE1MGU1MjRkMDRkNjZiODFiYjc=
|
6
|
+
metadata.gz: 592d029e4b6294136592855225f57340d18f0e75511e01fed4ff1f14e2babb1f01bb8929671b96eefc2e373f4046d2aa283fe539dea65ef932a48919dea30ced
|
7
|
+
data.tar.gz: 0c402294f210d83b2ed2680b59e01303be52dd097a932c65169cee955684be620a5364db00ef1fd72abfce735d7b4a1dc7ff581b4c5f159b9380e7870fa24dec
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,21 +1,45 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cri (2.
|
5
|
-
colored (
|
4
|
+
cri (2.6.0)
|
5
|
+
colored (~> 1.2)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
+
asciidoctor (0.1.4)
|
10
11
|
colored (1.2)
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
coveralls (0.7.0)
|
13
|
+
multi_json (~> 1.3)
|
14
|
+
rest-client
|
15
|
+
simplecov (>= 0.7)
|
16
|
+
term-ansicolor
|
17
|
+
thor
|
18
|
+
docile (1.1.3)
|
19
|
+
mime-types (2.2)
|
20
|
+
minitest (5.3.2)
|
21
|
+
multi_json (1.9.2)
|
22
|
+
rake (10.2.2)
|
23
|
+
rest-client (1.6.7)
|
24
|
+
mime-types (>= 1.16)
|
25
|
+
simplecov (0.8.2)
|
26
|
+
docile (~> 1.1.0)
|
27
|
+
multi_json
|
28
|
+
simplecov-html (~> 0.8.0)
|
29
|
+
simplecov-html (0.8.0)
|
30
|
+
term-ansicolor (1.3.0)
|
31
|
+
tins (~> 1.0)
|
32
|
+
thor (0.19.1)
|
33
|
+
tins (1.0.1)
|
34
|
+
yard (0.8.7.4)
|
14
35
|
|
15
36
|
PLATFORMS
|
16
37
|
ruby
|
17
38
|
|
18
39
|
DEPENDENCIES
|
40
|
+
asciidoctor
|
41
|
+
bundler (~> 1.6)
|
42
|
+
coveralls
|
19
43
|
cri!
|
20
44
|
minitest
|
21
45
|
rake
|
data/NEWS.md
CHANGED
data/README.adoc
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
= Cri =
|
2
2
|
|
3
|
+
link:http://rubygems.org/gems/cri[image:http://img.shields.io/gem/v/cri.svg[]]
|
4
|
+
link:https://travis-ci.org/ddfreyne/cri[image:http://img.shields.io/travis/ddfreyne/cri.svg[]]
|
5
|
+
link:https://coveralls.io/r/ddfreyne/cri[image:http://img.shields.io/coveralls/ddfreyne/cri.svg[]]
|
6
|
+
link:https://codeclimate.com/github/ddfreyne/cri[image:http://img.shields.io/codeclimate/github/ddfreyne/cri.svg[]]
|
7
|
+
link:http://inch-pages.github.io/github/ddfreyne/cri/[image:http://inch-pages.github.io/github/ddfreyne/cri.png[]]
|
8
|
+
|
3
9
|
Cri is a library for building easy-to-use commandline tools with support for
|
4
10
|
nested commands.
|
5
11
|
|
@@ -25,7 +31,7 @@ command = Cri::Command.define do
|
|
25
31
|
exit 0
|
26
32
|
end
|
27
33
|
flag nil, :more, 'do even more stuff'
|
28
|
-
option :s, :stuff, 'specify stuff to do', :
|
34
|
+
option :s, :stuff, 'specify stuff to do', argument: :required
|
29
35
|
|
30
36
|
run do |opts, args, cmd|
|
31
37
|
stuff = opts.fetch(:stuff, 'generic stuff')
|
@@ -64,6 +70,8 @@ options:
|
|
64
70
|
-s --stuff specify stuff to do
|
65
71
|
--------------------------------------------------------------------------------
|
66
72
|
|
73
|
+
=== General command metadata ===
|
74
|
+
|
67
75
|
Let’s disect the command definition and start with the first five lines:
|
68
76
|
|
69
77
|
[source,ruby]
|
@@ -83,6 +91,8 @@ the supercommand, because the latter will be automatically prepended.
|
|
83
91
|
|
84
92
|
Aliases don’t make sense for root commands, but for subcommands they do.
|
85
93
|
|
94
|
+
=== Command-line options ===
|
95
|
+
|
86
96
|
The next few lines contain the command’s option definitions:
|
87
97
|
|
88
98
|
[source,ruby]
|
@@ -92,7 +102,7 @@ flag :h, :help, 'show help for this command' do |value, cmd|
|
|
92
102
|
exit 0
|
93
103
|
end
|
94
104
|
flag nil, :more, 'do even more stuff'
|
95
|
-
option :s, :stuff, 'specify stuff to do', :
|
105
|
+
option :s, :stuff, 'specify stuff to do', argument: :required
|
96
106
|
--------------------------------------------------------------------------------
|
97
107
|
|
98
108
|
Options can be defined using the following methods:
|
@@ -111,6 +121,34 @@ Each of the above methods also take a block, which will be executed when the
|
|
111
121
|
option is found. The argument to the block are the option value (`true` in
|
112
122
|
case the option does not have an argument) and the command.
|
113
123
|
|
124
|
+
==== Multivalued options ====
|
125
|
+
|
126
|
+
Each of these four methods take a `:multiple` option. When set to true, multiple
|
127
|
+
option valus are accepted, and the option values will be stored in an array.
|
128
|
+
|
129
|
+
For example, to parse the command line options string `-o foo.txt -o bar.txt`
|
130
|
+
into an array, so that `options[:output]` contains `[ 'foo.txt', 'bar.txt' ]`,
|
131
|
+
you can use an option definition like this:
|
132
|
+
|
133
|
+
[source,ruby]
|
134
|
+
--------------------------------------------------------------------------------
|
135
|
+
option :o, :output, 'specify output paths', argument: :required, multiple: true
|
136
|
+
--------------------------------------------------------------------------------
|
137
|
+
|
138
|
+
This can also be used for flags (options without arguments). In this case, the
|
139
|
+
length of the options array is relevant.
|
140
|
+
|
141
|
+
For example, you can allow setting the verbosity level using `-v -v -v`. The
|
142
|
+
value of `options[:verbose].size` would then be the verbosity level (three in
|
143
|
+
this example). The option definition would then look like this:
|
144
|
+
|
145
|
+
[source,ruby]
|
146
|
+
--------------------------------------------------------------------------------
|
147
|
+
flag :v, :verbose, 'be verbose (use up to three times)', multiple: true
|
148
|
+
--------------------------------------------------------------------------------
|
149
|
+
|
150
|
+
=== The run block ===
|
151
|
+
|
114
152
|
The last part of the command defines the execution itself:
|
115
153
|
|
116
154
|
[source,ruby]
|
@@ -134,6 +172,8 @@ _command runner_ class (`Cri::CommandRunner`) that will perform the actual
|
|
134
172
|
execution of the command. This makes it easier to break up large run blocks
|
135
173
|
into manageable pieces.
|
136
174
|
|
175
|
+
=== Subcommands ===
|
176
|
+
|
137
177
|
Commands can have subcommands. For example, the `git` commandline tool would be
|
138
178
|
represented by a command that has subcommands named `commit`, `add`, and so on.
|
139
179
|
Commands with subcommands do not use a run block; execution will always be
|
data/Rakefile
CHANGED
@@ -1,44 +1,24 @@
|
|
1
1
|
# encoing: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
# Rake etc
|
6
|
-
require 'rake'
|
7
|
-
require 'minitest'
|
8
|
-
require 'minitest/unit'
|
9
|
-
|
10
|
-
# Cri itself
|
11
|
-
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/lib'))
|
12
|
-
require 'cri'
|
13
|
-
|
14
|
-
##### Documentation
|
15
|
-
|
3
|
+
require 'rake/testtask'
|
16
4
|
require 'yard'
|
17
5
|
|
18
6
|
YARD::Rake::YardocTask.new(:doc) do |yard|
|
19
7
|
yard.files = Dir['lib/**/*.rb']
|
20
8
|
yard.options = [
|
21
9
|
'--markup', 'markdown',
|
22
|
-
'--readme', 'README.
|
10
|
+
'--readme', 'README.adoc',
|
23
11
|
'--files', 'NEWS.md,LICENSE',
|
24
12
|
'--output-dir', 'doc/yardoc',
|
25
13
|
]
|
26
14
|
end
|
27
15
|
|
28
|
-
##### Testing
|
29
|
-
|
30
|
-
desc 'Runs all tests'
|
31
16
|
task :test do
|
32
|
-
|
33
|
-
|
34
|
-
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
|
35
|
-
|
36
|
-
MiniTest.autorun
|
37
|
-
|
38
|
-
require 'test/helper.rb'
|
17
|
+
require './test/helper.rb'
|
39
18
|
|
40
|
-
|
41
|
-
|
19
|
+
FileList['./test/**/test_*.rb', './test/**/*_spec.rb'].each do |fn|
|
20
|
+
require fn
|
21
|
+
end
|
42
22
|
end
|
43
23
|
|
44
24
|
task :default => :test
|
data/cri.gemspec
CHANGED
@@ -21,9 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
|
22
22
|
s.add_dependency('colored', '~> 1.2')
|
23
23
|
|
24
|
-
s.add_development_dependency('
|
25
|
-
s.add_development_dependency('minitest', '~> 5.3')
|
26
|
-
s.add_development_dependency('yard', '~> 0.8')
|
24
|
+
s.add_development_dependency('bundler', '~> 1.6')
|
27
25
|
|
28
26
|
s.rdoc_options = [ '--main', 'README.adoc' ]
|
29
27
|
s.extra_rdoc_files = [ 'LICENSE', 'README.adoc', 'NEWS.md' ]
|
data/lib/cri.rb
CHANGED
data/lib/cri/command.rb
CHANGED
@@ -251,7 +251,7 @@ module Cri
|
|
251
251
|
run_this(opts_and_args, parent_opts)
|
252
252
|
else
|
253
253
|
# Handle options
|
254
|
-
|
254
|
+
handle_options(opts_before_subcmd)
|
255
255
|
|
256
256
|
# Get command
|
257
257
|
if subcmd_name.nil?
|
@@ -282,13 +282,13 @@ module Cri
|
|
282
282
|
# Parse
|
283
283
|
parser = Cri::OptionParser.new(
|
284
284
|
opts_and_args, self.global_option_definitions)
|
285
|
-
|
285
|
+
handle_parser_errors_while { parser.run }
|
286
286
|
local_opts = parser.options
|
287
287
|
global_opts = parent_opts.merge(parser.options)
|
288
288
|
args = parser.arguments
|
289
289
|
|
290
290
|
# Handle options
|
291
|
-
|
291
|
+
handle_options(local_opts)
|
292
292
|
|
293
293
|
# Execute
|
294
294
|
if self.block.nil?
|
@@ -299,16 +299,25 @@ module Cri
|
|
299
299
|
end
|
300
300
|
|
301
301
|
# @return [String] The help text for this command
|
302
|
+
#
|
303
|
+
# @option params [Boolean] :verbose true if the help output should be
|
304
|
+
# verbose, false otherwise.
|
302
305
|
def help(params={})
|
303
306
|
HelpRenderer.new(self, params).render
|
304
307
|
end
|
305
308
|
|
306
309
|
# Compares this command's name to the other given command's name.
|
310
|
+
#
|
311
|
+
# @param [Cri::Command] other The command to compare with
|
312
|
+
#
|
313
|
+
# @return [-1, 0, 1] The result of the comparison between names
|
314
|
+
#
|
315
|
+
# @see Object<=>
|
307
316
|
def <=>(other)
|
308
317
|
self.name <=> other.name
|
309
318
|
end
|
310
319
|
|
311
|
-
|
320
|
+
private
|
312
321
|
|
313
322
|
def handle_options(opts)
|
314
323
|
opts.each_pair do |key, value|
|
@@ -323,7 +332,7 @@ module Cri
|
|
323
332
|
delegate = Cri::Command::OptionParserPartitioningDelegate.new
|
324
333
|
parser = Cri::OptionParser.new(opts_and_args, global_option_definitions)
|
325
334
|
parser.delegate = delegate
|
326
|
-
|
335
|
+
handle_parser_errors_while { parser.run }
|
327
336
|
parser
|
328
337
|
|
329
338
|
# Extract
|
data/lib/cri/command_dsl.rb
CHANGED
@@ -6,6 +6,10 @@ module Cri
|
|
6
6
|
# commands.
|
7
7
|
class CommandDSL
|
8
8
|
|
9
|
+
# Creates a new DSL, intended to be used for building a single command. A
|
10
|
+
# {CommandDSL} instance is not reusable; create a new instance if you want
|
11
|
+
# to build another command.
|
12
|
+
#
|
9
13
|
# @param [Cri::Command, nil] command The command to modify, or nil if a
|
10
14
|
# new command should be created
|
11
15
|
def initialize(command=nil)
|
@@ -101,10 +105,26 @@ module Cri
|
|
101
105
|
# @option params [:forbidden, :required, :optional] :argument Whether the
|
102
106
|
# argument is forbidden, required or optional
|
103
107
|
#
|
108
|
+
# @option params [Boolean] :multiple Whether or not the option should
|
109
|
+
# be multi-valued
|
110
|
+
#
|
104
111
|
# @return [void]
|
105
112
|
def option(short, long, desc, params={}, &block)
|
106
|
-
requiredness = params
|
107
|
-
|
113
|
+
requiredness = params.fetch(:argument, :forbidden)
|
114
|
+
multiple = params.fetch(:multiple, false)
|
115
|
+
|
116
|
+
if short.nil? && long.nil?
|
117
|
+
raise ArgumentError, "short and long options cannot both be nil"
|
118
|
+
end
|
119
|
+
|
120
|
+
@command.option_definitions << {
|
121
|
+
:short => short.nil? ? nil : short.to_s,
|
122
|
+
:long => long.nil? ? nil : long.to_s,
|
123
|
+
:desc => desc,
|
124
|
+
:argument => requiredness,
|
125
|
+
:multiple => multiple,
|
126
|
+
:block => block,
|
127
|
+
}
|
108
128
|
end
|
109
129
|
alias_method :opt, :option
|
110
130
|
|
@@ -117,11 +137,15 @@ module Cri
|
|
117
137
|
#
|
118
138
|
# @param [String] desc The option description
|
119
139
|
#
|
140
|
+
# @option params [Boolean] :multiple Whether or not the option should
|
141
|
+
# be multi-valued
|
142
|
+
#
|
120
143
|
# @return [void]
|
121
144
|
#
|
122
145
|
# @see {#option}
|
123
|
-
def required(short, long, desc, &block)
|
124
|
-
|
146
|
+
def required(short, long, desc, params={}, &block)
|
147
|
+
params = params.merge(:argument => :required)
|
148
|
+
self.option(short, long, desc, params, &block)
|
125
149
|
end
|
126
150
|
|
127
151
|
# Adds a new option with a forbidden argument to the command. If a block
|
@@ -133,11 +157,15 @@ module Cri
|
|
133
157
|
#
|
134
158
|
# @param [String] desc The option description
|
135
159
|
#
|
160
|
+
# @option params [Boolean] :multiple Whether or not the option should
|
161
|
+
# be multi-valued
|
162
|
+
#
|
136
163
|
# @return [void]
|
137
164
|
#
|
138
165
|
# @see {#option}
|
139
|
-
def flag(short, long, desc, &block)
|
140
|
-
|
166
|
+
def flag(short, long, desc, params={}, &block)
|
167
|
+
params = params.merge(:argument => :forbidden)
|
168
|
+
self.option(short, long, desc, params, &block)
|
141
169
|
end
|
142
170
|
alias_method :forbidden, :flag
|
143
171
|
|
@@ -150,11 +178,15 @@ module Cri
|
|
150
178
|
#
|
151
179
|
# @param [String] desc The option description
|
152
180
|
#
|
181
|
+
# @option params [Boolean] :multiple Whether or not the option should
|
182
|
+
# be multi-valued
|
183
|
+
#
|
153
184
|
# @return [void]
|
154
185
|
#
|
155
186
|
# @see {#option}
|
156
|
-
def optional(short, long, desc, &block)
|
157
|
-
|
187
|
+
def optional(short, long, desc, params={}, &block)
|
188
|
+
params = params.merge(:argument => :optional)
|
189
|
+
self.option(short, long, desc, params, &block)
|
158
190
|
end
|
159
191
|
|
160
192
|
# Sets the run block to the given block. The given block should have two
|
@@ -162,9 +194,15 @@ module Cri
|
|
162
194
|
# Calling this will override existing run block or runner declarations
|
163
195
|
# (using {#run} and {#runner}, respectively).
|
164
196
|
#
|
197
|
+
# @yieldparam [Hash<Symbol,Object>] opts A map of option names, as defined
|
198
|
+
# in the option definitions, onto strings (when single-valued) or arrays
|
199
|
+
# (when multi-valued)
|
200
|
+
#
|
201
|
+
# @yieldparam [Array<String>] args A list of arguments
|
202
|
+
#
|
165
203
|
# @return [void]
|
166
204
|
def run(&block)
|
167
|
-
unless
|
205
|
+
unless [2, 3].include?(block.arity)
|
168
206
|
raise ArgumentError,
|
169
207
|
"The block given to Cri::Command#run expects two or three args"
|
170
208
|
end
|
@@ -185,22 +223,5 @@ module Cri
|
|
185
223
|
klass.new(opts, args, cmd).call
|
186
224
|
end
|
187
225
|
end
|
188
|
-
|
189
|
-
protected
|
190
|
-
|
191
|
-
def add_option(short, long, desc, argument, block)
|
192
|
-
if short.nil? && long.nil?
|
193
|
-
raise ArgumentError, "short and long options cannot both be nil"
|
194
|
-
end
|
195
|
-
|
196
|
-
@command.option_definitions << {
|
197
|
-
:short => short.nil? ? nil : short.to_s,
|
198
|
-
:long => long.nil? ? nil : long.to_s,
|
199
|
-
:desc => desc,
|
200
|
-
:argument => argument,
|
201
|
-
:block => block }
|
202
|
-
end
|
203
|
-
|
204
226
|
end
|
205
|
-
|
206
227
|
end
|
data/lib/cri/command_runner.rb
CHANGED
@@ -15,6 +15,8 @@ module Cri
|
|
15
15
|
# @return [Command] The command
|
16
16
|
attr_reader :command
|
17
17
|
|
18
|
+
# Creates a command runner from the given options, arguments and command.
|
19
|
+
#
|
18
20
|
# @param [Hash] options A hash contain the options and their values
|
19
21
|
#
|
20
22
|
# @param [Array] arguments The list of arguments
|
data/lib/cri/core_ext/string.rb
CHANGED
data/lib/cri/help_renderer.rb
CHANGED
@@ -2,13 +2,22 @@
|
|
2
2
|
|
3
3
|
module Cri
|
4
4
|
|
5
|
+
# The {HelpRenderer} class is responsible for generating a string containing
|
6
|
+
# the help for a given command, intended to be printed on the command line.
|
5
7
|
class HelpRenderer
|
6
8
|
|
9
|
+
# Creates a new help renderer for the given command.
|
10
|
+
#
|
11
|
+
# @param [Cri::Command] cmd The command to generate the help for
|
12
|
+
#
|
13
|
+
# @option params [Boolean] :verbose true if the help output should be
|
14
|
+
# verbose, false otherwise.
|
7
15
|
def initialize(cmd, params={})
|
8
16
|
@cmd = cmd
|
9
17
|
@is_verbose = params.fetch(:verbose, false)
|
10
18
|
end
|
11
19
|
|
20
|
+
# @return [String] The help text for this command
|
12
21
|
def render
|
13
22
|
text = ''
|
14
23
|
|
data/lib/cri/option_parser.rb
CHANGED
@@ -16,8 +16,8 @@ module Cri
|
|
16
16
|
# A sample array of definition hashes could look like this:
|
17
17
|
#
|
18
18
|
# [
|
19
|
-
# { :short => 'a', :long => 'all', :argument => :forbidden },
|
20
|
-
# { :short => 'p', :long => 'port', :argument => :required
|
19
|
+
# { :short => 'a', :long => 'all', :argument => :forbidden, :multiple => true },
|
20
|
+
# { :short => 'p', :long => 'port', :argument => :required, :multiple => false },
|
21
21
|
# ]
|
22
22
|
#
|
23
23
|
# For example, the following commandline options (which should not be
|
@@ -258,7 +258,13 @@ module Cri
|
|
258
258
|
|
259
259
|
def add_option(definition, value)
|
260
260
|
key = (definition[:long] || definition[:short]).to_sym
|
261
|
-
|
261
|
+
if definition[:multiple]
|
262
|
+
options[key] ||= []
|
263
|
+
options[key] << value
|
264
|
+
else
|
265
|
+
options[key] = value
|
266
|
+
end
|
267
|
+
|
262
268
|
delegate.option_added(key, value, self) unless delegate.nil?
|
263
269
|
end
|
264
270
|
|
data/lib/cri/version.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/test_command.rb
CHANGED
@@ -85,7 +85,6 @@ class Cri::CommandTestCase < Cri::TestCase
|
|
85
85
|
description 'Sinks stuff (like ships and the like).'
|
86
86
|
|
87
87
|
run do |opts, args|
|
88
|
-
$stdout.puts "Sinking!"
|
89
88
|
end
|
90
89
|
end
|
91
90
|
|
@@ -438,6 +437,16 @@ class Cri::CommandTestCase < Cri::TestCase
|
|
438
437
|
assert_equal "args=foo,bar args.raw=foo,--,bar\n", out
|
439
438
|
end
|
440
439
|
|
440
|
+
def test_run_without_block
|
441
|
+
cmd = Cri::Command.define do
|
442
|
+
name 'moo'
|
443
|
+
end
|
444
|
+
|
445
|
+
assert_raises(Cri::NotImplementedError) do
|
446
|
+
cmd.run([])
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
441
450
|
def test_runner_with_raw_args
|
442
451
|
cmd = Cri::Command.define do
|
443
452
|
name 'moo'
|
@@ -454,4 +463,12 @@ class Cri::CommandTestCase < Cri::TestCase
|
|
454
463
|
assert_equal "args=foo,bar args.raw=foo,--,bar\n", out
|
455
464
|
end
|
456
465
|
|
466
|
+
def test_compare
|
467
|
+
foo = Cri::Command.define { name 'foo' }
|
468
|
+
bar = Cri::Command.define { name 'bar' }
|
469
|
+
qux = Cri::Command.define { name 'qux' }
|
470
|
+
|
471
|
+
assert_equal [ bar, foo, qux ], [ foo, bar, qux ].sort
|
472
|
+
end
|
473
|
+
|
457
474
|
end
|
data/test/test_command_dsl.rb
CHANGED
@@ -5,13 +5,13 @@ class Cri::CommandDSLTestCase < Cri::TestCase
|
|
5
5
|
def test_create_command
|
6
6
|
# Define
|
7
7
|
dsl = Cri::CommandDSL.new
|
8
|
-
dsl.instance_eval do
|
8
|
+
dsl.instance_eval do
|
9
9
|
name 'moo'
|
10
10
|
usage 'dunno whatever'
|
11
11
|
summary 'does stuff'
|
12
12
|
description 'This command does a lot of stuff.'
|
13
13
|
|
14
|
-
option :a, :aaa, 'opt a', :argument => :optional
|
14
|
+
option :a, :aaa, 'opt a', :argument => :optional, :multiple => true
|
15
15
|
required :b, :bbb, 'opt b'
|
16
16
|
optional :c, :ccc, 'opt c'
|
17
17
|
flag :d, :ddd, 'opt d'
|
@@ -36,11 +36,11 @@ class Cri::CommandDSLTestCase < Cri::TestCase
|
|
36
36
|
|
37
37
|
# Check options
|
38
38
|
expected_option_definitions = Set.new([
|
39
|
-
{ :short => 'a', :long => 'aaa', :desc => 'opt a', :argument => :optional,
|
40
|
-
{ :short => 'b', :long => 'bbb', :desc => 'opt b', :argument => :required, :block => nil },
|
41
|
-
{ :short => 'c', :long => 'ccc', :desc => 'opt c', :argument => :optional, :block => nil },
|
42
|
-
{ :short => 'd', :long => 'ddd', :desc => 'opt d', :argument => :forbidden, :block => nil },
|
43
|
-
{ :short => 'e', :long => 'eee', :desc => 'opt e', :argument => :forbidden, :block => nil }
|
39
|
+
{ :short => 'a', :long => 'aaa', :desc => 'opt a', :argument => :optional, :multiple => true, :block => nil },
|
40
|
+
{ :short => 'b', :long => 'bbb', :desc => 'opt b', :argument => :required, :multiple => false, :block => nil },
|
41
|
+
{ :short => 'c', :long => 'ccc', :desc => 'opt c', :argument => :optional, :multiple => false, :block => nil },
|
42
|
+
{ :short => 'd', :long => 'ddd', :desc => 'opt d', :argument => :forbidden, :multiple => false, :block => nil },
|
43
|
+
{ :short => 'e', :long => 'eee', :desc => 'opt e', :argument => :forbidden, :multiple => false, :block => nil }
|
44
44
|
])
|
45
45
|
actual_option_definitions = Set.new(command.option_definitions)
|
46
46
|
assert_equal expected_option_definitions, actual_option_definitions
|
@@ -71,21 +71,58 @@ class Cri::CommandDSLTestCase < Cri::TestCase
|
|
71
71
|
|
72
72
|
# Check options
|
73
73
|
expected_option_definitions = Set.new([
|
74
|
-
{ :short => 's', :long => nil, :desc => 'short', :argument => :forbidden, :block => nil },
|
75
|
-
{ :short => nil, :long => 'long', :desc => 'long', :argument => :forbidden, :block => nil }
|
76
|
-
|
74
|
+
{ :short => 's', :long => nil, :desc => 'short', :argument => :forbidden, :multiple => false, :block => nil },
|
75
|
+
{ :short => nil, :long => 'long', :desc => 'long', :argument => :forbidden, :multiple => false, :block => nil }
|
76
|
+
])
|
77
77
|
actual_option_definitions = Set.new(command.option_definitions)
|
78
78
|
assert_equal expected_option_definitions, actual_option_definitions
|
79
79
|
end
|
80
80
|
|
81
|
-
def
|
81
|
+
def test_multiple
|
82
|
+
# Define
|
83
|
+
dsl = Cri::CommandDSL.new
|
84
|
+
dsl.instance_eval do
|
85
|
+
flag :f, :flag, 'sample flag option', :multiple => true
|
86
|
+
required :r, :required, 'sample required option', :multiple => true
|
87
|
+
optional :o, :optional, 'sample optional option', :multiple => true
|
88
|
+
|
89
|
+
run { |opts, args| }
|
90
|
+
end
|
91
|
+
command = dsl.command
|
92
|
+
|
93
|
+
# Check options
|
94
|
+
expected_option_definitions = Set.new([
|
95
|
+
{ :short => 'f', :long => 'flag', :desc => 'sample flag option', :argument => :forbidden, :multiple => true, :block => nil },
|
96
|
+
{ :short => 'r', :long => 'required', :desc => 'sample required option', :argument => :required, :multiple => true, :block => nil },
|
97
|
+
{ :short => 'o', :long => 'optional', :desc => 'sample optional option', :argument => :optional, :multiple => true, :block => nil },
|
98
|
+
])
|
99
|
+
actual_option_definitions = Set.new(command.option_definitions)
|
100
|
+
assert_equal expected_option_definitions, actual_option_definitions
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_required_short_and_long
|
82
104
|
# Define
|
83
105
|
dsl = Cri::CommandDSL.new
|
106
|
+
assert_raises ArgumentError do
|
107
|
+
dsl.instance_eval do
|
108
|
+
option nil, nil, 'meh'
|
109
|
+
end
|
110
|
+
end
|
84
111
|
assert_raises ArgumentError do
|
85
112
|
dsl.instance_eval do
|
86
113
|
flag nil, nil, 'meh'
|
87
114
|
end
|
88
115
|
end
|
116
|
+
assert_raises ArgumentError do
|
117
|
+
dsl.instance_eval do
|
118
|
+
required nil, nil, 'meh'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
assert_raises ArgumentError do
|
122
|
+
dsl.instance_eval do
|
123
|
+
optional nil, nil, 'meh'
|
124
|
+
end
|
125
|
+
end
|
89
126
|
end
|
90
127
|
|
91
128
|
def test_subcommand
|
@@ -117,6 +154,16 @@ class Cri::CommandDSLTestCase < Cri::TestCase
|
|
117
154
|
assert_equal %w( aah moo ), command.aliases.sort
|
118
155
|
end
|
119
156
|
|
157
|
+
def test_run_arity
|
158
|
+
dsl = Cri::CommandDSL.new
|
159
|
+
assert_raises ArgumentError do
|
160
|
+
dsl.instance_eval do
|
161
|
+
run do |a, b, c, d, e|
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
120
167
|
def test_runner
|
121
168
|
# Define
|
122
169
|
dsl = Cri::CommandDSL.new
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class Cri::CommandRunnerTestCase < Cri::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
|
8
|
+
@options = { :vehicle => 'pig' }
|
9
|
+
@arguments = %w( baby_monkey )
|
10
|
+
@command = Cri::Command.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_initialize
|
14
|
+
|
15
|
+
runner = Cri::CommandRunner.new(@options, @arguments, @command)
|
16
|
+
|
17
|
+
assert_equal @options, runner.options
|
18
|
+
assert_equal @arguments, runner.arguments
|
19
|
+
assert_equal @command, runner.command
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_call_run
|
23
|
+
assert_raises(Cri::NotImplementedError) do
|
24
|
+
Cri::CommandRunner.new(@options, @arguments, @command).call
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_raises(Cri::NotImplementedError) do
|
28
|
+
Cri::CommandRunner.new(@options, @arguments, @command).run
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/test/test_option_parser.rb
CHANGED
@@ -23,7 +23,7 @@ class Cri::OptionParserTestCase < Cri::TestCase
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
26
|
+
def test_parse_with_unused_options
|
27
27
|
input = %w( foo )
|
28
28
|
definitions = [
|
29
29
|
{ :long => 'aaa', :short => 'a', :argument => :forbidden }
|
@@ -279,4 +279,16 @@ class Cri::OptionParserTestCase < Cri::TestCase
|
|
279
279
|
end
|
280
280
|
end
|
281
281
|
|
282
|
+
def test_parse_with_multiple_options
|
283
|
+
input = %w( foo -o test -o test2 -v -v -v)
|
284
|
+
definitions = [
|
285
|
+
{ :long => 'long', :short => 'o', :argument => :required, :multiple => true },
|
286
|
+
{ :long => 'verbose', :short => 'v', :multiple => true }
|
287
|
+
]
|
288
|
+
parser = Cri::OptionParser.parse(input, definitions)
|
289
|
+
|
290
|
+
assert_equal(['test', 'test2'], parser.options[:long])
|
291
|
+
assert_equal(3, parser.options[:verbose].size)
|
292
|
+
end
|
293
|
+
|
282
294
|
end
|
metadata
CHANGED
@@ -1,71 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Defreyne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colored
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.6'
|
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: '
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ~>
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '5.3'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ~>
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '5.3'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: yard
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0.8'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ~>
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0.8'
|
40
|
+
version: '1.6'
|
69
41
|
description: Cri allows building easy-to-use commandline interfaces with support for
|
70
42
|
subcommands.
|
71
43
|
email: denis.defreyne@stoneship.org
|
@@ -102,6 +74,7 @@ files:
|
|
102
74
|
- test/test_basic_root.rb
|
103
75
|
- test/test_command.rb
|
104
76
|
- test/test_command_dsl.rb
|
77
|
+
- test/test_command_runner.rb
|
105
78
|
- test/test_core_ext.rb
|
106
79
|
- test/test_option_parser.rb
|
107
80
|
homepage: http://stoneship.org/software/cri/
|
@@ -110,23 +83,23 @@ licenses:
|
|
110
83
|
metadata: {}
|
111
84
|
post_install_message:
|
112
85
|
rdoc_options:
|
113
|
-
- --main
|
86
|
+
- "--main"
|
114
87
|
- README.adoc
|
115
88
|
require_paths:
|
116
89
|
- lib
|
117
90
|
required_ruby_version: !ruby/object:Gem::Requirement
|
118
91
|
requirements:
|
119
|
-
- -
|
92
|
+
- - ">="
|
120
93
|
- !ruby/object:Gem::Version
|
121
94
|
version: '0'
|
122
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
96
|
requirements:
|
124
|
-
- -
|
97
|
+
- - ">="
|
125
98
|
- !ruby/object:Gem::Version
|
126
99
|
version: '0'
|
127
100
|
requirements: []
|
128
101
|
rubyforge_project:
|
129
|
-
rubygems_version: 2.2.
|
102
|
+
rubygems_version: 2.2.0
|
130
103
|
signing_key:
|
131
104
|
specification_version: 4
|
132
105
|
summary: a library for building easy-to-use commandline tools
|