cri 2.10.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +2 -0
- data/Gemfile.lock +24 -23
- data/NEWS.md +6 -0
- data/{README.adoc → README.md} +105 -64
- data/Rakefile +2 -0
- data/cri.gemspec +6 -5
- data/lib/cri.rb +11 -11
- data/lib/cri/command.rb +7 -2
- data/lib/cri/command_dsl.rb +8 -0
- data/lib/cri/command_runner.rb +2 -0
- data/lib/cri/commands/basic_help.rb +8 -6
- data/lib/cri/commands/basic_root.rb +2 -0
- data/lib/cri/help_renderer.rb +9 -7
- data/lib/cri/option_parser.rb +45 -15
- data/lib/cri/platform.rb +6 -0
- data/lib/cri/string_formatter.rb +18 -14
- data/lib/cri/version.rb +3 -1
- data/test/helper.rb +2 -0
- data/test/test_base.rb +2 -0
- data/test/test_basic_help.rb +2 -0
- data/test/test_basic_root.rb +2 -0
- data/test/test_command.rb +30 -6
- data/test/test_command_dsl.rb +18 -16
- data/test/test_command_runner.rb +2 -0
- data/test/test_help_renderer.rb +18 -16
- data/test/test_option_parser.rb +76 -2
- data/test/test_string_formatter.rb +2 -0
- metadata +7 -11
- data/lib/cri/argument_array.rb +0 -21
- data/lib/cri/core_ext.rb +0 -10
- data/lib/cri/core_ext/string.rb +0 -33
- data/test/test_argument_array.rb +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: cc4daab3e3ba10d21d0545fab6a7ab99dc8ad125b3ca3acd3691326b164ba4ca
|
4
|
+
data.tar.gz: 686ac2c2324893fbaabc650fe42858355f643eea90af8b6acff986207fb183ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cc8b4aadbde4cae477feb33d2578287d23dc77aea4700dae5115ee06d19e1234ba5625db2f3cd053bfa941e425cc50d0ac0c6836ffcb1b807b92f3aa3055470
|
7
|
+
data.tar.gz: 55c6c0dd76ab840f11f73568de6fa5105dfd934b4602d1fb55bc9f506d4bd001b9bb890110fee0b68bc23ca6824547f33b757855fda126bca27dd72f656d6164
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,50 +1,51 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cri (2.
|
4
|
+
cri (2.11.0)
|
5
5
|
colored (~> 1.2)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
asciidoctor (1.5.
|
11
|
-
ast (2.
|
10
|
+
asciidoctor (1.5.7.1)
|
11
|
+
ast (2.4.0)
|
12
12
|
colored (1.2)
|
13
|
-
coveralls (0.8.
|
13
|
+
coveralls (0.8.22)
|
14
14
|
json (>= 1.8, < 3)
|
15
|
-
simplecov (~> 0.
|
15
|
+
simplecov (~> 0.16.1)
|
16
16
|
term-ansicolor (~> 1.3)
|
17
17
|
thor (~> 0.19.4)
|
18
18
|
tins (~> 1.6)
|
19
|
-
docile (1.1
|
19
|
+
docile (1.3.1)
|
20
|
+
jaro_winkler (1.5.1)
|
20
21
|
json (2.1.0)
|
21
|
-
minitest (5.
|
22
|
-
parallel (1.12.
|
23
|
-
parser (2.
|
24
|
-
ast (~> 2.
|
25
|
-
powerpack (0.1.
|
26
|
-
rainbow (
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
minitest (5.11.3)
|
23
|
+
parallel (1.12.1)
|
24
|
+
parser (2.5.1.2)
|
25
|
+
ast (~> 2.4.0)
|
26
|
+
powerpack (0.1.2)
|
27
|
+
rainbow (3.0.0)
|
28
|
+
rake (12.3.1)
|
29
|
+
rubocop (0.58.2)
|
30
|
+
jaro_winkler (~> 1.5.1)
|
30
31
|
parallel (~> 1.10)
|
31
|
-
parser (>= 2.
|
32
|
+
parser (>= 2.5, != 2.5.1.1)
|
32
33
|
powerpack (~> 0.1)
|
33
|
-
rainbow (>= 2.2.2, <
|
34
|
+
rainbow (>= 2.2.2, < 4.0)
|
34
35
|
ruby-progressbar (~> 1.7)
|
35
36
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
36
37
|
ruby-progressbar (1.9.0)
|
37
|
-
simplecov (0.
|
38
|
-
docile (~> 1.1
|
38
|
+
simplecov (0.16.1)
|
39
|
+
docile (~> 1.1)
|
39
40
|
json (>= 1.8, < 3)
|
40
41
|
simplecov-html (~> 0.10.0)
|
41
42
|
simplecov-html (0.10.2)
|
42
43
|
term-ansicolor (1.6.0)
|
43
44
|
tins (~> 1.0)
|
44
45
|
thor (0.19.4)
|
45
|
-
tins (1.
|
46
|
-
unicode-display_width (1.
|
47
|
-
yard (0.9.
|
46
|
+
tins (1.16.3)
|
47
|
+
unicode-display_width (1.4.0)
|
48
|
+
yard (0.9.15)
|
48
49
|
|
49
50
|
PLATFORMS
|
50
51
|
ruby
|
@@ -60,4 +61,4 @@ DEPENDENCIES
|
|
60
61
|
yard
|
61
62
|
|
62
63
|
BUNDLED WITH
|
63
|
-
1.
|
64
|
+
1.16.3
|
data/NEWS.md
CHANGED
data/{README.adoc → README.md}
RENAMED
@@ -1,19 +1,19 @@
|
|
1
|
-
|
1
|
+
# Cri
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
[](http://rubygems.org/gems/cri)
|
4
|
+
[](https://travis-ci.org/ddfreyne/cri)
|
5
|
+
[](https://coveralls.io/r/ddfreyne/cri)
|
6
|
+
[](https://codeclimate.com/github/ddfreyne/cri)
|
7
|
+
[](http://inch-ci.org/github/ddfreyne/cri/)
|
8
8
|
|
9
9
|
Cri is a library for building easy-to-use command-line tools with support for
|
10
10
|
nested commands.
|
11
11
|
|
12
|
-
|
12
|
+
## Requirements
|
13
13
|
|
14
|
-
Cri requires Ruby 2.
|
14
|
+
Cri requires Ruby 2.3 or newer.
|
15
15
|
|
16
|
-
|
16
|
+
## Usage
|
17
17
|
|
18
18
|
The central concept in Cri is the _command_, which has option definitions as
|
19
19
|
well as code for actually executing itself. In Cri, the command-line tool
|
@@ -21,8 +21,7 @@ itself is a command as well.
|
|
21
21
|
|
22
22
|
Here’s a sample command definition:
|
23
23
|
|
24
|
-
|
25
|
-
--------------------------------------------------------------------------------
|
24
|
+
```ruby
|
26
25
|
command = Cri::Command.define do
|
27
26
|
name 'dostuff'
|
28
27
|
usage 'dostuff [options]'
|
@@ -46,21 +45,20 @@ command = Cri::Command.define do
|
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
49
|
-
|
48
|
+
```
|
50
49
|
|
51
50
|
To run this command, invoke the `#run` method with the raw arguments. For
|
52
51
|
example, for a root command (the command-line tool itself), the command could
|
53
52
|
be called like this:
|
54
53
|
|
55
|
-
|
56
|
-
--------------------------------------------------------------------------------
|
54
|
+
```ruby
|
57
55
|
command.run(ARGV)
|
58
|
-
|
56
|
+
```
|
59
57
|
|
60
58
|
Each command has automatically generated help. This help can be printed using
|
61
59
|
`Cri::Command#help`; something like this will be shown:
|
62
60
|
|
63
|
-
|
61
|
+
```
|
64
62
|
usage: dostuff [options]
|
65
63
|
|
66
64
|
does stuff
|
@@ -72,20 +70,19 @@ options:
|
|
72
70
|
-h --help show help for this command
|
73
71
|
--more do even more stuff
|
74
72
|
-s --stuff specify stuff to do
|
75
|
-
|
73
|
+
```
|
76
74
|
|
77
|
-
|
75
|
+
### General command metadata
|
78
76
|
|
79
77
|
Let’s disect the command definition and start with the first five lines:
|
80
78
|
|
81
|
-
|
82
|
-
--------------------------------------------------------------------------------
|
79
|
+
```ruby
|
83
80
|
name 'dostuff'
|
84
81
|
usage 'dostuff [options]'
|
85
82
|
aliases :ds, :stuff
|
86
83
|
summary 'does stuff'
|
87
84
|
description 'This command does a lot of stuff. I really mean a lot.'
|
88
|
-
|
85
|
+
```
|
89
86
|
|
90
87
|
These lines of the command definition specify the name of the command (or the
|
91
88
|
command-line tool, if the command is the root command), the usage, a list of
|
@@ -95,31 +92,33 @@ the supercommand, because the latter will be automatically prepended.
|
|
95
92
|
|
96
93
|
Aliases don’t make sense for root commands, but for subcommands they do.
|
97
94
|
|
98
|
-
|
95
|
+
### Command-line options
|
99
96
|
|
100
97
|
The next few lines contain the command’s option definitions:
|
101
98
|
|
102
|
-
|
103
|
-
--------------------------------------------------------------------------------
|
99
|
+
```ruby
|
104
100
|
flag :h, :help, 'show help for this command' do |value, cmd|
|
105
101
|
puts cmd.help
|
106
102
|
exit 0
|
107
103
|
end
|
108
104
|
flag nil, :more, 'do even more stuff'
|
109
105
|
option :s, :stuff, 'specify stuff to do', argument: :required
|
110
|
-
|
106
|
+
```
|
111
107
|
|
112
108
|
Options can be defined using the following methods:
|
113
109
|
|
114
|
-
* `Cri::CommandDSL#option` or `Cri::CommandDSL#opt`
|
110
|
+
* `Cri::CommandDSL#option` or `Cri::CommandDSL#opt` (include an `argument` parameter: `:required` or `:optional` that specifies if the option requires or allows an argument)
|
115
111
|
* `Cri::CommandDSL#flag` (implies no arguments passed to option)
|
116
|
-
|
117
|
-
|
112
|
+
|
113
|
+
The following _deprecated_ methods can also be used to define options:
|
114
|
+
|
115
|
+
* `Cri::CommandDSL#required` (implies an option that requires an argument -- deprecated because `#required` suggests that the option is required, wich is incorrect; the _argument_ is required.)
|
116
|
+
* `Cri::CommandDSL#optional` (implies an option that can optionally include an argument -- deprecated because `#optional` looks too similar to `#option`.)
|
118
117
|
|
119
118
|
All these methods take these arguments:
|
120
119
|
|
121
|
-
1. a short option
|
122
|
-
2. a long option
|
120
|
+
1. a short option name
|
121
|
+
2. a long option name
|
123
122
|
3. a description
|
124
123
|
4. optional extra parameters
|
125
124
|
|
@@ -128,27 +127,62 @@ would not make any sense). In the example above, the `--more` option has no
|
|
128
127
|
short form.
|
129
128
|
|
130
129
|
Each of the above methods also take a block, which will be executed when the
|
131
|
-
option is found. The
|
130
|
+
option is found. The arguments to the block are the option value (`true` in
|
132
131
|
case the option does not have an argument) and the command.
|
133
132
|
|
134
|
-
|
133
|
+
#### Transforming options
|
134
|
+
|
135
|
+
The `:transform` parameter specifies how the value should be transformed. It takes any object that responds to `#call`:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
option :p, :port, 'set port', argument: :required,
|
139
|
+
transform: -> (x) { Integer(x) }
|
140
|
+
```
|
141
|
+
|
142
|
+
The following example uses `#Integer` to transform a string into an integer:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
option :p, :port, 'set port', argument: :required, transform: method(:Integer)
|
146
|
+
```
|
147
|
+
|
148
|
+
The following example uses a custom object to perform transformation, as well as validation:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
class PortTransformer
|
152
|
+
def call(str)
|
153
|
+
raise ArgumentError unless str.is_a?(String)
|
154
|
+
Integer(str).tap do |int|
|
155
|
+
raise unless (0x0001..0xffff).include?(int)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
option :p, :port, 'set port', argument: :required, transform: PortTransformer.new
|
161
|
+
```
|
162
|
+
|
163
|
+
Default values are not transformed:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
option :p, :port, 'set port', argument: :required, default: 8080, transform: PortTransformer.new
|
167
|
+
```
|
168
|
+
|
169
|
+
#### Options with default values
|
135
170
|
|
136
|
-
The `:default` parameter sets the option value that will be used if
|
171
|
+
The `:default` parameter sets the option value that will be used if the option is passed without an argument or isn't passed at all:
|
137
172
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
--------------------------------------------------------------------------------
|
173
|
+
```ruby
|
174
|
+
option :a, :animal, 'add animal', default: 'giraffe', argument: :optional
|
175
|
+
```
|
142
176
|
|
143
177
|
In the example above, the value for the `--animal` option will be the string
|
144
178
|
`"giraffe"`, unless otherwise specified:
|
145
179
|
|
146
|
-
|
180
|
+
```
|
147
181
|
OPTIONS
|
148
182
|
-a --animal[=<value>] add animal (default: giraffe)
|
149
|
-
|
183
|
+
```
|
150
184
|
|
151
|
-
|
185
|
+
#### Multivalued options
|
152
186
|
|
153
187
|
Each of these four methods take a `:multiple` parameter. When set to true, multiple
|
154
188
|
option valus are accepted, and the option values will be stored in an array.
|
@@ -157,10 +191,9 @@ For example, to parse the command line options string `-o foo.txt -o bar.txt`
|
|
157
191
|
into an array, so that `options[:output]` contains `[ 'foo.txt', 'bar.txt' ]`,
|
158
192
|
you can use an option definition like this:
|
159
193
|
|
160
|
-
|
161
|
-
--------------------------------------------------------------------------------
|
194
|
+
```ruby
|
162
195
|
option :o, :output, 'specify output paths', argument: :required, multiple: true
|
163
|
-
|
196
|
+
```
|
164
197
|
|
165
198
|
This can also be used for flags (options without arguments). In this case, the
|
166
199
|
length of the options array is relevant.
|
@@ -169,19 +202,17 @@ For example, you can allow setting the verbosity level using `-v -v -v`. The
|
|
169
202
|
value of `options[:verbose].size` would then be the verbosity level (three in
|
170
203
|
this example). The option definition would then look like this:
|
171
204
|
|
172
|
-
|
173
|
-
--------------------------------------------------------------------------------
|
205
|
+
```ruby
|
174
206
|
flag :v, :verbose, 'be verbose (use up to three times)', multiple: true
|
175
|
-
|
207
|
+
```
|
176
208
|
|
177
|
-
|
209
|
+
#### Skipping option parsing
|
178
210
|
|
179
211
|
If you want to skip option parsing for your command or subcommand, you can add
|
180
212
|
the `skip_option_parsing` method to your command definition and everything on your
|
181
213
|
command line after the command name will be passed to your command as arguments.
|
182
214
|
|
183
|
-
|
184
|
-
-------------------------------------------------------------------------------
|
215
|
+
```ruby
|
185
216
|
command = Cri::Command.define do
|
186
217
|
name 'dostuff'
|
187
218
|
usage 'dostuff [args]'
|
@@ -195,18 +226,17 @@ command = Cri::Command.define do
|
|
195
226
|
puts args.inspect
|
196
227
|
end
|
197
228
|
end
|
198
|
-
|
229
|
+
```
|
199
230
|
|
200
231
|
When executing this command with `dostuff --some=value -f yes`, the `opts` hash
|
201
232
|
that is passed to your `run` block will be empty and the `args` array will be
|
202
233
|
`["--some=value", "-f", "yes"]`.
|
203
234
|
|
204
|
-
|
235
|
+
### The run block
|
205
236
|
|
206
237
|
The last part of the command defines the execution itself:
|
207
238
|
|
208
|
-
|
209
|
-
--------------------------------------------------------------------------------
|
239
|
+
```ruby
|
210
240
|
run do |opts, args, cmd|
|
211
241
|
stuff = opts.fetch(:stuff, 'generic stuff')
|
212
242
|
puts "Doing #{stuff}!"
|
@@ -215,7 +245,7 @@ run do |opts, args, cmd|
|
|
215
245
|
puts 'Doing it even more!'
|
216
246
|
end
|
217
247
|
end
|
218
|
-
|
248
|
+
```
|
219
249
|
|
220
250
|
The +Cri::CommandDSL#run+ method takes a block with the actual code to
|
221
251
|
execute. This block takes three arguments: the options, any arguments passed
|
@@ -226,7 +256,7 @@ _command runner_ class (`Cri::CommandRunner`) that will perform the actual
|
|
226
256
|
execution of the command. This makes it easier to break up large run blocks
|
227
257
|
into manageable pieces.
|
228
258
|
|
229
|
-
|
259
|
+
### Subcommands
|
230
260
|
|
231
261
|
Commands can have subcommands. For example, the `git` command-line tool would be
|
232
262
|
represented by a command that has subcommands named `commit`, `add`, and so on.
|
@@ -236,27 +266,38 @@ dispatched to a subcommand (or none, if no subcommand is found).
|
|
236
266
|
To add a command as a subcommand to another command, use the
|
237
267
|
`Cri::Command#add_command` method, like this:
|
238
268
|
|
239
|
-
|
240
|
-
--------------------------------------------------------------------------------
|
269
|
+
```ruby
|
241
270
|
root_cmd.add_command(cmd_add)
|
242
271
|
root_cmd.add_command(cmd_commit)
|
243
|
-
|
244
|
-
|
272
|
+
root_cmd.add_command(cmd_init)
|
273
|
+
```
|
274
|
+
|
275
|
+
You can also define a subcommand on the fly without creating a class first
|
276
|
+
using `Cri::Command#define_command` (name can be skipped if you set it inside
|
277
|
+
the block instead):
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
root_cmd.define_command('add') do
|
281
|
+
# option ...
|
282
|
+
run do |opts, args, cmd|
|
283
|
+
# ...
|
284
|
+
end
|
285
|
+
end
|
286
|
+
```
|
245
287
|
|
246
288
|
You can specify a default subcommand. This subcommand will be executed when the
|
247
289
|
command has subcommands, and no subcommands are otherwise explicitly specified:
|
248
290
|
|
249
|
-
|
250
|
-
--------------------------------------------------------------------------------
|
291
|
+
```ruby
|
251
292
|
default_subcommand 'compile'
|
252
|
-
|
293
|
+
```
|
253
294
|
|
254
|
-
|
295
|
+
## Contributors
|
255
296
|
|
256
297
|
* Bart Mesuere
|
257
298
|
* Ken Coar
|
258
299
|
* Tim Sharpe
|
259
300
|
* Toon Willems
|
260
301
|
|
261
|
-
Thanks for Lee “injekt” Jarvis for
|
302
|
+
Thanks for Lee “injekt” Jarvis for [Slop](https://github.com/injekt/slop),
|
262
303
|
which has inspired the design of Cri 2.0.
|
data/Rakefile
CHANGED
data/cri.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/cri/version'
|
3
4
|
|
4
5
|
Gem::Specification.new do |s|
|
5
6
|
s.name = 'cri'
|
@@ -15,12 +16,12 @@ Gem::Specification.new do |s|
|
|
15
16
|
s.files = Dir['[A-Z]*'] + Dir['{lib,test}/**/*'] + ['cri.gemspec']
|
16
17
|
s.require_paths = ['lib']
|
17
18
|
|
18
|
-
s.required_ruby_version = '~> 2.
|
19
|
+
s.required_ruby_version = '~> 2.3'
|
19
20
|
|
20
21
|
s.add_dependency('colored', '~> 1.2')
|
21
22
|
|
22
23
|
s.add_development_dependency('bundler', '~> 1.6')
|
23
24
|
|
24
|
-
s.rdoc_options = ['--main', 'README.
|
25
|
-
s.extra_rdoc_files = ['LICENSE', 'README.
|
25
|
+
s.rdoc_options = ['--main', 'README.md']
|
26
|
+
s.extra_rdoc_files = ['LICENSE', 'README.md', 'NEWS.md']
|
26
27
|
end
|