commander 5.0.0 → 6.0.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 +4 -4
- data/.github/workflows/ci.yml +67 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +1 -4
- data/.rubocop_todo.yml +46 -42
- data/.ruby-version +1 -0
- data/Gemfile +10 -0
- data/History.rdoc +7 -0
- data/README.md +7 -32
- data/commander.gemspec +3 -8
- data/lib/commander/blank.rb +9 -0
- data/lib/commander/command.rb +26 -11
- data/lib/commander/configure.rb +30 -2
- data/lib/commander/core_ext/array.rb +3 -1
- data/lib/commander/core_ext/object.rb +3 -1
- data/lib/commander/delegates.rb +10 -0
- data/lib/commander/help_formatters/base.rb +11 -7
- data/lib/commander/help_formatters/terminal.rb +13 -5
- data/lib/commander/help_formatters/terminal_compact.rb +8 -5
- data/lib/commander/help_formatters.rb +28 -0
- data/lib/commander/methods.rb +12 -0
- data/lib/commander/platform.rb +6 -0
- data/lib/commander/runner.rb +17 -38
- data/lib/commander/user_interaction.rb +30 -59
- data/lib/commander/version.rb +1 -1
- metadata +12 -90
- data/.travis.yml +0 -12
- data/Manifest +0 -38
- data/spec/command_spec.rb +0 -198
- data/spec/configure_spec.rb +0 -39
- data/spec/core_ext/array_spec.rb +0 -20
- data/spec/core_ext/object_spec.rb +0 -21
- data/spec/help_formatters/terminal_compact_spec.rb +0 -71
- data/spec/help_formatters/terminal_spec.rb +0 -69
- data/spec/methods_spec.rb +0 -63
- data/spec/runner_spec.rb +0 -761
- data/spec/spec_helper.rb +0 -89
- data/spec/ui_spec.rb +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2e21aee4b50aee1e76830f9f084a14f31ca37b2b78ce330363ef6811e5af924b
|
|
4
|
+
data.tar.gz: 29086cb85530a560b2ada64092eb63f2924c7b6b1014b1229ac085630ca38456
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6bfbc2fef5110d982b14b1cba0af293620b52df2a8265e74cc6db8fae48a6d4c1d042ee4bf5f6825402604a4884fe52917faae7031c5ad6e317a4bc8e4475a3c
|
|
7
|
+
data.tar.gz: beedd12841890d36708b894e1a88c315a453f2cd2805178449f338606b391b8a9e793215bc2f893275b23eca568a26186c1b5e5071e49efe432a5cc7af9748db
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Ruby ${{ matrix.ruby }}
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
ruby:
|
|
20
|
+
- '3.1'
|
|
21
|
+
- '3.2'
|
|
22
|
+
- '3.3'
|
|
23
|
+
- '3.4'
|
|
24
|
+
- '4.0.6'
|
|
25
|
+
- jruby
|
|
26
|
+
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
|
|
30
|
+
- name: Set up Ruby
|
|
31
|
+
uses: ruby/setup-ruby@v1
|
|
32
|
+
with:
|
|
33
|
+
ruby-version: ${{ matrix.ruby }}
|
|
34
|
+
bundler-cache: true
|
|
35
|
+
|
|
36
|
+
- name: Run tests
|
|
37
|
+
run: bundle exec rake spec
|
|
38
|
+
|
|
39
|
+
lint:
|
|
40
|
+
name: RuboCop
|
|
41
|
+
runs-on: ubuntu-latest
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/checkout@v4
|
|
44
|
+
|
|
45
|
+
- name: Set up Ruby
|
|
46
|
+
uses: ruby/setup-ruby@v1
|
|
47
|
+
with:
|
|
48
|
+
ruby-version: '4.0.6'
|
|
49
|
+
bundler-cache: true
|
|
50
|
+
|
|
51
|
+
- name: Run RuboCop
|
|
52
|
+
run: bundle exec rubocop
|
|
53
|
+
|
|
54
|
+
security:
|
|
55
|
+
name: Bundler Audit
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
|
|
60
|
+
- name: Set up Ruby
|
|
61
|
+
uses: ruby/setup-ruby@v1
|
|
62
|
+
with:
|
|
63
|
+
ruby-version: '4.0.6'
|
|
64
|
+
bundler-cache: true
|
|
65
|
+
|
|
66
|
+
- name: Run bundler-audit
|
|
67
|
+
run: bundle exec bundler-audit check --update
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
inherit_from: .rubocop_todo.yml
|
|
2
2
|
|
|
3
3
|
AllCops:
|
|
4
|
-
TargetRubyVersion: 3.
|
|
4
|
+
TargetRubyVersion: 3.1
|
|
5
5
|
NewCops: enable
|
|
6
6
|
SuggestExtensions: false
|
|
7
7
|
|
|
@@ -54,9 +54,6 @@ Style/FormatStringToken:
|
|
|
54
54
|
Style/MixinUsage:
|
|
55
55
|
Enabled: false
|
|
56
56
|
|
|
57
|
-
Lint/ErbNewArguments:
|
|
58
|
-
Enabled: false
|
|
59
|
-
|
|
60
57
|
Style/DocumentDynamicEvalDefinition:
|
|
61
58
|
Enabled: false
|
|
62
59
|
|
data/.rubocop_todo.yml
CHANGED
|
@@ -1,77 +1,81 @@
|
|
|
1
|
-
# This configuration was generated by
|
|
2
|
-
#
|
|
1
|
+
# This configuration was generated by
|
|
2
|
+
# `rubocop --auto-gen-config --no-auto-gen-timestamp`
|
|
3
|
+
# using RuboCop version 1.88.2.
|
|
3
4
|
# The point is for the user to remove these configuration records
|
|
4
5
|
# one by one as the offenses are removed from the code base.
|
|
5
6
|
# Note that changes in the inspected code, or installation of new
|
|
6
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
7
8
|
|
|
8
|
-
# Offense count:
|
|
9
|
-
|
|
10
|
-
Enabled: false
|
|
11
|
-
|
|
12
|
-
# Offense count: 2
|
|
9
|
+
# Offense count: 1
|
|
10
|
+
# Configuration parameters: AllowComments, AllowNil.
|
|
13
11
|
Lint/SuppressedException:
|
|
14
|
-
|
|
12
|
+
Exclude:
|
|
13
|
+
- 'lib/commander/user_interaction.rb'
|
|
15
14
|
|
|
16
|
-
# Offense count:
|
|
15
|
+
# Offense count: 6
|
|
16
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
|
|
17
17
|
Metrics/AbcSize:
|
|
18
18
|
Max: 30
|
|
19
19
|
|
|
20
20
|
# Offense count: 1
|
|
21
|
-
# Configuration parameters: CountComments.
|
|
21
|
+
# Configuration parameters: CountComments, CountAsOne.
|
|
22
22
|
Metrics/ClassLength:
|
|
23
|
-
|
|
23
|
+
Max: 250
|
|
24
24
|
|
|
25
|
-
# Offense count:
|
|
25
|
+
# Offense count: 5
|
|
26
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
26
27
|
Metrics/CyclomaticComplexity:
|
|
27
28
|
Max: 13
|
|
28
29
|
|
|
29
|
-
# Offense count:
|
|
30
|
-
# Configuration parameters:
|
|
31
|
-
Layout/LineLength:
|
|
32
|
-
Max: 242
|
|
33
|
-
|
|
34
|
-
# Offense count: 7
|
|
35
|
-
# Configuration parameters: CountComments.
|
|
30
|
+
# Offense count: 8
|
|
31
|
+
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
36
32
|
Metrics/MethodLength:
|
|
37
33
|
Max: 36
|
|
38
34
|
|
|
39
|
-
# Offense count:
|
|
35
|
+
# Offense count: 5
|
|
36
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns.
|
|
40
37
|
Metrics/PerceivedComplexity:
|
|
41
38
|
Max: 14
|
|
42
39
|
|
|
43
|
-
# Offense count:
|
|
40
|
+
# Offense count: 2
|
|
44
41
|
Naming/AccessorMethodName:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
Style/Documentation:
|
|
49
|
-
Enabled: false
|
|
50
|
-
|
|
51
|
-
# Offense count: 12
|
|
52
|
-
# Configuration parameters: AllowedVariables.
|
|
53
|
-
Style/GlobalVars:
|
|
54
|
-
Enabled: false
|
|
42
|
+
Exclude:
|
|
43
|
+
- 'lib/commander/core_ext/object.rb'
|
|
44
|
+
- 'lib/commander/help_formatters.rb'
|
|
55
45
|
|
|
56
46
|
# Offense count: 1
|
|
57
|
-
|
|
47
|
+
Security/Eval:
|
|
48
|
+
Exclude:
|
|
49
|
+
- 'lib/commander/delegates.rb'
|
|
50
|
+
|
|
51
|
+
# Offense count: 2
|
|
52
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
58
53
|
Style/IfUnlessModifier:
|
|
59
|
-
|
|
54
|
+
Exclude:
|
|
55
|
+
- 'lib/commander/runner.rb'
|
|
56
|
+
- 'lib/commander/user_interaction.rb'
|
|
60
57
|
|
|
61
58
|
# Offense count: 1
|
|
62
59
|
Style/MultilineBlockChain:
|
|
63
|
-
|
|
60
|
+
Exclude:
|
|
61
|
+
- 'lib/commander/user_interaction.rb'
|
|
64
62
|
|
|
65
63
|
# Offense count: 1
|
|
64
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
66
65
|
Style/MultilineTernaryOperator:
|
|
67
|
-
|
|
66
|
+
Exclude:
|
|
67
|
+
- 'lib/commander/user_interaction.rb'
|
|
68
68
|
|
|
69
|
-
# Offense count:
|
|
69
|
+
# Offense count: 4
|
|
70
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
70
71
|
Style/RescueModifier:
|
|
71
|
-
|
|
72
|
+
Exclude:
|
|
73
|
+
- 'lib/commander/runner.rb'
|
|
74
|
+
- 'lib/commander/user_interaction.rb'
|
|
72
75
|
|
|
73
|
-
# Offense count:
|
|
74
|
-
#
|
|
75
|
-
# Configuration parameters:
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
# Offense count: 5
|
|
77
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
78
|
+
# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
79
|
+
# URISchemes: http, https
|
|
80
|
+
Layout/LineLength:
|
|
81
|
+
Max: 242
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.6
|
data/Gemfile
CHANGED
|
@@ -3,3 +3,13 @@
|
|
|
3
3
|
source 'https://rubygems.org'
|
|
4
4
|
|
|
5
5
|
gemspec
|
|
6
|
+
|
|
7
|
+
group :development, :test do
|
|
8
|
+
gem 'bundler-audit', '~> 0.9'
|
|
9
|
+
gem 'rake', '~> 13.0'
|
|
10
|
+
gem 'rspec', '~> 3.13'
|
|
11
|
+
gem 'rubocop', '~> 1.88'
|
|
12
|
+
# 1.x requires Ruby >= 3.2; allow the last 0.x on Ruby 3.1 while newer
|
|
13
|
+
# rubies still resolve to 1.x.
|
|
14
|
+
gem 'simplecov', '>= 0.22', '< 2'
|
|
15
|
+
end
|
data/History.rdoc
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
=== 6.0.0 / 2026-08-01
|
|
2
|
+
|
|
3
|
+
* Drop support for Ruby 3.0; require Ruby >= 3.1 (#104). (@dior001)
|
|
4
|
+
* Update highline dependency to ~> 3.1 (#104). (@dior001)
|
|
5
|
+
* Modernize the codebase for the current Ruby ecosystem, including frozen string literals and anonymous block forwarding (#104). (@dior001)
|
|
6
|
+
* Fix `SortedSet` error on Ruby 3.2+, where it was extracted from the `set` library (#104).
|
|
7
|
+
|
|
1
8
|
=== 5.0.0 / 2024-01-15
|
|
2
9
|
|
|
3
10
|
* Drop support for Ruby < 3.0; update highline dependency to ~3.0 (#102). (@belousovAV)
|
data/README.md
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
[
|
|
2
|
-
[](https://inch-ci.org/github/commander-rb/commander)
|
|
1
|
+
[](https://github.com/commander-rb/commander/actions/workflows/ci.yml)
|
|
3
2
|
|
|
4
3
|
# Commander
|
|
5
4
|
|
|
@@ -24,9 +23,12 @@ features, and an elegant API.
|
|
|
24
23
|
* Sexy paging for long bodies of text
|
|
25
24
|
* Support for MacOS text-to-speech
|
|
26
25
|
* Command aliasing (very powerful, as both switches and arguments can be used)
|
|
27
|
-
* Growl notification support for MacOS
|
|
28
26
|
* Use the `commander` executable to initialize a commander driven program
|
|
29
27
|
|
|
28
|
+
## Requirements
|
|
29
|
+
|
|
30
|
+
Ruby >= 3.1 (tested through Ruby 4.0).
|
|
31
|
+
|
|
30
32
|
## Installation
|
|
31
33
|
|
|
32
34
|
$ gem install commander
|
|
@@ -50,7 +52,6 @@ as well as an object, specifying a method to call, so view the RDoc for more inf
|
|
|
50
52
|
### Classic style
|
|
51
53
|
|
|
52
54
|
```ruby
|
|
53
|
-
require 'rubygems'
|
|
54
55
|
require 'commander/import'
|
|
55
56
|
|
|
56
57
|
# :name is optional, otherwise uses the basename of this executable
|
|
@@ -93,7 +94,6 @@ $ foobar bar --suffix '}' --prefix '{'
|
|
|
93
94
|
**NOTE:** Make sure to use `require 'commander'` rather than `require 'commander/import'`, otherwise Commander methods will still be imported into the global namespace.
|
|
94
95
|
|
|
95
96
|
```ruby
|
|
96
|
-
require 'rubygems'
|
|
97
97
|
require 'commander'
|
|
98
98
|
|
|
99
99
|
class MyApplication
|
|
@@ -122,7 +122,6 @@ MyApplication.new.run if $0 == __FILE__
|
|
|
122
122
|
### Block style
|
|
123
123
|
|
|
124
124
|
```ruby
|
|
125
|
-
require 'rubygems'
|
|
126
125
|
require 'commander'
|
|
127
126
|
|
|
128
127
|
Commander.configure do
|
|
@@ -240,30 +239,6 @@ else
|
|
|
240
239
|
end
|
|
241
240
|
```
|
|
242
241
|
|
|
243
|
-
## Growl Notifications
|
|
244
|
-
|
|
245
|
-
Commander provides methods for displaying Growl notifications. To use these
|
|
246
|
-
methods you need to install https://github.com/tj/growl which utilizes
|
|
247
|
-
the [growlnotify](https://growl.info/extras.php#growlnotify) executable. Note that
|
|
248
|
-
growl is auto-imported by Commander when available, no need to require.
|
|
249
|
-
|
|
250
|
-
```ruby
|
|
251
|
-
# Display a generic Growl notification
|
|
252
|
-
notify 'Something happened'
|
|
253
|
-
|
|
254
|
-
# Display an 'info' status notification
|
|
255
|
-
notify_info 'You have #{emails.length} new email(s)'
|
|
256
|
-
|
|
257
|
-
# Display an 'ok' status notification
|
|
258
|
-
notify_ok 'Gems updated'
|
|
259
|
-
|
|
260
|
-
# Display a 'warning' status notification
|
|
261
|
-
notify_warning '1 gem failed installation'
|
|
262
|
-
|
|
263
|
-
# Display an 'error' status notification
|
|
264
|
-
notify_error "Gem #{name} failed"
|
|
265
|
-
```
|
|
266
|
-
|
|
267
242
|
## Commander Goodies
|
|
268
243
|
|
|
269
244
|
### Option Defaults
|
|
@@ -459,11 +434,11 @@ For feature rich ASCII tables for your terminal app check out the terminal-table
|
|
|
459
434
|
|
|
460
435
|
## Running Specifications
|
|
461
436
|
|
|
462
|
-
$ rake spec
|
|
437
|
+
$ bundle exec rake spec
|
|
463
438
|
|
|
464
439
|
OR
|
|
465
440
|
|
|
466
|
-
$
|
|
441
|
+
$ bundle exec rspec
|
|
467
442
|
|
|
468
443
|
## Contrib
|
|
469
444
|
|
data/commander.gemspec
CHANGED
|
@@ -18,18 +18,13 @@ Gem::Specification.new do |s|
|
|
|
18
18
|
'documentation_uri' => "https://www.rubydoc.info/gems/commander/#{s.version}",
|
|
19
19
|
'homepage_uri' => s.homepage,
|
|
20
20
|
'source_code_uri' => "#{s.homepage}/tree/v#{s.version}",
|
|
21
|
+
'rubygems_mfa_required' => 'true',
|
|
21
22
|
}
|
|
22
|
-
s.required_ruby_version = '>= 3.
|
|
23
|
+
s.required_ruby_version = '>= 3.1'
|
|
23
24
|
|
|
24
25
|
s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
25
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
26
26
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
|
27
27
|
s.require_paths = ['lib']
|
|
28
28
|
|
|
29
|
-
s.
|
|
30
|
-
|
|
31
|
-
s.add_development_dependency('rake')
|
|
32
|
-
s.add_development_dependency('rspec', '~> 3.2')
|
|
33
|
-
s.add_development_dependency('rubocop', '~> 1.12.1')
|
|
34
|
-
s.add_development_dependency('simplecov')
|
|
29
|
+
s.add_dependency('highline', '~> 3.1')
|
|
35
30
|
end
|
data/lib/commander/blank.rb
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# Strips a class of (almost) all its instance methods, leaving it as a
|
|
5
|
+
# near-blank slate. Mixed into Commander::Command::Options so that
|
|
6
|
+
# +method_missing+ can treat arbitrary option names as accessors without
|
|
7
|
+
# clashing with methods Ruby defines on every object (e.g. +send+, +type+).
|
|
3
8
|
module Blank
|
|
9
|
+
##
|
|
10
|
+
# Undefines every instance method on +base+ except those beginning with
|
|
11
|
+
# a double underscore and +object_id+, which are kept so the resulting
|
|
12
|
+
# object remains minimally usable (e.g. for +__send__+ and identity checks).
|
|
4
13
|
def self.included(base)
|
|
5
14
|
base.class_eval do
|
|
6
15
|
instance_methods.each { |m| undef_method m unless m =~ /^__|object_id/ }
|
data/lib/commander/command.rb
CHANGED
|
@@ -3,13 +3,29 @@
|
|
|
3
3
|
require 'optparse'
|
|
4
4
|
|
|
5
5
|
module Commander
|
|
6
|
+
##
|
|
7
|
+
# A single named command belonging to a Commander::Runner: its
|
|
8
|
+
# description, examples, options (parsed via OptionParser), and the
|
|
9
|
+
# handler invoked with the remaining arguments once options have been
|
|
10
|
+
# parsed. Built up via the block yielded by Runner#command, e.g.
|
|
11
|
+
#
|
|
12
|
+
# command :foo do |c|
|
|
13
|
+
# c.syntax = 'foo [options]'
|
|
14
|
+
# c.option '--bar', 'A switch'
|
|
15
|
+
# c.action { |args, options| ... }
|
|
16
|
+
# end
|
|
6
17
|
class Command
|
|
7
18
|
attr_accessor :name, :examples, :syntax, :description, :summary, :proxy_options, :options
|
|
8
19
|
attr_reader :global_options
|
|
9
20
|
|
|
10
21
|
##
|
|
11
22
|
# Options struct.
|
|
12
|
-
|
|
23
|
+
#
|
|
24
|
+
# An open-ended, OpenStruct-like object populated by #option and
|
|
25
|
+
# #proxy_option_struct. Reading an unset attribute returns +nil+;
|
|
26
|
+
# writing any attribute (via +some_attr=+) stores it. Almost all of
|
|
27
|
+
# Object's own instance methods are stripped out (see Blank) so that
|
|
28
|
+
# option names never collide with built-ins like +send+ or +class+.
|
|
13
29
|
class Options
|
|
14
30
|
include Blank
|
|
15
31
|
|
|
@@ -17,14 +33,22 @@ module Commander
|
|
|
17
33
|
@table = {}
|
|
18
34
|
end
|
|
19
35
|
|
|
36
|
+
##
|
|
37
|
+
# The underlying Hash of option name (Symbol) => value pairs.
|
|
20
38
|
def __hash__
|
|
21
39
|
@table
|
|
22
40
|
end
|
|
23
41
|
|
|
42
|
+
##
|
|
43
|
+
# Reads or writes an arbitrary option. <tt>options.foo</tt> reads
|
|
44
|
+
# the +:foo+ entry; <tt>options.foo = 1</tt> writes it.
|
|
24
45
|
def method_missing(meth, *args)
|
|
25
46
|
meth.to_s =~ /=$/ ? @table[meth.to_s.chop.to_sym] = args.first : @table[meth]
|
|
26
47
|
end
|
|
27
48
|
|
|
49
|
+
##
|
|
50
|
+
# Merge _defaults_ into this struct, without overwriting any
|
|
51
|
+
# options already set.
|
|
28
52
|
def default(defaults = {})
|
|
29
53
|
@table = defaults.merge! @table
|
|
30
54
|
end
|
|
@@ -36,7 +60,6 @@ module Commander
|
|
|
36
60
|
|
|
37
61
|
##
|
|
38
62
|
# Initialize new command with specified _name_.
|
|
39
|
-
|
|
40
63
|
def initialize(name)
|
|
41
64
|
@name, @examples, @when_called = name.to_s, [], []
|
|
42
65
|
@options, @proxy_options = [], []
|
|
@@ -55,7 +78,6 @@ module Commander
|
|
|
55
78
|
# c.example "Should do something", "my_command something"
|
|
56
79
|
# end
|
|
57
80
|
#
|
|
58
|
-
|
|
59
81
|
def example(description, command)
|
|
60
82
|
@examples << [description, command]
|
|
61
83
|
end
|
|
@@ -106,7 +128,6 @@ module Commander
|
|
|
106
128
|
# c.option '--time TIME', Time
|
|
107
129
|
# c.option '--date [DATE]', Date
|
|
108
130
|
#
|
|
109
|
-
|
|
110
131
|
def option(*args, &block)
|
|
111
132
|
switches, description = Runner.separate_switches_from_description(*args)
|
|
112
133
|
proc = block || option_proc(switches)
|
|
@@ -138,7 +159,6 @@ module Commander
|
|
|
138
159
|
# # Pass an object to handle callback (requires method symbol)
|
|
139
160
|
# c.when_called SomeObject, :some_method
|
|
140
161
|
#
|
|
141
|
-
|
|
142
162
|
def when_called(*args, &block)
|
|
143
163
|
fail ArgumentError, 'must pass an object, class, or block.' if args.empty? && !block
|
|
144
164
|
|
|
@@ -152,17 +172,15 @@ module Commander
|
|
|
152
172
|
# * parses options, call option blocks
|
|
153
173
|
# * invokes when_called proc
|
|
154
174
|
#
|
|
155
|
-
|
|
156
175
|
def run(*args)
|
|
157
176
|
call parse_options_and_call_procs(*args)
|
|
158
177
|
end
|
|
159
178
|
|
|
160
|
-
|
|
179
|
+
# :stopdoc:
|
|
161
180
|
|
|
162
181
|
##
|
|
163
182
|
# Parses options and calls associated procs,
|
|
164
183
|
# returning the arguments remaining.
|
|
165
|
-
|
|
166
184
|
def parse_options_and_call_procs(*args)
|
|
167
185
|
return args if args.empty?
|
|
168
186
|
|
|
@@ -177,7 +195,6 @@ module Commander
|
|
|
177
195
|
|
|
178
196
|
##
|
|
179
197
|
# Call the commands when_called block with _args_.
|
|
180
|
-
|
|
181
198
|
def call(args = [])
|
|
182
199
|
object, meth = @when_called[0, 2]
|
|
183
200
|
meth ||= :call
|
|
@@ -193,7 +210,6 @@ module Commander
|
|
|
193
210
|
##
|
|
194
211
|
# Creates an Options instance populated with the option values
|
|
195
212
|
# collected by the #option_proc.
|
|
196
|
-
|
|
197
213
|
def proxy_option_struct
|
|
198
214
|
(global_options + proxy_options).each_with_object(Options.new) do |(option, value), options|
|
|
199
215
|
# options that are present will evaluate to true
|
|
@@ -207,7 +223,6 @@ module Commander
|
|
|
207
223
|
# Option proxy proc used when a block is not explicitly passed
|
|
208
224
|
# via the #option method. This allows commander to auto-populate
|
|
209
225
|
# and work with option values.
|
|
210
|
-
|
|
211
226
|
def option_proc(switches)
|
|
212
227
|
->(value) { proxy_options << [Runner.switch_to_sym(switches.last), value] }
|
|
213
228
|
end
|
data/lib/commander/configure.rb
CHANGED
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# Commander is the top-level namespace for the whole gem: see
|
|
5
|
+
# Commander::Methods for the DSL mixin, Commander::Runner for the engine
|
|
6
|
+
# that drives it, and Commander::Command for individual commands.
|
|
3
7
|
module Commander
|
|
4
|
-
|
|
8
|
+
##
|
|
9
|
+
# Runs a Commander program within an isolated, anonymous module rather
|
|
10
|
+
# than polluting the including object (as Commander::Methods normally
|
|
11
|
+
# does when included directly). Useful for embedding a Commander CLI
|
|
12
|
+
# inside a larger application without leaking its DSL methods. Calls
|
|
13
|
+
# Runner#run! once the block has finished configuring commands.
|
|
14
|
+
#
|
|
15
|
+
# Any _configuration_opts_ are passed through as block arguments.
|
|
16
|
+
#
|
|
17
|
+
# === Examples
|
|
18
|
+
#
|
|
19
|
+
# Commander.configure do
|
|
20
|
+
# program :name, 'my-tool'
|
|
21
|
+
# program :version, '1.0.0'
|
|
22
|
+
# program :description, 'Does something useful'
|
|
23
|
+
#
|
|
24
|
+
# command :greet do |c|
|
|
25
|
+
# c.action { |args, _options| say "Hello, #{args.first}!" }
|
|
26
|
+
# end
|
|
27
|
+
# end
|
|
28
|
+
#
|
|
29
|
+
# Commander.configure(default_name) do |name|
|
|
30
|
+
# program :name, name
|
|
31
|
+
# end
|
|
32
|
+
def configure(*configuration_opts, &)
|
|
5
33
|
configuration_module = Module.new
|
|
6
34
|
configuration_module.extend Commander::Methods
|
|
7
35
|
|
|
8
|
-
configuration_module.class_exec(*configuration_opts, &
|
|
36
|
+
configuration_module.class_exec(*configuration_opts, &)
|
|
9
37
|
|
|
10
38
|
configuration_module.class_exec do
|
|
11
39
|
run!
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# Adds Array.parse, used by HighLine's #ask/#ask_for_array so that
|
|
5
|
+
# +ask '...', Array+ splits a raw response into a Ruby Array.
|
|
3
6
|
class Array
|
|
4
7
|
##
|
|
5
8
|
# Split _string_ into an array. Used in
|
|
@@ -17,7 +20,6 @@ class Array
|
|
|
17
20
|
# # or use ask_for_CLASS
|
|
18
21
|
# list = ask_for_array 'Favorite cookies: '
|
|
19
22
|
#
|
|
20
|
-
|
|
21
23
|
def self.parse(string)
|
|
22
24
|
# Using reverse + lookahead to work around Ruby 1.8's lack of lookbehind
|
|
23
25
|
# TODO: simplify now that we don't support Ruby 1.8
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# Adds Object#get_binding, used by HelpFormatter::Context to capture a
|
|
5
|
+
# target object's binding for evaluation inside an ERB help template.
|
|
3
6
|
class Object
|
|
4
7
|
##
|
|
5
8
|
# Return the current binding.
|
|
6
|
-
|
|
7
9
|
def get_binding
|
|
8
10
|
binding
|
|
9
11
|
end
|
data/lib/commander/delegates.rb
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Commander
|
|
4
|
+
##
|
|
5
|
+
# = Delegates
|
|
6
|
+
#
|
|
7
|
+
# Mixed into Commander::Methods to expose the singleton
|
|
8
|
+
# Commander::Runner instance's DSL (+command+, +program+, +run!+, etc.)
|
|
9
|
+
# as top-level methods, so scripts can call them directly instead of
|
|
10
|
+
# reaching through <tt>Commander::Runner.instance</tt>.
|
|
4
11
|
module Delegates
|
|
5
12
|
%w(
|
|
6
13
|
add_command
|
|
@@ -20,6 +27,9 @@ module Commander
|
|
|
20
27
|
END
|
|
21
28
|
end
|
|
22
29
|
|
|
30
|
+
##
|
|
31
|
+
# Delegates to Commander::Runner#commands, returning the hash of
|
|
32
|
+
# registered command name => Commander::Command pairs.
|
|
23
33
|
def defined_commands(...)
|
|
24
34
|
::Commander::Runner.instance.commands(...)
|
|
25
35
|
end
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Commander
|
|
4
|
-
##
|
|
5
|
-
# = Help Formatter
|
|
6
|
-
#
|
|
7
|
-
# Commander's help formatters control the output when
|
|
8
|
-
# either the help command, or --help switch are called.
|
|
9
|
-
# The default formatter is Commander::HelpFormatter::Terminal.
|
|
10
|
-
|
|
11
4
|
module HelpFormatter
|
|
5
|
+
##
|
|
6
|
+
# Base class for help formatters. Subclasses receive the
|
|
7
|
+
# Commander::Runner instance being documented and must implement
|
|
8
|
+
# #render (global help) and #render_command (per-command help). This
|
|
9
|
+
# base implementation renders placeholder text and exists mainly for
|
|
10
|
+
# testing and as a minimal example.
|
|
12
11
|
class Base
|
|
13
12
|
def initialize(runner)
|
|
14
13
|
@runner = runner
|
|
15
14
|
end
|
|
16
15
|
|
|
16
|
+
##
|
|
17
|
+
# Render the global help text shown for <tt>--help</tt> with no
|
|
18
|
+
# command, or the +help+ command with no arguments.
|
|
17
19
|
def render
|
|
18
20
|
'Implement global help here'
|
|
19
21
|
end
|
|
20
22
|
|
|
23
|
+
##
|
|
24
|
+
# Render the help text for a single _command_.
|
|
21
25
|
def render_command(command)
|
|
22
26
|
"Implement help for #{command.name} here"
|
|
23
27
|
end
|
|
@@ -4,21 +4,29 @@ require 'erb'
|
|
|
4
4
|
|
|
5
5
|
module Commander
|
|
6
6
|
module HelpFormatter
|
|
7
|
+
##
|
|
8
|
+
# The default help formatter. Renders full-width, verbosely-labeled
|
|
9
|
+
# help text (examples, per-option descriptions, etc.) from the ERB
|
|
10
|
+
# templates in the neighboring +terminal/+ directory. See
|
|
11
|
+
# HelpFormatter::TerminalCompact for a more condensed alternative.
|
|
7
12
|
class Terminal < Base
|
|
13
|
+
##
|
|
14
|
+
# Render the global help text for the program.
|
|
8
15
|
def render
|
|
9
16
|
template(:help).result(ProgramContext.new(@runner).get_binding)
|
|
10
17
|
end
|
|
11
18
|
|
|
19
|
+
##
|
|
20
|
+
# Render the help text for a single _command_.
|
|
12
21
|
def render_command(command)
|
|
13
22
|
template(:command_help).result(Context.new(command).get_binding)
|
|
14
23
|
end
|
|
15
24
|
|
|
25
|
+
##
|
|
26
|
+
# Compile the ERB template named _name_ (+:help+ or
|
|
27
|
+
# +:command_help+) from this formatter's template directory.
|
|
16
28
|
def template(name)
|
|
17
|
-
|
|
18
|
-
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), nil, '-')
|
|
19
|
-
else
|
|
20
|
-
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), trim_mode: '-')
|
|
21
|
-
end
|
|
29
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), 'terminal', "#{name}.erb")), trim_mode: '-')
|
|
22
30
|
end
|
|
23
31
|
end
|
|
24
32
|
end
|