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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YTY4ZDU4NjdmNGI4NDNhM2UxMTA1YTA1MDBjZmEzYWZiNDgwOTY0ZA==
5
- data.tar.gz: !binary |-
6
- MjkxMmY1ZDA1M2ExNDUxYmUxOTYyNjVjZTE3OWExM2Y1NmVhODg2Mg==
2
+ SHA1:
3
+ metadata.gz: 0b5c4be8a90bd61c37d60ee1a789c51147f3d096
4
+ data.tar.gz: 19f03a77cb1414c4c5ae591d47a93027642160db
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MTNjMmU4ZTViYjg2YzFiYjI5MjZiZTcyNzViNGYyYTEzZjdiMzY5MTc4Mzlk
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
@@ -1,2 +1,9 @@
1
1
  source 'https://rubygems.org'
2
+
2
3
  gemspec
4
+
5
+ gem 'coveralls'
6
+ gem 'rake'
7
+ gem 'minitest'
8
+ gem 'yard'
9
+ gem 'asciidoctor'
@@ -1,21 +1,45 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cri (2.5.0)
5
- colored (>= 1.2)
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
- minitest (5.3.0)
12
- rake (10.1.1)
13
- yard (0.8.7.3)
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
@@ -1,6 +1,11 @@
1
1
  Cri News
2
2
  ========
3
3
 
4
+ 2.6.0
5
+ -----
6
+
7
+ * Added support for multi-valued options [Toon Willems]
8
+
4
9
  2.5.0
5
10
  -----
6
11
 
@@ -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', :argument => :required
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', :argument => :required
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
- ##### Requirements
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.md',
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
- ENV['QUIET'] ||= 'true'
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
- test_files = Dir['test/test_*.rb']
41
- test_files.each { |f| require f }
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
@@ -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('rake', '~> 10.1')
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
@@ -1,6 +1,9 @@
1
1
  # encoding: utf-8
2
+
2
3
  require 'cri/version'
3
4
 
5
+ # The namespace for Cri, a library for building easy-to-use commandline tools
6
+ # with support for nested commands.
4
7
  module Cri
5
8
 
6
9
  # A generic error class for all Cri-specific errors.
@@ -251,7 +251,7 @@ module Cri
251
251
  run_this(opts_and_args, parent_opts)
252
252
  else
253
253
  # Handle options
254
- self.handle_options(opts_before_subcmd)
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
- self.handle_parser_errors_while { parser.run }
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
- self.handle_options(local_opts)
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
- protected
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
- self.handle_parser_errors_while { parser.run }
335
+ handle_parser_errors_while { parser.run }
327
336
  parser
328
337
 
329
338
  # Extract
@@ -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[:argument] || :forbidden
107
- self.add_option(short, long, desc, requiredness, block)
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
- self.add_option(short, long, desc, :required, block)
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
- self.add_option(short, long, desc, :forbidden, block)
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
- self.add_option(short, long, desc, :optional, block)
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 block.arity != 2 || block.arity != 3
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
@@ -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
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  require 'colored'
3
4
 
4
5
  module Cri::CoreExtensions
@@ -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
 
@@ -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
- options[key] = value
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
 
@@ -1,6 +1,8 @@
1
+ # encoding: utf-8
2
+
1
3
  module Cri
2
4
 
3
5
  # The current Cri version.
4
- VERSION = '2.5.0'
6
+ VERSION = '2.6.0'
5
7
 
6
8
  end
@@ -1,5 +1,13 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require 'coveralls'
4
+ Coveralls.wear!
5
+
6
+ require 'minitest'
7
+ require 'minitest/autorun'
8
+
9
+ require 'cri'
10
+
3
11
  require 'stringio'
4
12
 
5
13
  class Cri::TestCase < Minitest::Test
@@ -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
@@ -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, :block => nil },
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 test_optional_options
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
@@ -23,7 +23,7 @@ class Cri::OptionParserTestCase < Cri::TestCase
23
23
  end
24
24
  end
25
25
 
26
- def test_parse_without_options
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.5.0
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-03-01 00:00:00.000000000 Z
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: rake
28
+ name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.1'
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: '10.1'
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.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