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 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