dry-cli 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore DELETED
@@ -1,11 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- .byebug_history
11
- .rubocop-*
data/.rspec DELETED
@@ -1,4 +0,0 @@
1
- --color
2
- --require spec_helper
3
- --order random
4
-
@@ -1,95 +0,0 @@
1
- # this file is managed by dry-rb/devtools project
2
-
3
- AllCops:
4
- TargetRubyVersion: 2.4
5
-
6
- Style/EachWithObject:
7
- Enabled: false
8
-
9
- Style/StringLiterals:
10
- Enabled: true
11
- EnforcedStyle: single_quotes
12
-
13
- Style/Alias:
14
- Enabled: false
15
-
16
- Style/LambdaCall:
17
- Enabled: false
18
-
19
- Style/StabbyLambdaParentheses:
20
- Enabled: false
21
-
22
- Style/FormatString:
23
- Enabled: false
24
-
25
- Style/Documentation:
26
- Enabled: false
27
-
28
- Layout/SpaceInLambdaLiteral:
29
- Enabled: false
30
-
31
- Layout/MultilineMethodCallIndentation:
32
- Enabled: true
33
- EnforcedStyle: indented
34
-
35
- Metrics/LineLength:
36
- Max: 100
37
-
38
- Metrics/MethodLength:
39
- Max: 22
40
-
41
- Metrics/ClassLength:
42
- Max: 150
43
-
44
- Metrics/AbcSize:
45
- Max: 20
46
-
47
- Metrics/BlockLength:
48
- Enabled: false
49
-
50
- Metrics/CyclomaticComplexity:
51
- Enabled: true
52
- Max: 10
53
-
54
- Lint/BooleanSymbol:
55
- Enabled: false
56
-
57
- Style/AccessModifierDeclarations:
58
- Enabled: false
59
-
60
- Style/BlockDelimiters:
61
- Enabled: false
62
-
63
- Layout/IndentFirstArrayElement:
64
- EnforcedStyle: consistent
65
-
66
- Style/ClassAndModuleChildren:
67
- Exclude:
68
- - "spec/**/*_spec.rb"
69
-
70
- Lint/HandleExceptions:
71
- Exclude:
72
- - "spec/spec_helper.rb"
73
-
74
- Naming/FileName:
75
- Exclude:
76
- - "lib/dry-*.rb"
77
-
78
- Style/SymbolArray:
79
- Exclude:
80
- - "spec/**/*_spec.rb"
81
-
82
- Style/ConditionalAssignment:
83
- Enabled: false
84
-
85
- Naming/MethodName:
86
- Enabled: false
87
-
88
- Style/AsciiComments:
89
- Enabled: false
90
-
91
- Style/DateTime:
92
- Enabled: false
93
-
94
- Style/IfUnlessModifier:
95
- Enabled: false
@@ -1,13 +0,0 @@
1
- # Contributor Code of Conduct
2
-
3
- As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
-
5
- We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
-
7
- Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
-
9
- Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
-
11
- Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
-
13
- This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.4.0, available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct)
@@ -1,29 +0,0 @@
1
- # Issue Guidelines
2
-
3
- ## Reporting bugs
4
-
5
- If you found a bug, report an issue and describe what's the expected behavior versus what actually happens. If the bug causes a crash, attach a full backtrace. If possible, a reproduction script showing the problem is highly appreciated.
6
-
7
- ## Reporting feature requests
8
-
9
- Report a feature request **only after discussing it first on [discourse.dry-rb.org](https://discourse.dry-rb.org)** where it was accepted. Please provide a concise description of the feature, don't link to a discussion thread, and instead summarize what was discussed.
10
-
11
- ## Reporting questions, support requests, ideas, concerns etc.
12
-
13
- **PLEASE DON'T** - use [discourse.dry-rb.org](http://discourse.dry-rb.org) instead.
14
-
15
- # Pull Request Guidelines
16
-
17
- A Pull Request will only be accepted if it addresses a specific issue that was reported previously, or fixes typos, mistakes in documentation etc.
18
-
19
- Other requirements:
20
-
21
- 1) Do not open a pull request if you can't provide tests along with it. If you have problems writing tests, ask for help in the related issue.
22
- 2) Follow the style conventions of the surrounding code. In most cases, this is standard ruby style.
23
- 3) Add API documentation if it's a new feature
24
- 4) Update API documentation if it changes an existing feature
25
- 5) Bonus points for sending a PR to [github.com/dry-rb/dry-rb.org](github.com/dry-rb/dry-rb.org) which updates user documentation and guides
26
-
27
- # Asking for help
28
-
29
- If these guidelines aren't helpful, and you're stuck, please post a message on [discourse.dry-rb.org](https://discourse.dry-rb.org) or join [our chat](https://dry-rb.zulipchat.com).
data/Gemfile DELETED
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- gemspec
6
-
7
- git_source(:github) do |repo_name| "https://github.com/#{repo_name}" end
8
-
9
- unless ENV['CI']
10
- gem 'byebug', require: false, platforms: :mri
11
- gem 'yard', require: false
12
- end
13
-
14
- gem 'ossy', github: 'solnic/ossy', branch: 'master', platform: :mri
data/Rakefile DELETED
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rake'
4
- require 'bundler/gem_tasks'
5
- require 'rspec/core/rake_task'
6
-
7
- namespace :spec do
8
- RSpec::Core::RakeTask.new(:unit) do |task|
9
- file_list = FileList['spec/**/*_spec.rb']
10
- file_list = file_list.exclude('spec/{integration,isolation}/**/*_spec.rb')
11
-
12
- task.pattern = file_list
13
- end
14
- end
15
-
16
- task default: 'spec:unit'
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'dry/cli'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,588 +0,0 @@
1
- ---
2
- title: Introduction
3
- description: General purpose Command Line Interface (CLI) framework
4
- layout: gem-single
5
- type: gem
6
- name: dry-cli
7
- ---
8
-
9
- ## Table of Contents
10
-
11
- - [Features](#features)
12
- - [Registration](#registration)
13
- - [Commands as objects](#commands-as-objects)
14
- - [Subcommands](#subcommands)
15
- - [Arguments](#arguments)
16
- - [Option](#option)
17
- - [Variadic arguments](#variadic-arguments)
18
- - [Installation](#installation)
19
- - [Usage](#usage)
20
- - [Available commands](#available-commands)
21
- - [Help](#help)
22
- - [Optional arguments](#optional-arguments)
23
- - [Required arguments](#required-arguments)
24
- - [Options](#options)
25
- - [Boolean options](#boolean-options)
26
- - [Array options](#array-options)
27
- - [Subcommands](#subcommands-1)
28
- - [Aliases](#aliases)
29
- - [Subcommand aliases](#subcommand-aliases)
30
- - [Callbacks](#callbacks)
31
- - [File Utils](#file-utils)
32
- - [Development](#development)
33
- - [Contributing](#contributing)
34
- - [Alternatives](#alternatives)
35
- - [Copyright](#copyright)
36
-
37
- <!-- Tocer[finish]: Auto-generated, don't remove. -->
38
-
39
- ## Features
40
-
41
- ### Registration
42
-
43
- For a given _command name_, you can register a corresponding _command object_ (aka command).
44
-
45
- Example: for `foo hi` _command name_ there is the corresponding `Foo::CLI::Hello` _command object_.
46
-
47
- ```ruby
48
- #!/usr/bin/env ruby
49
- require "bundler/setup"
50
- require "dry/cli"
51
-
52
- module Foo
53
- module CLI
54
- module Commands
55
- extend Dry::CLI::Registry
56
-
57
- class Hello < Dry::CLI::Command
58
- def call(*)
59
- end
60
- end
61
- end
62
- end
63
- end
64
-
65
- class Version < Dry::CLI::Command
66
- def call(*)
67
- end
68
- end
69
-
70
- Foo::CLI::Commands.register "hi", Foo::CLI::Commands::Hello
71
- Foo::CLI::Commands.register "v", Version
72
-
73
- Dry::CLI.new(Foo::CLI::Commands).call
74
- ```
75
-
76
- **Please note:** there is NOT a convention between the _command name_ and the _command object_ class.
77
- The manual _registration_ assigns a _command object_ to a _command name_.
78
-
79
- ### Commands as objects
80
-
81
- A command is a subclass of `Dry::CLI::Command` and it MUST respond to `#call(*)`.
82
-
83
- ### Subcommands
84
-
85
- There is nothing special in subcommands: they are just _command objects_ registered under a **nested** _command name_.
86
-
87
- ```ruby
88
- #!/usr/bin/env ruby
89
- require "bundler/setup"
90
- require "dry/cli"
91
-
92
- module Foo
93
- module CLI
94
- module Commands
95
- extend Dry::CLI::Registry
96
-
97
- module Generate
98
- class Configuration < Dry::CLI::Command
99
- def call(*)
100
- end
101
- end
102
- end
103
- end
104
- end
105
- end
106
-
107
- Foo::CLI::Commands.register "generate configuration", Foo::CLI::Commands::Generate::Configuration
108
-
109
- Dry::CLI.new(Foo::CLI::Commands).call
110
- ```
111
-
112
- ### Arguments
113
-
114
- An argument is a token passed after the _command name_.
115
- For instance, given the `foo greet` command, when an user types `foo greet Luca`, then `Luca` is considered an argument.
116
- A command can accept none or many arguments.
117
- An argument can be declared as _required_.
118
-
119
- ```ruby
120
- #!/usr/bin/env ruby
121
- require "bundler/setup"
122
- require "dry/cli"
123
-
124
- module Foo
125
- module CLI
126
- module Commands
127
- extend Dry::CLI::Registry
128
-
129
- class Greet < Dry::CLI::Command
130
- argument :name, required: true, desc: "The name of the person to greet"
131
- argument :age, desc: "The age of the person to greet"
132
-
133
- def call(name:, age: nil, **)
134
- result = "Hello, #{name}."
135
- result = "#{result} You are #{age} years old." unless age.nil?
136
-
137
- puts result
138
- end
139
- end
140
-
141
- register "greet", Greet
142
- end
143
- end
144
- end
145
-
146
- Dry::CLI.new(Foo::CLI::Commands).call
147
- ```
148
-
149
- ```shell
150
- % foo greet Luca
151
- Hello, Luca.
152
- ```
153
-
154
- ```shell
155
- % foo greet Luca 35
156
- Hello, Luca. You are 35 years old.
157
- ```
158
-
159
- ```shell
160
- % foo greet
161
- ERROR: "foo greet" was called with no arguments
162
- Usage: "foo greet NAME"
163
- ```
164
-
165
- ### Option
166
-
167
- An option is a named argument that is passed after the _command name_ **and** the arguments.
168
-
169
- For instance, given the `foo request` command, when an user types `foo request --mode=http2`, then `--mode=http2` is considered an option.
170
- A command can accept none or many options.
171
-
172
- ```ruby
173
- #!/usr/bin/env ruby
174
- require "bundler/setup"
175
- require "dry/cli"
176
-
177
- module Foo
178
- module CLI
179
- module Commands
180
- extend Dry::CLI::Registry
181
-
182
- class Request < Dry::CLI::Command
183
- option :mode, default: "http", values: %w[http http2], desc: "The request mode"
184
-
185
- def call(**options)
186
- puts "Performing a request (mode: #{options.fetch(:mode)})"
187
- end
188
- end
189
-
190
- register "request", Request
191
- end
192
- end
193
- end
194
-
195
- Dry::CLI.new(Foo::CLI::Commands).call
196
- ```
197
-
198
- ```shell
199
- % foo request
200
- Performing a request (mode: http)
201
- ```
202
-
203
- ```shell
204
- % foo request --mode=http2
205
- Performing a request (mode: http2)
206
- ```
207
-
208
- ```shell
209
- % foo request --mode=unknown
210
- Error: "request" was called with arguments "--mode=unknown"
211
- ```
212
-
213
- ### Variadic arguments
214
-
215
- Sometimes we need extra arguments because those will be forwarded to a sub-command like `ssh`, `docker` or `cat`.
216
-
217
- By using `--` (double dash, aka hypen), the user indicates the end of the arguments and options belonging to the main command, and the beginning of the variadic arguments that can be forwarded to the sub-command.
218
- These extra arguments are included as `:args` in the keyword arguments available for each command.
219
-
220
- ```ruby
221
- #!/usr/bin/env ruby
222
- require "bundler/setup"
223
- require "dry/cli"
224
-
225
- module Foo
226
- module CLI
227
- module Commands
228
- extend Dry::CLI::Registry
229
-
230
- class Runner < Dry::CLI::Command
231
- argument :image, required: true, desc: "Docker image"
232
-
233
- def call(image:, args: [], **)
234
- puts `docker run -it --rm #{image} #{args.join(" ")}`
235
- end
236
- end
237
-
238
- register "run", Runner
239
- end
240
- end
241
- end
242
-
243
- Dry::CLI.new(Foo::CLI::Commands).call
244
- ```
245
-
246
- ```shell
247
- % foo run ruby:latest -- ruby -v
248
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
249
- ```
250
-
251
- The user separates via `--` the arguments for `foo` and the command has to be run by the Docker container.
252
- In this specific case, `ruby:latest` corresponds to the `image` mandatory argument for `foo`, whereas `ruby -v` is the variadic argument that is passed to Docker via `args`.
253
-
254
- ## Installation
255
-
256
- Add this line to your application's Gemfile:
257
-
258
- ```ruby
259
- gem "dry-cli"
260
- ```
261
-
262
- And then execute:
263
-
264
- $ bundle
265
-
266
- Or install it yourself as:
267
-
268
- $ gem install dry-cli
269
-
270
- ## Usage
271
-
272
- Imagine to build a CLI executable `foo` for your Ruby project.
273
-
274
- ```ruby
275
- #!/usr/bin/env ruby
276
- require "bundler/setup"
277
- require "dry/cli"
278
-
279
- module Foo
280
- module CLI
281
- module Commands
282
- extend Dry::CLI::Registry
283
-
284
- class Version < Dry::CLI::Command
285
- desc "Print version"
286
-
287
- def call(*)
288
- puts "1.0.0"
289
- end
290
- end
291
-
292
- class Echo < Dry::CLI::Command
293
- desc "Print input"
294
-
295
- argument :input, desc: "Input to print"
296
-
297
- example [
298
- " # Prints 'wuh?'",
299
- "hello, folks # Prints 'hello, folks'"
300
- ]
301
-
302
- def call(input: nil, **)
303
- if input.nil?
304
- puts "wuh?"
305
- else
306
- puts input
307
- end
308
- end
309
- end
310
-
311
- class Start < Dry::CLI::Command
312
- desc "Start Foo machinery"
313
-
314
- argument :root, required: true, desc: "Root directory"
315
-
316
- example [
317
- "path/to/root # Start Foo at root directory"
318
- ]
319
-
320
- def call(root:, **)
321
- puts "started - root: #{root}"
322
- end
323
- end
324
-
325
- class Stop < Dry::CLI::Command
326
- desc "Stop Foo machinery"
327
-
328
- option :graceful, type: :boolean, default: true, desc: "Graceful stop"
329
-
330
- def call(**options)
331
- puts "stopped - graceful: #{options.fetch(:graceful)}"
332
- end
333
- end
334
-
335
- class Exec < Dry::CLI::Command
336
- desc "Execute a task"
337
-
338
- argument :task, type: :string, required: true, desc: "Task to be executed"
339
- argument :dirs, type: :array, required: false, desc: "Optional directories"
340
-
341
- def call(task:, dirs: [], **)
342
- puts "exec - task: #{task}, dirs: #{dirs.inspect}"
343
- end
344
- end
345
-
346
- module Generate
347
- class Configuration < Dry::CLI::Command
348
- desc "Generate configuration"
349
-
350
- option :apps, type: :array, default: [], desc: "Generate configuration for specific apps"
351
-
352
- def call(apps:, **)
353
- puts "generated configuration for apps: #{apps.inspect}"
354
- end
355
- end
356
-
357
- class Test < Dry::CLI::Command
358
- desc "Generate tests"
359
-
360
- option :framework, default: "minitest", values: %w[minitest rspec]
361
-
362
- def call(framework:, **)
363
- puts "generated tests - framework: #{framework}"
364
- end
365
- end
366
- end
367
-
368
- register "version", Version, aliases: ["v", "-v", "--version"]
369
- register "echo", Echo
370
- register "start", Start
371
- register "stop", Stop
372
- register "exec", Exec
373
-
374
- register "generate", aliases: ["g"] do |prefix|
375
- prefix.register "config", Generate::Configuration
376
- prefix.register "test", Generate::Test
377
- end
378
- end
379
- end
380
- end
381
-
382
- Dry::CLI.new(Foo::CLI::Commands).call
383
- ```
384
-
385
- Let's have a look at the command line usage.
386
-
387
- ### Available commands
388
-
389
- ```shell
390
- % foo
391
- Commands:
392
- foo echo [INPUT] # Print input
393
- foo exec TASK [DIRS] # Execute a task
394
- foo generate [SUBCOMMAND]
395
- foo start ROOT # Start Foo machinery
396
- foo stop # Stop Foo machinery
397
- foo version # Print version
398
- ```
399
-
400
- ### Help
401
-
402
- ```shell
403
- % foo echo --help
404
- Command:
405
- foo echo
406
-
407
- Usage:
408
- foo echo [INPUT]
409
-
410
- Description:
411
- Print input
412
-
413
- Arguments:
414
- INPUT # Input to print
415
-
416
- Options:
417
- --help, -h # Print this help
418
-
419
- Examples:
420
- foo echo # Prints 'wuh?'
421
- foo echo hello, folks # Prints 'hello, folks'
422
- ```
423
-
424
- ### Optional arguments
425
-
426
- ```shell
427
- % foo echo
428
- wuh?
429
-
430
- % foo echo hello
431
- hello
432
- ```
433
-
434
- ### Required arguments
435
-
436
- ```shell
437
- % foo start .
438
- started - root: .
439
- ```
440
-
441
- ```shell
442
- % foo start
443
- ERROR: "foo start" was called with no arguments
444
- Usage: "foo start ROOT"
445
- ```
446
-
447
- ### Array arguments
448
-
449
- Captures all the remaining arguments in a single array.
450
- Please note that `array` argument must be used as last argument as it works as a _"catch-all"_.
451
-
452
- ```shell
453
- % foo exec test
454
- exec - task: test, dirs: []
455
- ```
456
-
457
- ```shell
458
- % foo exec test spec/bookshelf/entities spec/bookshelf/repositories
459
- exec - task: test, dirs: ["spec/bookshelf/entities", "spec/bookshelf/repositories"]
460
- ```
461
-
462
- ### Options
463
-
464
- ```shell
465
- % foo generate test
466
- generated tests - framework: minitest
467
- ```
468
-
469
- ```shell
470
- % foo generate test --framework=rspec
471
- generated tests - framework: rspec
472
- ```
473
-
474
- ```shell
475
- % foo generate test --framework=unknown
476
- Error: "test" was called with arguments "--framework=unknown"
477
- ```
478
-
479
- ### Boolean options
480
-
481
- ```shell
482
- % foo stop
483
- stopped - graceful: true
484
- ```
485
-
486
- ```shell
487
- % foo stop --no-graceful
488
- stopped - graceful: false
489
- ```
490
-
491
- ### Array options
492
-
493
- ```shell
494
- % foo generate config --apps=web,api
495
- generated configuration for apps: ["web", "api"]
496
- ```
497
-
498
- ### Subcommands
499
-
500
- ```shell
501
- % foo generate
502
- Commands:
503
- foo generate config # Generate configuration
504
- foo generate test # Generate tests
505
- ```
506
-
507
- ### Aliases
508
-
509
- ```shell
510
- % foo version
511
- 1.0.0
512
- ```
513
-
514
- ```shell
515
- % foo v
516
- 1.0.0
517
- ```
518
-
519
- ```shell
520
- % foo -v
521
- 1.0.0
522
- ```
523
-
524
- ```shell
525
- % foo --version
526
- 1.0.0
527
- ```
528
-
529
- ### Subcommand aliases
530
-
531
- ```shell
532
- % foo g config
533
- generated configuration for apps: []
534
- ```
535
-
536
- ### Callbacks
537
-
538
- Third party gems can register _before_ and _after_ callbacks to enhance a command.
539
-
540
- From the `foo` gem we have a command `hello`.
541
-
542
- ```ruby
543
- #!/usr/bin/env ruby
544
- require "dry/cli"
545
-
546
- module Foo
547
- module CLI
548
- module Commands
549
- extend Dry::CLI::Registry
550
-
551
- class Hello < Dry::CLI::Command
552
- argument :name, required: true
553
-
554
- def call(name:, **)
555
- puts "hello #{name}"
556
- end
557
- end
558
- end
559
- end
560
- end
561
-
562
- Foo::CLI::Commands.register "hello", Foo::CLI::Commands::Hello
563
-
564
- cli = Dry::CLI.new(Foo::CLI::Commands)
565
- cli.call
566
- ```
567
-
568
- The `foo-bar` gem enhances `hello` command with callbacks:
569
-
570
- ```ruby
571
- Foo::CLI::Commands.before("hello") { |args| puts "debug: #{args.inspect}" } # syntax 1
572
- Foo::CLI::Commands.after "hello", &->(args) { puts "bye, #{args.fetch(:name)}" } # syntax 2
573
- ```
574
-
575
- ```shell
576
- % foo hello Anton
577
- debug: {:name=>"Anton"}
578
- hello Anton
579
- bye, Anton
580
- ```
581
-
582
- ### File Utilities
583
-
584
- File utilities is a set of useful methods to manipulate files and directories, which is opted to be required. [API doc](http://www.rubydoc.info/gems/dry-cli/Dry/CLI/Utils/Files)
585
-
586
- ```ruby
587
- require 'dry/cli/utils/files'
588
- ```