rfix 1.4.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/rfix +78 -34
- data/lib/rfix.rb +17 -28
- data/lib/rfix/branch.rb +3 -25
- data/lib/rfix/branch/base.rb +27 -0
- data/lib/rfix/branch/head.rb +15 -0
- data/lib/rfix/branch/main.rb +33 -0
- data/lib/rfix/branch/name.rb +21 -0
- data/lib/rfix/branch/reference.rb +15 -0
- data/lib/rfix/branch/upstream.rb +17 -0
- data/lib/rfix/cli/command.rb +19 -0
- data/lib/rfix/cli/command/base.rb +61 -0
- data/lib/rfix/cli/command/branch.rb +13 -0
- data/lib/rfix/cli/command/config.rb +22 -0
- data/lib/rfix/cli/command/extension.rb +25 -0
- data/lib/rfix/cli/command/help.rb +11 -0
- data/lib/rfix/cli/command/info.rb +11 -0
- data/lib/rfix/cli/command/lint.rb +17 -0
- data/lib/rfix/cli/command/local.rb +11 -0
- data/lib/rfix/cli/command/origin.rb +11 -0
- data/lib/rfix/cli/command/setup.rb +11 -0
- data/lib/rfix/error.rb +5 -1
- data/lib/rfix/extension/offense.rb +79 -0
- data/lib/rfix/extension/pastel.rb +11 -0
- data/lib/rfix/extension/string.rb +12 -0
- data/lib/rfix/extension/strings.rb +9 -0
- data/lib/rfix/file.rb +6 -41
- data/lib/rfix/file/base.rb +73 -0
- data/lib/rfix/file/deleted.rb +17 -0
- data/lib/rfix/file/ignored.rb +17 -0
- data/lib/rfix/file/tracked.rb +42 -0
- data/lib/rfix/file/untracked.rb +20 -0
- data/lib/rfix/formatter.rb +125 -86
- data/lib/rfix/highlighter.rb +118 -0
- data/lib/rfix/indicator.rb +19 -0
- data/lib/rfix/log.rb +12 -121
- data/lib/rfix/rake/gemfile.rb +111 -0
- data/lib/rfix/rake/paths.rb +25 -23
- data/lib/rfix/rake/support.rb +72 -57
- data/lib/rfix/repository.rb +114 -164
- data/lib/rfix/types.rb +52 -0
- data/lib/rfix/version.rb +1 -1
- data/rfix.gemspec +28 -38
- data/vendor/dry-cli/CHANGELOG.md +191 -0
- data/vendor/dry-cli/CODEOWNERS +1 -0
- data/vendor/dry-cli/CODE_OF_CONDUCT.md +13 -0
- data/vendor/dry-cli/CONTRIBUTING.md +29 -0
- data/vendor/dry-cli/Gemfile +14 -0
- data/vendor/dry-cli/Gemfile.devtools +18 -0
- data/vendor/dry-cli/LICENSE +20 -0
- data/vendor/dry-cli/README.md +29 -0
- data/vendor/dry-cli/Rakefile +13 -0
- data/vendor/dry-cli/bin/console +15 -0
- data/vendor/dry-cli/bin/setup +8 -0
- data/vendor/dry-cli/changelog.yml +97 -0
- data/vendor/dry-cli/docsite/source/arguments.html.md +57 -0
- data/vendor/dry-cli/docsite/source/callbacks.html.md +51 -0
- data/vendor/dry-cli/docsite/source/commands-with-subcommands-and-params.md +86 -0
- data/vendor/dry-cli/docsite/source/commands.html.md +41 -0
- data/vendor/dry-cli/docsite/source/index.html.md +302 -0
- data/vendor/dry-cli/docsite/source/options.html.md +51 -0
- data/vendor/dry-cli/docsite/source/subcommands.html.md +38 -0
- data/vendor/dry-cli/docsite/source/variadic-arguments.html.md +45 -0
- data/vendor/dry-cli/dry-cli.gemspec +36 -0
- data/vendor/dry-cli/lib/dry/cli.rb +224 -0
- data/vendor/dry-cli/lib/dry/cli/banner.rb +135 -0
- data/vendor/dry-cli/lib/dry/cli/command.rb +387 -0
- data/vendor/dry-cli/lib/dry/cli/command_registry.rb +253 -0
- data/vendor/dry-cli/lib/dry/cli/errors.rb +37 -0
- data/vendor/dry-cli/lib/dry/cli/inflector.rb +17 -0
- data/vendor/dry-cli/lib/dry/cli/inline.rb +75 -0
- data/vendor/dry-cli/lib/dry/cli/option.rb +131 -0
- data/vendor/dry-cli/lib/dry/cli/parser.rb +138 -0
- data/vendor/dry-cli/lib/dry/cli/program_name.rb +21 -0
- data/vendor/dry-cli/lib/dry/cli/registry.rb +338 -0
- data/vendor/dry-cli/lib/dry/cli/usage.rb +94 -0
- data/vendor/dry-cli/lib/dry/cli/version.rb +8 -0
- data/vendor/dry-cli/project.yml +13 -0
- data/vendor/dry-cli/spec/integration/commands_spec.rb +14 -0
- data/vendor/dry-cli/spec/integration/inherited_commands_spec.rb +24 -0
- data/vendor/dry-cli/spec/integration/inline_spec.rb +43 -0
- data/vendor/dry-cli/spec/integration/processes_errors_spec.rb +29 -0
- data/vendor/dry-cli/spec/integration/rendering_spec.rb +31 -0
- data/vendor/dry-cli/spec/integration/single_command_spec.rb +81 -0
- data/vendor/dry-cli/spec/integration/subcommands_spec.rb +60 -0
- data/vendor/dry-cli/spec/integration/third_party_gems_spec.rb +18 -0
- data/vendor/dry-cli/spec/spec_helper.rb +15 -0
- data/vendor/dry-cli/spec/support/coverage.rb +15 -0
- data/vendor/dry-cli/spec/support/files.rb +13 -0
- data/vendor/dry-cli/spec/support/fixtures/based +65 -0
- data/vendor/dry-cli/spec/support/fixtures/baz +9 -0
- data/vendor/dry-cli/spec/support/fixtures/baz_command.rb +19 -0
- data/vendor/dry-cli/spec/support/fixtures/foo +588 -0
- data/vendor/dry-cli/spec/support/fixtures/infinites +31 -0
- data/vendor/dry-cli/spec/support/fixtures/inline +20 -0
- data/vendor/dry-cli/spec/support/fixtures/registry.rb +15 -0
- data/vendor/dry-cli/spec/support/fixtures/shared_commands.rb +596 -0
- data/vendor/dry-cli/spec/support/fixtures/with_block.rb +86 -0
- data/vendor/dry-cli/spec/support/fixtures/with_registry.rb +90 -0
- data/vendor/dry-cli/spec/support/fixtures/with_zero_arity_block.rb +87 -0
- data/vendor/dry-cli/spec/support/helpers.rb +37 -0
- data/vendor/dry-cli/spec/support/path.rb +24 -0
- data/vendor/dry-cli/spec/support/rspec.rb +26 -0
- data/vendor/dry-cli/spec/support/rspec_options.rb +16 -0
- data/vendor/dry-cli/spec/support/shared_examples/commands.rb +300 -0
- data/vendor/dry-cli/spec/support/shared_examples/inherited_commands.rb +197 -0
- data/vendor/dry-cli/spec/support/shared_examples/rendering.rb +181 -0
- data/vendor/dry-cli/spec/support/shared_examples/subcommands.rb +226 -0
- data/vendor/dry-cli/spec/support/shared_examples/third_party_gems.rb +49 -0
- data/vendor/dry-cli/spec/support/warnings.rb +10 -0
- data/vendor/dry-cli/spec/unit/dry/cli/cli_spec.rb +123 -0
- data/vendor/dry-cli/spec/unit/dry/cli/inflector_spec.rb +26 -0
- data/vendor/dry-cli/spec/unit/dry/cli/registry_spec.rb +78 -0
- data/vendor/dry-cli/spec/unit/dry/cli/version_spec.rb +7 -0
- data/vendor/strings-ansi/CHANGELOG.md +24 -0
- data/vendor/strings-ansi/CODE_OF_CONDUCT.md +74 -0
- data/vendor/strings-ansi/Gemfile +11 -0
- data/{LICENSE.txt → vendor/strings-ansi/LICENSE.txt} +1 -1
- data/vendor/strings-ansi/README.md +155 -0
- data/vendor/strings-ansi/Rakefile +8 -0
- data/vendor/strings-ansi/appveyor.yml +32 -0
- data/vendor/strings-ansi/bin/console +14 -0
- data/vendor/strings-ansi/bin/setup +8 -0
- data/vendor/strings-ansi/lib/strings-ansi.rb +1 -0
- data/vendor/strings-ansi/lib/strings/ansi.rb +84 -0
- data/vendor/strings-ansi/lib/strings/ansi/extensions.rb +23 -0
- data/vendor/strings-ansi/lib/strings/ansi/version.rb +7 -0
- data/vendor/strings-ansi/spec/fixtures/ansi_codes.yaml +194 -0
- data/vendor/strings-ansi/spec/spec_helper.rb +51 -0
- data/vendor/strings-ansi/spec/unit/ansi_spec.rb +15 -0
- data/vendor/strings-ansi/spec/unit/extensions_spec.rb +19 -0
- data/vendor/strings-ansi/spec/unit/only_ansi_spec.rb +36 -0
- data/vendor/strings-ansi/spec/unit/sanitize_spec.rb +53 -0
- data/vendor/strings-ansi/strings-ansi.gemspec +34 -0
- data/vendor/strings-ansi/tasks/console.rake +11 -0
- data/vendor/strings-ansi/tasks/coverage.rake +11 -0
- data/vendor/strings-ansi/tasks/spec.rake +29 -0
- metadata +274 -188
- data/.github/workflows/main.yml +0 -26
- data/.gitignore +0 -43
- data/.rspec +0 -2
- data/.rubocop.yml +0 -87
- data/.travis.yml +0 -35
- data/Gemfile +0 -2
- data/Gemfile.base +0 -14
- data/Gemfile.base.lock +0 -172
- data/Gemfile.lock +0 -188
- data/Guardfile +0 -16
- data/Makefile +0 -12
- data/README.md +0 -85
- data/Rakefile +0 -31
- data/bin/bundle +0 -114
- data/bin/console +0 -29
- data/bin/guard +0 -29
- data/bin/rake +0 -29
- data/bin/rfix +0 -29
- data/bin/rspec +0 -29
- data/bin/setup +0 -29
- data/ci/Gemfile.rubocop-0.80 +0 -2
- data/ci/Gemfile.rubocop-0.80.lock +0 -170
- data/ci/Gemfile.rubocop-0.81 +0 -2
- data/ci/Gemfile.rubocop-0.81.lock +0 -170
- data/ci/Gemfile.rubocop-0.82 +0 -2
- data/ci/Gemfile.rubocop-0.82.lock +0 -170
- data/ci/Gemfile.rubocop-0.83 +0 -2
- data/ci/Gemfile.rubocop-0.83.lock +0 -168
- data/ci/Gemfile.rubocop-0.84 +0 -2
- data/ci/Gemfile.rubocop-0.84.lock +0 -171
- data/ci/Gemfile.rubocop-0.85 +0 -2
- data/ci/Gemfile.rubocop-0.85.1 +0 -2
- data/ci/Gemfile.rubocop-0.85.1.lock +0 -173
- data/ci/Gemfile.rubocop-0.85.lock +0 -173
- data/lib/rfix/box.rb +0 -112
- data/lib/rfix/branches/base.rb +0 -15
- data/lib/rfix/branches/head.rb +0 -13
- data/lib/rfix/branches/main.rb +0 -28
- data/lib/rfix/branches/name.rb +0 -23
- data/lib/rfix/branches/reference.rb +0 -21
- data/lib/rfix/branches/upstream.rb +0 -13
- data/lib/rfix/cmd.rb +0 -39
- data/lib/rfix/commands/branch.rb +0 -15
- data/lib/rfix/commands/extensions/options.rb +0 -8
- data/lib/rfix/commands/help.rb +0 -7
- data/lib/rfix/commands/helper/args.rb +0 -141
- data/lib/rfix/commands/helper/help.rb +0 -6
- data/lib/rfix/commands/helper/loader.rb +0 -6
- data/lib/rfix/commands/helper/option.rb +0 -0
- data/lib/rfix/commands/helper/params.rb +0 -0
- data/lib/rfix/commands/helper/rubocop.rb +0 -17
- data/lib/rfix/commands/info.rb +0 -30
- data/lib/rfix/commands/lint.rb +0 -22
- data/lib/rfix/commands/local.rb +0 -12
- data/lib/rfix/commands/origin.rb +0 -19
- data/lib/rfix/commands/setup.rb +0 -29
- data/lib/rfix/commands/welcome.rb +0 -24
- data/lib/rfix/deleted.rb +0 -13
- data/lib/rfix/extensions/extensions.rb +0 -18
- data/lib/rfix/extensions/offense.rb +0 -78
- data/lib/rfix/extensions/string.rb +0 -8
- data/lib/rfix/file_cache.rb +0 -59
- data/lib/rfix/git_helper.rb +0 -59
- data/lib/rfix/indentation.rb +0 -39
- data/lib/rfix/loader/bundler.rb +0 -37
- data/lib/rfix/loader/env.rb +0 -33
- data/lib/rfix/loader/spec.rb +0 -41
- data/lib/rfix/no_file.rb +0 -13
- data/lib/rfix/rfix.rb +0 -34
- data/lib/rfix/tracked.rb +0 -72
- data/lib/rfix/tracked_file.rb +0 -16
- data/lib/rfix/untracked.rb +0 -13
- data/resources/ps.png +0 -0
- data/tasks/bump.rake +0 -11
- data/tasks/bundle.rake +0 -17
- data/tasks/complex.rake +0 -54
- data/tasks/execute.rake +0 -38
- data/tasks/libgit2.rake +0 -33
- data/tasks/simple.rake +0 -62
- data/tasks/travis.rake +0 -74
- data/tasks/vendor.rake +0 -34
@@ -0,0 +1,387 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
require "dry/cli/option"
|
5
|
+
|
6
|
+
module Dry
|
7
|
+
class CLI
|
8
|
+
# Base class for commands
|
9
|
+
#
|
10
|
+
# @since 0.1.0
|
11
|
+
class Command
|
12
|
+
# @since 0.1.0
|
13
|
+
# @api private
|
14
|
+
def self.inherited(base)
|
15
|
+
super
|
16
|
+
base.class_eval do
|
17
|
+
@_mutex = Mutex.new
|
18
|
+
@description = nil
|
19
|
+
@examples = []
|
20
|
+
@subcommands = []
|
21
|
+
@arguments = base.superclass_arguments || []
|
22
|
+
@options = base.superclass_options || []
|
23
|
+
end
|
24
|
+
base.extend ClassMethods
|
25
|
+
end
|
26
|
+
|
27
|
+
# @since 0.1.0
|
28
|
+
# @api private
|
29
|
+
module ClassMethods
|
30
|
+
# @since 0.1.0
|
31
|
+
# @api private
|
32
|
+
attr_reader :description
|
33
|
+
|
34
|
+
# @since 0.1.0
|
35
|
+
# @api private
|
36
|
+
attr_reader :examples
|
37
|
+
|
38
|
+
# @since 0.1.0
|
39
|
+
# @api private
|
40
|
+
attr_reader :arguments
|
41
|
+
|
42
|
+
# @since 0.1.0
|
43
|
+
# @api private
|
44
|
+
attr_reader :options
|
45
|
+
|
46
|
+
# @since x.x.x
|
47
|
+
# @api private
|
48
|
+
attr_accessor :subcommands
|
49
|
+
|
50
|
+
# @since x.x.x
|
51
|
+
# @api private
|
52
|
+
end
|
53
|
+
|
54
|
+
# Set the description of the command
|
55
|
+
#
|
56
|
+
# @param description [String] the description
|
57
|
+
#
|
58
|
+
# @since 0.1.0
|
59
|
+
#
|
60
|
+
# @example
|
61
|
+
# require "dry/cli"
|
62
|
+
#
|
63
|
+
# class Echo < Dry::CLI::Command
|
64
|
+
# desc "Prints given input"
|
65
|
+
#
|
66
|
+
# def call(*)
|
67
|
+
# # ...
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
def self.desc(description)
|
71
|
+
@description = description
|
72
|
+
end
|
73
|
+
|
74
|
+
# Describe the usage of the command
|
75
|
+
#
|
76
|
+
# @param examples [Array<String>] one or more examples
|
77
|
+
#
|
78
|
+
# @since 0.1.0
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# require "dry/cli"
|
82
|
+
#
|
83
|
+
# class Server < Dry::CLI::Command
|
84
|
+
# example [
|
85
|
+
# " # Basic usage (it uses the bundled server engine)",
|
86
|
+
# "--server=webrick # Force `webrick` server engine",
|
87
|
+
# "--host=0.0.0.0 # Bind to a host",
|
88
|
+
# "--port=2306 # Bind to a port",
|
89
|
+
# "--no-code-reloading # Disable code reloading"
|
90
|
+
# ]
|
91
|
+
#
|
92
|
+
# def call(*)
|
93
|
+
# # ...
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# # $ foo server --help
|
98
|
+
# # # ...
|
99
|
+
# #
|
100
|
+
# # Examples:
|
101
|
+
# # foo server # Basic usage (it uses the bundled server engine)
|
102
|
+
# # foo server --server=webrick # Force `webrick` server engine
|
103
|
+
# # foo server --host=0.0.0.0 # Bind to a host
|
104
|
+
# # foo server --port=2306 # Bind to a port
|
105
|
+
# # foo server --no-code-reloading # Disable code reloading
|
106
|
+
def self.example(*examples)
|
107
|
+
@examples += examples.flatten(1)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Specify an argument
|
111
|
+
#
|
112
|
+
# @param name [Symbol] the argument name
|
113
|
+
# @param options [Hash] a set of options
|
114
|
+
#
|
115
|
+
# @since 0.1.0
|
116
|
+
#
|
117
|
+
# @example Optional argument
|
118
|
+
# require "dry/cli"
|
119
|
+
#
|
120
|
+
# class Hello < Dry::CLI::Command
|
121
|
+
# argument :name
|
122
|
+
#
|
123
|
+
# def call(name: nil, **)
|
124
|
+
# if name.nil?
|
125
|
+
# puts "Hello, stranger"
|
126
|
+
# else
|
127
|
+
# puts "Hello, #{name}"
|
128
|
+
# end
|
129
|
+
# end
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# # $ foo hello
|
133
|
+
# # Hello, stranger
|
134
|
+
#
|
135
|
+
# # $ foo hello Luca
|
136
|
+
# # Hello, Luca
|
137
|
+
#
|
138
|
+
# @example Required argument
|
139
|
+
# require "dry/cli"
|
140
|
+
#
|
141
|
+
# class Hello < Dry::CLI::Command
|
142
|
+
# argument :name, required: true
|
143
|
+
#
|
144
|
+
# def call(name:, **)
|
145
|
+
# puts "Hello, #{name}"
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
#
|
149
|
+
# # $ foo hello Luca
|
150
|
+
# # Hello, Luca
|
151
|
+
#
|
152
|
+
# # $ foo hello
|
153
|
+
# # ERROR: "foo hello" was called with no arguments
|
154
|
+
# # Usage: "foo hello NAME"
|
155
|
+
#
|
156
|
+
# @example Multiple arguments
|
157
|
+
# require "dry/cli"
|
158
|
+
#
|
159
|
+
# module Generate
|
160
|
+
# class Action < Dry::CLI::Command
|
161
|
+
# argument :app, required: true
|
162
|
+
# argument :action, required: true
|
163
|
+
#
|
164
|
+
# def call(app:, action:, **)
|
165
|
+
# puts "Generating action: #{action} for app: #{app}"
|
166
|
+
# end
|
167
|
+
# end
|
168
|
+
# end
|
169
|
+
#
|
170
|
+
# # $ foo generate action web home
|
171
|
+
# # Generating action: home for app: web
|
172
|
+
#
|
173
|
+
# # $ foo generate action
|
174
|
+
# # ERROR: "foo generate action" was called with no arguments
|
175
|
+
# # Usage: "foo generate action APP ACTION"
|
176
|
+
#
|
177
|
+
# @example Description
|
178
|
+
# require "dry/cli"
|
179
|
+
#
|
180
|
+
# class Hello < Dry::CLI::Command
|
181
|
+
# argument :name, desc: "The name of the person to greet"
|
182
|
+
#
|
183
|
+
# def call(name: nil, **)
|
184
|
+
# # ...
|
185
|
+
# end
|
186
|
+
# end
|
187
|
+
#
|
188
|
+
# # $ foo hello --help
|
189
|
+
# # Command:
|
190
|
+
# # foo hello
|
191
|
+
# #
|
192
|
+
# # Usage:
|
193
|
+
# # foo hello [NAME]
|
194
|
+
# #
|
195
|
+
# # Arguments:
|
196
|
+
# # NAME # The name of the person to greet
|
197
|
+
# #
|
198
|
+
# # Options:
|
199
|
+
# # --help, -h # Print this help
|
200
|
+
def self.argument(name, options = {})
|
201
|
+
@arguments << Argument.new(name, options)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Command line option (aka optional argument)
|
205
|
+
#
|
206
|
+
# @param name [Symbol] the param name
|
207
|
+
# @param options [Hash] a set of options
|
208
|
+
#
|
209
|
+
# @since 0.1.0
|
210
|
+
#
|
211
|
+
# @example Basic usage
|
212
|
+
# require "dry/cli"
|
213
|
+
#
|
214
|
+
# class Console < Dry::CLI::Command
|
215
|
+
# param :engine
|
216
|
+
#
|
217
|
+
# def call(engine: nil, **)
|
218
|
+
# puts "starting console (engine: #{engine || :irb})"
|
219
|
+
# end
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# # $ foo console
|
223
|
+
# # starting console (engine: irb)
|
224
|
+
#
|
225
|
+
# # $ foo console --engine=pry
|
226
|
+
# # starting console (engine: pry)
|
227
|
+
#
|
228
|
+
# @example List values
|
229
|
+
# require "dry/cli"
|
230
|
+
#
|
231
|
+
# class Console < Dry::CLI::Command
|
232
|
+
# param :engine, values: %w(irb pry ripl)
|
233
|
+
#
|
234
|
+
# def call(engine: nil, **)
|
235
|
+
# puts "starting console (engine: #{engine || :irb})"
|
236
|
+
# end
|
237
|
+
# end
|
238
|
+
#
|
239
|
+
# # $ foo console
|
240
|
+
# # starting console (engine: irb)
|
241
|
+
#
|
242
|
+
# # $ foo console --engine=pry
|
243
|
+
# # starting console (engine: pry)
|
244
|
+
#
|
245
|
+
# # $ foo console --engine=foo
|
246
|
+
# # ERROR: Invalid param provided
|
247
|
+
#
|
248
|
+
# @example Description
|
249
|
+
# require "dry/cli"
|
250
|
+
#
|
251
|
+
# class Console < Dry::CLI::Command
|
252
|
+
# param :engine, desc: "Force a console engine"
|
253
|
+
#
|
254
|
+
# def call(engine: nil, **)
|
255
|
+
# # ...
|
256
|
+
# end
|
257
|
+
# end
|
258
|
+
#
|
259
|
+
# # $ foo console --help
|
260
|
+
# # # ...
|
261
|
+
# #
|
262
|
+
# # Options:
|
263
|
+
# # --engine=VALUE # Force a console engine: (irb/pry/ripl)
|
264
|
+
# # --help, -h # Print this help
|
265
|
+
#
|
266
|
+
# @example Boolean
|
267
|
+
# require "dry/cli"
|
268
|
+
#
|
269
|
+
# class Server < Dry::CLI::Command
|
270
|
+
# param :code_reloading, type: :boolean, default: true
|
271
|
+
#
|
272
|
+
# def call(code_reloading:, **)
|
273
|
+
# puts "staring server (code reloading: #{code_reloading})"
|
274
|
+
# end
|
275
|
+
# end
|
276
|
+
#
|
277
|
+
# # $ foo server
|
278
|
+
# # starting server (code reloading: true)
|
279
|
+
#
|
280
|
+
# # $ foo server --no-code-reloading
|
281
|
+
# # starting server (code reloading: false)
|
282
|
+
#
|
283
|
+
# # $ foo server --help
|
284
|
+
# # # ...
|
285
|
+
# #
|
286
|
+
# # Options:
|
287
|
+
# # --[no]-code-reloading
|
288
|
+
#
|
289
|
+
# @example Aliases
|
290
|
+
# require "dry/cli"
|
291
|
+
#
|
292
|
+
# class Server < Dry::CLI::Command
|
293
|
+
# param :port, aliases: ["-p"]
|
294
|
+
#
|
295
|
+
# def call(options)
|
296
|
+
# puts "staring server (port: #{options.fetch(:port, 2300)})"
|
297
|
+
# end
|
298
|
+
# end
|
299
|
+
#
|
300
|
+
# # $ foo server
|
301
|
+
# # starting server (port: 2300)
|
302
|
+
#
|
303
|
+
# # $ foo server --port=2306
|
304
|
+
# # starting server (port: 2306)
|
305
|
+
#
|
306
|
+
# # $ foo server -p 2306
|
307
|
+
# # starting server (port: 2306)
|
308
|
+
#
|
309
|
+
# # $ foo server --help
|
310
|
+
# # # ...
|
311
|
+
# #
|
312
|
+
# # Options:
|
313
|
+
# # --port=VALUE, -p VALUE
|
314
|
+
def self.option(name, options = {})
|
315
|
+
@options << Option.new(name, options)
|
316
|
+
end
|
317
|
+
|
318
|
+
# @since 0.1.0
|
319
|
+
# @api private
|
320
|
+
def self.params
|
321
|
+
@_mutex.synchronize do
|
322
|
+
(@arguments + @options).uniq
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# @since 0.1.0
|
327
|
+
# @api private
|
328
|
+
def self.default_params
|
329
|
+
params.each_with_object({}) do |param, result|
|
330
|
+
result[param.name] = param.default unless param.default.nil?
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
# @since 0.1.0
|
335
|
+
# @api private
|
336
|
+
def self.required_arguments
|
337
|
+
arguments.select(&:required?)
|
338
|
+
end
|
339
|
+
|
340
|
+
# @since 0.1.0
|
341
|
+
# @api private
|
342
|
+
def self.optional_arguments
|
343
|
+
arguments.reject(&:required?)
|
344
|
+
end
|
345
|
+
|
346
|
+
# @since x.x.x
|
347
|
+
# @api private
|
348
|
+
def self.subcommands
|
349
|
+
subcommands
|
350
|
+
end
|
351
|
+
|
352
|
+
# @since 0.7.0
|
353
|
+
# @api private
|
354
|
+
def self.superclass_variable_dup(var)
|
355
|
+
if superclass.instance_variable_defined?(var)
|
356
|
+
superclass.instance_variable_get(var).dup
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
# @since 0.7.0
|
361
|
+
# @api private
|
362
|
+
def self.superclass_arguments
|
363
|
+
superclass_variable_dup(:@arguments)
|
364
|
+
end
|
365
|
+
|
366
|
+
# @since 0.7.0
|
367
|
+
# @api private
|
368
|
+
def self.superclass_options
|
369
|
+
superclass_variable_dup(:@options)
|
370
|
+
end
|
371
|
+
|
372
|
+
extend Forwardable
|
373
|
+
|
374
|
+
delegate %i[
|
375
|
+
description
|
376
|
+
examples
|
377
|
+
arguments
|
378
|
+
options
|
379
|
+
params
|
380
|
+
default_params
|
381
|
+
required_arguments
|
382
|
+
optional_arguments
|
383
|
+
subcommands
|
384
|
+
] => "self.class"
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
@@ -0,0 +1,253 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module Dry
|
6
|
+
class CLI
|
7
|
+
# Command registry
|
8
|
+
#
|
9
|
+
# @since 0.1.0
|
10
|
+
# @api private
|
11
|
+
class CommandRegistry
|
12
|
+
# @since 0.1.0
|
13
|
+
# @api private
|
14
|
+
def initialize
|
15
|
+
@_mutex = Mutex.new
|
16
|
+
@root = Node.new
|
17
|
+
end
|
18
|
+
|
19
|
+
# @since 0.1.0
|
20
|
+
# @api private
|
21
|
+
def set(name, command, aliases)
|
22
|
+
@_mutex.synchronize do
|
23
|
+
node = @root
|
24
|
+
name.split(/[[:space:]]/).each do |token|
|
25
|
+
node = node.put(node, token)
|
26
|
+
end
|
27
|
+
|
28
|
+
node.aliases!(aliases)
|
29
|
+
if command
|
30
|
+
node.leaf!(command)
|
31
|
+
node.subcommands!(command)
|
32
|
+
end
|
33
|
+
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @since 0.1.0
|
39
|
+
# @api private
|
40
|
+
#
|
41
|
+
def get(arguments)
|
42
|
+
@_mutex.synchronize do
|
43
|
+
node = @root
|
44
|
+
args = []
|
45
|
+
names = []
|
46
|
+
valid_leaf = nil
|
47
|
+
result = LookupResult.new(node, args, names, node.leaf?)
|
48
|
+
|
49
|
+
arguments.each_with_index do |token, i|
|
50
|
+
tmp = node.lookup(token)
|
51
|
+
|
52
|
+
if tmp.nil? && valid_leaf
|
53
|
+
result = valid_leaf
|
54
|
+
break
|
55
|
+
elsif tmp.nil?
|
56
|
+
result = LookupResult.new(node, args, names, false)
|
57
|
+
break
|
58
|
+
elsif tmp.leaf?
|
59
|
+
args = arguments[i + 1..-1]
|
60
|
+
names = arguments[0..i]
|
61
|
+
node = tmp
|
62
|
+
result = LookupResult.new(node, args, names, true)
|
63
|
+
valid_leaf = result
|
64
|
+
break unless tmp.children?
|
65
|
+
else
|
66
|
+
names = arguments[0..i]
|
67
|
+
node = tmp
|
68
|
+
result = LookupResult.new(node, args, names, node.leaf?)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
result
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Node of the registry
|
77
|
+
#
|
78
|
+
# @since 0.1.0
|
79
|
+
# @api private
|
80
|
+
class Node
|
81
|
+
# @since 0.1.0
|
82
|
+
# @api private
|
83
|
+
attr_reader :parent
|
84
|
+
|
85
|
+
# @since 0.1.0
|
86
|
+
# @api private
|
87
|
+
attr_reader :children
|
88
|
+
|
89
|
+
# @since 0.1.0
|
90
|
+
# @api private
|
91
|
+
attr_reader :aliases
|
92
|
+
|
93
|
+
# @since 0.1.0
|
94
|
+
# @api private
|
95
|
+
attr_reader :command
|
96
|
+
|
97
|
+
# @since 0.1.0
|
98
|
+
# @api private
|
99
|
+
attr_reader :before_callbacks
|
100
|
+
|
101
|
+
# @since 0.1.0
|
102
|
+
# @api private
|
103
|
+
attr_reader :after_callbacks
|
104
|
+
|
105
|
+
# @since 0.1.0
|
106
|
+
# @api private
|
107
|
+
def initialize(parent = nil)
|
108
|
+
@parent = parent
|
109
|
+
@children = {}
|
110
|
+
@aliases = {}
|
111
|
+
@command = nil
|
112
|
+
|
113
|
+
@before_callbacks = Chain.new
|
114
|
+
@after_callbacks = Chain.new
|
115
|
+
end
|
116
|
+
|
117
|
+
# @since 0.1.0
|
118
|
+
# @api private
|
119
|
+
def put(parent, key)
|
120
|
+
children[key] ||= self.class.new(parent)
|
121
|
+
end
|
122
|
+
|
123
|
+
# @since 0.1.0
|
124
|
+
# @api private
|
125
|
+
def lookup(token)
|
126
|
+
children[token] || aliases[token]
|
127
|
+
end
|
128
|
+
|
129
|
+
# @since 0.1.0
|
130
|
+
# @api private
|
131
|
+
def leaf!(command)
|
132
|
+
@command = command
|
133
|
+
end
|
134
|
+
|
135
|
+
# @since x.x.x
|
136
|
+
# @api private
|
137
|
+
def subcommands!(command)
|
138
|
+
command_class = command.is_a?(Class) ? command : command.class
|
139
|
+
command_class.subcommands = children
|
140
|
+
end
|
141
|
+
|
142
|
+
# @since 0.1.0
|
143
|
+
# @api private
|
144
|
+
def alias!(key, child)
|
145
|
+
@aliases[key] = child
|
146
|
+
end
|
147
|
+
|
148
|
+
# @since 0.1.0
|
149
|
+
# @api private
|
150
|
+
def aliases!(aliases)
|
151
|
+
aliases.each do |a|
|
152
|
+
parent.alias!(a, self)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# @since 0.1.0
|
157
|
+
# @api private
|
158
|
+
def leaf?
|
159
|
+
!command.nil?
|
160
|
+
end
|
161
|
+
|
162
|
+
# @since x.x.x
|
163
|
+
# @api private
|
164
|
+
def children?
|
165
|
+
children.any?
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Result of a registry lookup
|
170
|
+
#
|
171
|
+
# @since 0.1.0
|
172
|
+
# @api private
|
173
|
+
class LookupResult
|
174
|
+
# @since 0.1.0
|
175
|
+
# @api private
|
176
|
+
attr_reader :names
|
177
|
+
|
178
|
+
# @since 0.1.0
|
179
|
+
# @api private
|
180
|
+
attr_reader :arguments
|
181
|
+
|
182
|
+
# @since 0.1.0
|
183
|
+
# @api private
|
184
|
+
def initialize(node, arguments, names, found)
|
185
|
+
@node = node
|
186
|
+
@arguments = arguments
|
187
|
+
@names = names
|
188
|
+
@found = found
|
189
|
+
end
|
190
|
+
|
191
|
+
# @since 0.1.0
|
192
|
+
# @api private
|
193
|
+
def found?
|
194
|
+
@found
|
195
|
+
end
|
196
|
+
|
197
|
+
# @since 0.1.0
|
198
|
+
# @api private
|
199
|
+
def children
|
200
|
+
@node.children
|
201
|
+
end
|
202
|
+
|
203
|
+
# @since 0.1.0
|
204
|
+
# @api private
|
205
|
+
def command
|
206
|
+
@node.command
|
207
|
+
end
|
208
|
+
|
209
|
+
# @since 0.2.0
|
210
|
+
# @api private
|
211
|
+
def before_callbacks
|
212
|
+
@node.before_callbacks
|
213
|
+
end
|
214
|
+
|
215
|
+
# @since 0.2.0
|
216
|
+
# @api private
|
217
|
+
def after_callbacks
|
218
|
+
@node.after_callbacks
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Callbacks chain
|
223
|
+
#
|
224
|
+
# @since 0.4.0
|
225
|
+
# @api private
|
226
|
+
class Chain
|
227
|
+
# @since 0.4.0
|
228
|
+
# @api private
|
229
|
+
attr_reader :chain
|
230
|
+
|
231
|
+
# @since 0.4.0
|
232
|
+
# @api private
|
233
|
+
def initialize
|
234
|
+
@chain = Set.new
|
235
|
+
end
|
236
|
+
|
237
|
+
# @since 0.4.0
|
238
|
+
# @api private
|
239
|
+
def append(&callback)
|
240
|
+
chain.add(callback)
|
241
|
+
end
|
242
|
+
|
243
|
+
# @since 0.4.0
|
244
|
+
# @api private
|
245
|
+
def run(context, *args)
|
246
|
+
chain.each do |callback|
|
247
|
+
context.instance_exec(*args, &callback)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|