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