cri 2.10.1 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem](http://img.shields.io/gem/v/cri.svg)](http://rubygems.org/gems/cri)
|
4
|
+
[![Travis](http://img.shields.io/travis/ddfreyne/cri.svg)](https://travis-ci.org/ddfreyne/cri)
|
5
|
+
[![Coveralls](http://img.shields.io/coveralls/ddfreyne/cri.svg)](https://coveralls.io/r/ddfreyne/cri)
|
6
|
+
[![Codeclimate](http://img.shields.io/codeclimate/github/ddfreyne/cri.svg)](https://codeclimate.com/github/ddfreyne/cri)
|
7
|
+
[![Inch](http://inch-ci.org/github/ddfreyne/cri.svg)](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
|