dry-cli 1.3.0 → 1.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ab3b2530b7f867fee473bfb808d816bcfefd9732f49e158d32d5d914873516c
4
- data.tar.gz: 897275b361168f15eb760ced1d5a6db6ec1229361a9b323e06a3204bfe89cd8d
3
+ metadata.gz: 87a109a8a8d9f3045e2cffa05a43fe8e31dd75fdd148cc6e7ea2610e2185e351
4
+ data.tar.gz: 7e5cf4b8a263cfe22c7be02cfa2faeca8ccd946933fb7c4e6d3c446341946324
5
5
  SHA512:
6
- metadata.gz: c12f142b52bb3114425d7be016416603a951cc88b5252593a77f3cd48bbe73d0b7e453dca3519fd5025af9832b875f563208914cb5657d6d0b5eef19782d6412
7
- data.tar.gz: 2749e9f49dcf611171bdcdb2f9dbc51106cf78d7658155b2229a6e391610c18f288235ebe2abac654b6dfa8a0461e54e325cd2d315aa9303b2a06e1ddc1119fa
6
+ metadata.gz: b6eb3230d06cde1fe957bcff4c964f755735dff96c30ac1d8c4d39c2532d92b43e749363d9475eb09632da5ef0dd5608b7d354f6011c10189f9bd791d519f848
7
+ data.tar.gz: c5a9c59751712f8306daafd35e3bb5759a8ac0457b088c6efd7ff45f607c2467b3faeaf744af8e3cb96eed44216427e27fcd265195329b878b8e41852ceb494c
data/CHANGELOG.md CHANGED
@@ -1,7 +1,53 @@
1
- <!--- DO NOT EDIT THIS FILE - IT'S AUTOMATICALLY GENERATED VIA DEVTOOLS --->
1
+ # Changelog
2
2
 
3
- ## 1.3.0 2025-07-29
3
+ All notable changes to this project will be documented in this file.
4
4
 
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Break Versioning](https://www.taoensso.com/break-versioning).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ ### Changed
13
+
14
+ ### Deprecated
15
+
16
+ ### Removed
17
+
18
+ ### Fixed
19
+
20
+ ### Security
21
+
22
+ [Unreleased]: https://github.com/dry-rb/dry-cli/compare/v1.4.1...main
23
+
24
+ ## [1.4.1] - 2026-01-21
25
+
26
+ ### Fixed
27
+
28
+ - Remove spurious leading blank line when printing usage output. (@aaronmallen in #154)
29
+
30
+ [1.4.1]: https://github.com/dry-rb/dry-cli/compare/v1.4.0...v1.4.1
31
+
32
+ ## [1.4.0] - 2026-01-09
33
+
34
+ ### Added
35
+
36
+ - Provide the CLI’s `out` and `err` streams to command instances (unless `@out` and `@err` ivars already exist in the command). (@aaronmallen in #150)
37
+
38
+ ### Changed
39
+
40
+ - Require Ruby 3.2 or later. (@timriley)
41
+
42
+ ### Fixed
43
+
44
+ - Pass a commands keyword arguments to any related callbacks. (@gustavothecoder in #136)
45
+ - Avoid duplicated option names in `--help` output when a subclass re-defines an option. (@gustavothecoder in #143)
46
+ - Properly raise an error when an invalid value is passed to an option (previously this was working for arguments only, not options). (@gustavothecoder in #142)
47
+
48
+ [1.4.0]: https://github.com/dry-rb/dry-cli/compare/v1.3.0...v1.4.0
49
+
50
+ ## [1.3.0] - 2025-07-29
5
51
 
6
52
  ### Added
7
53
 
@@ -31,40 +77,34 @@
31
77
 
32
78
  - Set minimum Ruby version to 3.1. (@timriley)
33
79
 
34
- [Compare v1.2.0...v1.3.0](https://github.com/dry-rb/dry-cli/compare/v1.2.0...v1.3.0)
35
-
36
- ## 1.2.0 2024-10-15
80
+ [1.3.0]: https://github.com/dry-rb/dry-cli/compare/v1.2.0...v1.3.0
37
81
 
82
+ ## [1.2.0] - 2024-10-15
38
83
 
39
84
  ### Added
40
85
 
41
86
  - Added `:hidden` option to register commands that should not be shown in the help output. (@benoittgt in #137)
42
87
  - Provide suggestions when there is a typo in a command name. (@benoittgt in #138)
43
88
 
89
+ [1.2.0]: https://github.com/dry-rb/dry-cli/compare/v1.1.0...v1.2.0
44
90
 
45
- [Compare v1.1.0...v1.2.0](https://github.com/dry-rb/dry-cli/compare/v1.1.0...v1.2.0)
46
-
47
- ## 1.1.0 2024-07-14
48
-
91
+ ## [1.1.0] - 2024-07-14
49
92
 
50
93
  ### Added
51
94
 
52
95
  - Added `:flag` option type. This acts like a `:boolean` that can only be set to true, so has no `--no-` prefix to disable it. (@Billiam in #117)
53
96
 
97
+ [1.1.0]: https://github.com/dry-rb/dry-cli/compare/v1.0.0...v1.1.0
54
98
 
55
- [Compare v1.0.0...v1.1.0](https://github.com/dry-rb/dry-cli/compare/v1.0.0...v1.1.0)
56
-
57
- ## 1.0.0 2022-11-05
58
-
99
+ ## [1.0.0] - 2022-11-05
59
100
 
60
101
  ### Changed
61
102
 
62
103
  - Version bumped to 1.0.0 (@solnic)
63
104
 
64
- [Compare v0.7.0...v1.0.0](https://github.com/dry-rb/dry-cli/compare/v0.7.0...v1.0.0)
65
-
66
- ## 0.7.0 2020-05-08
105
+ [1.0.0]: https://github.com/dry-rb/dry-cli/compare/v0.7.0...v1.0.0
67
106
 
107
+ ## [0.7.0] - 2020-05-08
68
108
 
69
109
  ### Added
70
110
 
@@ -88,10 +128,9 @@
88
128
  - Remove concurrent-ruby as runtime dependency (@jodosha)
89
129
  - [Internal] Banner and Parses refactoring (@IvanShamatov)
90
130
 
91
- [Compare v0.6.0...v0.7.0](https://github.com/dry-rb/dry-cli/compare/v0.6.0...v0.7.0)
92
-
93
- ## 0.6.0 2020-03-06
131
+ [0.7.0]: https://github.com/dry-rb/dry-cli/compare/v0.6.0...v0.7.0
94
132
 
133
+ ## [0.6.0] - 2020-03-06
95
134
 
96
135
  ### Added
97
136
 
@@ -105,11 +144,9 @@
105
144
  - [John Ledbetter & Luca Guidi] Fix ruby 2.7 warnings (@jodosha)
106
145
  - Fix banner, when option is a type of Array (@IvanShamatov)
107
146
 
147
+ [0.6.0]: https://github.com/dry-rb/dry-cli/compare/v0.5.1...v0.6.0
108
148
 
109
- [Compare v0.5.1...v0.6.0](https://github.com/dry-rb/dry-cli/compare/v0.5.1...v0.6.0)
110
-
111
- ## 0.5.1 2020-01-23
112
-
149
+ ## [0.5.1] - 2020-01-23
113
150
 
114
151
  ### Added
115
152
 
@@ -123,48 +160,38 @@
123
160
 
124
161
  - Added missing 'set' require (@solnic)
125
162
 
163
+ [0.5.1]: https://github.com/dry-rb/dry-cli/compare/v0.5.0...v0.5.1
126
164
 
127
- [Compare v0.5.0...v0.5.1](https://github.com/dry-rb/dry-cli/compare/v0.5.0...v0.5.1)
128
-
129
- ## 0.5.0 2019-12-21
130
-
165
+ ## [0.5.0] - 2019-12-21
131
166
 
132
167
  ### Added
133
168
 
134
169
  - [Internal] removed runtime and development dependency against `hanami-utils` (@jodosha, @IvanShamatov, @solnic)
135
170
 
171
+ [0.5.0]: https://github.com/dry-rb/dry-cli/compare/v0.4.0...v0.5.0
136
172
 
137
- [Compare v0.4.0...v0.5.0](https://github.com/dry-rb/dry-cli/compare/v0.4.0...v0.5.0)
138
-
139
- ## 0.4.0 2019-12-10
140
-
173
+ ## [0.4.0] - 2019-12-10
141
174
 
142
175
  ### Added
143
176
 
144
177
  - `hanami-cli` => `dry-cli` (@jodosha, @IvanShamatov, @solnic)
145
178
 
179
+ [0.4.0]: https://github.com/dry-rb/dry-cli/compare/v0.3.1...v0.4.0
146
180
 
147
- [Compare v0.3.1...v0.4.0](https://github.com/dry-rb/dry-cli/compare/v0.3.1...v0.4.0)
148
-
149
- ## 0.3.1 2019-01-18
150
-
181
+ ## [0.3.1] - 2019-01-18
151
182
 
152
183
  ### Added
153
184
 
154
185
  - Official support for Ruby: MRI 2.6 (@jodosha)
155
186
  - Support `bundler` 2.0+ (@jodosha)
156
187
 
188
+ [0.3.1]: https://github.com/dry-rb/dry-cli/compare/v0.3.0...v0.3.1
157
189
 
158
- [Compare v0.3.0...v0.3.1](https://github.com/dry-rb/dry-cli/compare/v0.3.0...v0.3.1)
159
-
160
- ## 0.3.0 2018-10-24
190
+ ## [0.3.0] - 2018-10-24
161
191
 
192
+ [0.3.0]: https://github.com/dry-rb/dry-cli/compare/v0.3.0.beta1...v0.3.0
162
193
 
163
-
164
- [Compare v0.3.0.beta1...v0.3.0](https://github.com/dry-rb/dry-cli/compare/v0.3.0.beta1...v0.3.0)
165
-
166
- ## 0.3.0.beta1 2018-08-08
167
-
194
+ ## [0.3.0.beta1] - 2018-08-08
168
195
 
169
196
  ### Added
170
197
 
@@ -177,29 +204,21 @@
177
204
 
178
205
  - Print informative message when unknown or wrong option is passed (`"test" was called with arguments "--framework=unknown"`) (@davydovanton)
179
206
 
207
+ [0.3.0.beta1]: https://github.com/dry-rb/dry-cli/compare/v0.2.0...v0.3.0.beta1
180
208
 
181
- [Compare v0.2.0...v0.3.0.beta1](https://github.com/dry-rb/dry-cli/compare/v0.2.0...v0.3.0.beta1)
182
-
183
- ## 0.2.0 2018-04-11
184
-
185
-
186
-
187
- [Compare v0.2.0.rc2...v0.2.0](https://github.com/dry-rb/dry-cli/compare/v0.2.0.rc2...v0.2.0)
188
-
189
- ## 0.2.0.rc2 2018-04-06
209
+ ## [0.2.0] - 2018-04-11
190
210
 
211
+ [0.2.0]: https://github.com/dry-rb/dry-cli/compare/v0.2.0.rc2...v0.2.0
191
212
 
213
+ ## [0.2.0.rc2] - 2018-04-06
192
214
 
193
- [Compare v0.2.0.rc1...v0.2.0.rc2](https://github.com/dry-rb/dry-cli/compare/v0.2.0.rc1...v0.2.0.rc2)
215
+ [0.2.0.rc2]: https://github.com/dry-rb/dry-cli/compare/v0.2.0.rc1...v0.2.0.rc2
194
216
 
195
- ## 0.2.0.rc1 2018-03-30
217
+ ## [0.2.0.rc1] - 2018-03-30
196
218
 
219
+ [0.2.0.rc1]: https://github.com/dry-rb/dry-cli/compare/v0.2.0.beta2...v0.2.0.rc1
197
220
 
198
-
199
- [Compare v0.2.0.beta2...v0.2.0.rc1](https://github.com/dry-rb/dry-cli/compare/v0.2.0.beta2...v0.2.0.rc1)
200
-
201
- ## 0.2.0.beta2 2018-03-23
202
-
221
+ ## [0.2.0.beta2] - 2018-03-23
203
222
 
204
223
  ### Added
205
224
 
@@ -209,21 +228,17 @@
209
228
 
210
229
  - Ensure callbacks' context of execution (aka `self`) to be the command that is being executed (@jodosha, @davydovanton)
211
230
 
231
+ [0.2.0.beta2]: https://github.com/dry-rb/dry-cli/compare/v0.2.0.beta1...v0.2.0.beta2
212
232
 
213
- [Compare v0.2.0.beta1...v0.2.0.beta2](https://github.com/dry-rb/dry-cli/compare/v0.2.0.beta1...v0.2.0.beta2)
214
-
215
- ## 0.2.0.beta1 2018-02-28
216
-
233
+ ## [0.2.0.beta1] - 2018-02-28
217
234
 
218
235
  ### Added
219
236
 
220
237
  - Register `before`/`after` callbacks for commands (@davydovanton)
221
238
 
239
+ [0.2.0.beta1]: https://github.com/dry-rb/dry-cli/compare/v0.1.1...v0.2.0.beta1
222
240
 
223
- [Compare v0.1.1...v0.2.0.beta1](https://github.com/dry-rb/dry-cli/compare/v0.1.1...v0.2.0.beta1)
224
-
225
- ## 0.1.1 2018-02-27
226
-
241
+ ## [0.1.1] - 2018-02-27
227
242
 
228
243
  ### Added
229
244
 
@@ -234,39 +249,29 @@
234
249
  - Ensure default values for arguments to be sent to commands (@AlfonsoUceda)
235
250
  - Ensure to fail when a missing required argument isn't provider, but an option is provided instead (@AlfonsoUceda)
236
251
 
252
+ [0.1.1]: https://github.com/dry-rb/dry-cli/compare/v0.1.0...v0.1.1
237
253
 
238
- [Compare v0.1.0...v0.1.1](https://github.com/dry-rb/dry-cli/compare/v0.1.0...v0.1.1)
239
-
240
- ## 0.1.0 2017-10-25
241
-
254
+ ## [0.1.0] - 2017-10-25
242
255
 
256
+ [0.1.0]: https://github.com/dry-rb/dry-cli/compare/v0.1.0.rc1...v0.1.0
243
257
 
244
- [Compare v0.1.0.rc1...v0.1.0](https://github.com/dry-rb/dry-cli/compare/v0.1.0.rc1...v0.1.0)
258
+ ## [0.1.0.rc1] - 2017-10-16
245
259
 
246
- ## 0.1.0.rc1 2017-10-16
260
+ [0.1.0.rc1]: https://github.com/dry-rb/dry-cli/compare/v0.1.0.beta3...v0.1.0.rc1
247
261
 
262
+ ## [0.1.0.beta3] - 2017-10-04
248
263
 
264
+ [0.1.0.beta3]: https://github.com/dry-rb/dry-cli/compare/v0.1.0.beta2...v0.1.0.beta3
249
265
 
250
- [Compare v0.1.0.beta3...v0.1.0.rc1](https://github.com/dry-rb/dry-cli/compare/v0.1.0.beta3...v0.1.0.rc1)
251
-
252
- ## 0.1.0.beta3 2017-10-04
253
-
254
-
255
-
256
- [Compare v0.1.0.beta2...v0.1.0.beta3](https://github.com/dry-rb/dry-cli/compare/v0.1.0.beta2...v0.1.0.beta3)
257
-
258
- ## 0.1.0.beta2 2017-10-03
259
-
266
+ ## [0.1.0.beta2] - 2017-10-03
260
267
 
261
268
  ### Added
262
269
 
263
270
  - Allow default value for arguments (@AlfonsoUceda)
264
271
 
272
+ [0.1.0.beta2]: https://github.com/dry-rb/dry-cli/compare/v0.1.0.beta1...v0.1.0.beta2
265
273
 
266
- [Compare v0.1.0.beta1...v0.1.0.beta2](https://github.com/dry-rb/dry-cli/compare/v0.1.0.beta1...v0.1.0.beta2)
267
-
268
- ## 0.1.0.beta1 2017-08-11
269
-
274
+ ## [0.1.0.beta1] - 2017-08-11
270
275
 
271
276
  ### Added
272
277
 
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2023 dry-rb team
3
+ Copyright (c) 2015-2026 Hanakai team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,22 +1,17 @@
1
- <!--- this file is synced from dry-rb/template-gem project -->
2
- [gem]: https://rubygems.org/gems/dry-cli
1
+ <!--- This file is synced from hanakai-rb/repo-sync -->
2
+
3
+ [rubygem]: https://rubygems.org/gems/dry-cli
3
4
  [actions]: https://github.com/dry-rb/dry-cli/actions
4
5
 
5
- # dry-cli [![Gem Version](https://badge.fury.io/rb/dry-cli.svg)][gem] [![CI Status](https://github.com/dry-rb/dry-cli/workflows/ci/badge.svg)][actions]
6
+ # dry-cli [![Gem Version](https://badge.fury.io/rb/dry-cli.svg)][rubygem] [![CI Status](https://github.com/dry-rb/dry-cli/workflows/CI/badge.svg)][actions]
6
7
 
7
8
  ## Links
8
9
 
9
- * [User documentation](https://dry-rb.org/gems/dry-cli)
10
- * [API documentation](http://rubydoc.info/gems/dry-cli)
11
- * [Forum](https://discourse.dry-rb.org)
12
-
13
- ## Supported Ruby versions
14
-
15
- This library officially supports the following Ruby versions:
16
-
17
- * MRI `>= 3.1.0`
18
- * jruby `>= 9.4` (not tested on CI)
10
+ - [User documentation](https://dry-rb.org/gems/dry-cli)
11
+ - [API documentation](http://rubydoc.info/gems/dry-cli)
12
+ - [Forum](https://discourse.dry-rb.org)
19
13
 
20
14
  ## License
21
15
 
22
16
  See `LICENSE` file.
17
+
data/dry-cli.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # this file is synced from dry-rb/template-gem project
3
+ # This file is synced from hanakai-rb/repo-sync. To update it, edit repo-sync.yml.
4
4
 
5
5
  lib = File.expand_path("lib", __dir__)
6
6
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
@@ -8,8 +8,8 @@ require "dry/cli/version"
8
8
 
9
9
  Gem::Specification.new do |spec|
10
10
  spec.name = "dry-cli"
11
- spec.authors = ["Luca Guidi"]
12
- spec.email = ["me@lucaguidi.com"]
11
+ spec.authors = ["Hanakai team"]
12
+ spec.email = ["info@hanakai.org"]
13
13
  spec.license = "MIT"
14
14
  spec.version = Dry::CLI::VERSION.dup
15
15
 
@@ -21,17 +21,18 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = []
22
22
  spec.require_paths = ["lib"]
23
23
 
24
+ spec.extra_rdoc_files = ["README.md", "CHANGELOG.md", "LICENSE"]
25
+
24
26
  spec.metadata["allowed_push_host"] = "https://rubygems.org"
25
27
  spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-cli/blob/main/CHANGELOG.md"
26
28
  spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-cli"
27
29
  spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-cli/issues"
30
+ spec.metadata["funding_uri"] = "https://github.com/sponsors/hanami"
28
31
 
29
- spec.required_ruby_version = ">= 3.1"
30
-
31
- # to update dependencies edit project.yml
32
+ spec.required_ruby_version = ">= 3.2"
32
33
 
33
- spec.add_development_dependency "bundler", ">= 1.6", "< 3"
34
- spec.add_development_dependency "rake", "~> 13.0"
35
- spec.add_development_dependency "rspec", "~> 3.7"
36
- spec.add_development_dependency "simplecov", "~> 0.17.1"
34
+ spec.add_development_dependency "bundler"
35
+ spec.add_development_dependency "rake"
36
+ spec.add_development_dependency "rspec"
37
37
  end
38
+
@@ -86,8 +86,8 @@ module Dry
86
86
  required_arguments = command.required_arguments
87
87
  optional_arguments = command.optional_arguments
88
88
 
89
- required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any? # rubocop:disable Layout/LineLength
90
- optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any? # rubocop:disable Layout/LineLength
89
+ required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any?
90
+ optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any?
91
91
  result = [required, optional].compact
92
92
 
93
93
  " #{result.join(" ")}" unless result.empty?
@@ -97,7 +97,7 @@ module Dry
97
97
  # @api private
98
98
  def self.extended_command_arguments(command)
99
99
  command.arguments.map do |argument|
100
- " #{argument.name.to_s.upcase.ljust(32)} # #{"REQUIRED " if argument.required?}#{argument.desc}" # rubocop:disable Layout/LineLength
100
+ " #{argument.name.to_s.upcase.ljust(32)} # #{"REQUIRED " if argument.required?}#{argument.desc}"
101
101
  end.join("\n")
102
102
  end
103
103
 
@@ -195,7 +195,12 @@ module Dry
195
195
  # # Options:
196
196
  # # --help, -h # Print this help
197
197
  def self.argument(name, options = {})
198
- @arguments << Argument.new(name, options)
198
+ new_arg = Argument.new(name, options)
199
+
200
+ duplicate_index = @arguments.find_index { _1.name == new_arg.name }
201
+ @arguments.delete_at(duplicate_index) unless duplicate_index.nil?
202
+
203
+ @arguments << new_arg
199
204
  end
200
205
 
201
206
  # Command line option (aka optional argument)
@@ -309,7 +314,12 @@ module Dry
309
314
  # # Options:
310
315
  # # --port=VALUE, -p VALUE
311
316
  def self.option(name, options = {})
312
- @options << Option.new(name, options)
317
+ new_op = Option.new(name, options)
318
+
319
+ duplicate_index = @options.find_index { _1.name == new_op.name }
320
+ @options.delete_at(duplicate_index) unless duplicate_index.nil?
321
+
322
+ @options << new_op
313
323
  end
314
324
 
315
325
  # @since 0.1.0
@@ -379,6 +389,39 @@ module Dry
379
389
  optional_arguments
380
390
  subcommands
381
391
  ] => "self.class"
392
+
393
+ protected
394
+
395
+ # The error output used to print error messaging
396
+ #
397
+ # @example
398
+ # class MyCommand
399
+ # def call
400
+ # out.puts "Hello World!"
401
+ # exit(0)
402
+ # rescue StandardError => e
403
+ # err.puts "Uh oh: #{e.message}"
404
+ # exit(1)
405
+ # end
406
+ # end
407
+ #
408
+ # @since unreleased
409
+ # @return [IO]
410
+ attr_reader :err
411
+
412
+ # The standard output object used to print messaging
413
+ #
414
+ # @example
415
+ # class MyCommand
416
+ # def call
417
+ # out.puts "Hello World!"
418
+ # exit(0)
419
+ # end
420
+ # end
421
+ #
422
+ # @since unreleased
423
+ # @return [IO]
424
+ attr_reader :out
382
425
  end
383
426
  end
384
427
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
-
5
3
  module Dry
6
4
  class CLI
7
5
  # Command registry
@@ -255,9 +253,9 @@ module Dry
255
253
 
256
254
  # @since 0.4.0
257
255
  # @api private
258
- def run(context, *args)
256
+ def run(context, **args)
259
257
  chain.each do |callback|
260
- context.instance_exec(*args, &callback)
258
+ context.instance_exec(**args, &callback)
261
259
  end
262
260
  end
263
261
  end
@@ -9,6 +9,10 @@ module Dry
9
9
  class Error < StandardError
10
10
  end
11
11
 
12
+ # @since 1.4.0
13
+ class ValueError < Error
14
+ end
15
+
12
16
  # @since 0.2.1
13
17
  class UnknownCommandError < Error
14
18
  # @since 0.2.1
@@ -13,7 +13,7 @@ module Dry
13
13
  # methods below
14
14
  #
15
15
  # DSL consists of 5 methods:
16
- # `desc`, `example`, `argument`, `option` 
16
+ # `desc`, `example`, `argument`, `option`
17
17
  # — are similar to methods from Command class
18
18
  #
19
19
  # `run` accepts a block to execute
@@ -121,6 +121,18 @@ module Dry
121
121
  .map { |name| name.size == 1 ? "-#{name}" : "--#{name}" }
122
122
  .map { |name| boolean? || flag? ? name : "#{name} VALUE" }
123
123
  end
124
+
125
+ # @api private
126
+ def valid_value?(value)
127
+ available_values = values
128
+ return true if available_values.nil?
129
+
130
+ if array?
131
+ (value - available_values).empty?
132
+ else
133
+ available_values.map(&:to_s).include?(value.to_s)
134
+ end
135
+ end
124
136
  end
125
137
 
126
138
  # Command line argument
@@ -31,25 +31,25 @@ module Dry
31
31
 
32
32
  parsed_options = command.default_params.merge(parsed_options)
33
33
  parse_required_params(command, arguments, prog_name, parsed_options)
34
- rescue ::OptionParser::ParseError
35
- Result.failure("ERROR: \"#{prog_name}\" was called with arguments \"#{original_arguments.join(" ")}\"") # rubocop:disable Layout/LineLength
34
+ rescue ::OptionParser::ParseError, ValueError
35
+ Result.failure("ERROR: \"#{prog_name}\" was called with arguments \"#{original_arguments.join(" ")}\"")
36
36
  end
37
37
 
38
38
  # @since 0.1.0
39
39
  # @api private
40
40
  #
41
- # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
41
+ # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Layout/LineLength
42
42
  def self.parse_required_params(command, arguments, prog_name, parsed_options)
43
- parsed_params = match_arguments(command.arguments, arguments)
44
- parsed_required_params = match_arguments(command.required_arguments, arguments)
45
- all_required_params_satisfied = command.required_arguments.all? { |param| !parsed_required_params[param.name].nil? } # rubocop:disable Layout/LineLength
43
+ parsed_params = match_arguments(command.arguments, arguments, parsed_options)
44
+ parsed_required_params = match_arguments(command.required_arguments, arguments, parsed_options)
45
+ all_required_params_satisfied = command.required_arguments.all? { |param| !parsed_required_params[param.name].nil? }
46
46
 
47
47
  unused_arguments = arguments.drop(command.required_arguments.length)
48
48
 
49
49
  unless all_required_params_satisfied
50
50
  parsed_required_params_values = parsed_required_params.values.compact
51
51
 
52
- usage = "\nUsage: \"#{prog_name} #{command.required_arguments.map(&:description_name).join(" ")}" # rubocop:disable Layout/LineLength
52
+ usage = "\nUsage: \"#{prog_name} #{command.required_arguments.map(&:description_name).join(" ")}"
53
53
 
54
54
  usage += " | #{prog_name} SUBCOMMAND" if command.subcommands.any?
55
55
 
@@ -58,7 +58,7 @@ module Dry
58
58
  if parsed_required_params_values.empty?
59
59
  return Result.failure("ERROR: \"#{prog_name}\" was called with no arguments#{usage}")
60
60
  else
61
- return Result.failure("ERROR: \"#{prog_name}\" was called with arguments #{parsed_required_params_values}#{usage}") # rubocop:disable Layout/LineLength
61
+ return Result.failure("ERROR: \"#{prog_name}\" was called with arguments #{parsed_required_params_values}#{usage}")
62
62
  end
63
63
  end
64
64
 
@@ -67,17 +67,24 @@ module Dry
67
67
  parsed_options = parsed_options.merge(args: unused_arguments) if unused_arguments.any?
68
68
  Result.success(parsed_options)
69
69
  end
70
- # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity
70
+ # rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Layout/LineLength
71
71
 
72
- def self.match_arguments(command_arguments, arguments)
72
+ def self.match_arguments(command_arguments, arguments, default_values)
73
73
  result = {}
74
74
 
75
+ arg = nil
75
76
  command_arguments.each_with_index do |cmd_arg, index|
76
77
  if cmd_arg.array?
77
- result[cmd_arg.name] = arguments[index..]
78
+ arg = arguments[index..] || default_values[cmd_arg.name]
79
+ raise ValueError unless cmd_arg.valid_value?(arg)
80
+
81
+ result[cmd_arg.name] = arg
78
82
  break
79
83
  else
80
- result[cmd_arg.name] = arguments.at(index)
84
+ arg = arguments.at(index) || default_values[cmd_arg.name]
85
+ raise ValueError unless cmd_arg.valid_value?(arg)
86
+
87
+ result[cmd_arg.name] = arg
81
88
  end
82
89
  end
83
90
 
data/lib/dry/cli/usage.rb CHANGED
@@ -57,8 +57,8 @@ module Dry
57
57
  required_arguments = command.required_arguments
58
58
  optional_arguments = command.optional_arguments
59
59
 
60
- required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any? # rubocop:disable Layout/LineLength
61
- optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any? # rubocop:disable Layout/LineLength
60
+ required = required_arguments.map { |arg| arg.name.upcase }.join(" ") if required_arguments.any?
61
+ optional = optional_arguments.map { |arg| "[#{arg.name.upcase}]" }.join(" ") if optional_arguments.any?
62
62
  result = [required, optional].compact
63
63
 
64
64
  " #{result.join(" ")}" unless result.empty?
@@ -3,6 +3,6 @@
3
3
  module Dry
4
4
  class CLI
5
5
  # @since 0.1.0
6
- VERSION = "1.3.0"
6
+ VERSION = "1.4.1"
7
7
  end
8
8
  end
data/lib/dry/cli.rb CHANGED
@@ -64,8 +64,8 @@ module Dry
64
64
  def call(arguments: ARGV, out: $stdout, err: $stderr)
65
65
  @out, @err = out, err
66
66
  kommand ? perform_command(arguments) : perform_registry(arguments)
67
- rescue SignalException => e
68
- signal_exception(e)
67
+ rescue SignalException => exception
68
+ signal_exception(exception)
69
69
  rescue Errno::EPIPE
70
70
  # no op
71
71
  end
@@ -97,6 +97,10 @@ module Dry
97
97
  # @api private
98
98
  def perform_command(arguments)
99
99
  command, args = parse(kommand, arguments, [])
100
+
101
+ command.instance_variable_set(:@err, err) unless command.instance_variable_defined?(:@err)
102
+ command.instance_variable_set(:@out, out) unless command.instance_variable_defined?(:@out)
103
+
100
104
  command.call(**args)
101
105
  end
102
106
 
@@ -113,9 +117,12 @@ module Dry
113
117
 
114
118
  command, args = parse(result.command, result.arguments, result.names)
115
119
 
116
- result.before_callbacks.run(command, args)
120
+ command.instance_variable_set(:@err, err) unless command.instance_variable_defined?(:@err)
121
+ command.instance_variable_set(:@out, out) unless command.instance_variable_defined?(:@out)
122
+
123
+ result.before_callbacks.run(command, **args)
117
124
  command.call(**args)
118
- result.after_callbacks.run(command, args)
125
+ result.after_callbacks.run(command, **args)
119
126
  end
120
127
 
121
128
  # Parse arguments for a command.
@@ -165,8 +172,7 @@ module Dry
165
172
  # @since 1.1.1
166
173
  def spell_checker(result, arguments)
167
174
  spell_checker = SpellChecker.call(result, arguments)
168
- err.puts spell_checker if spell_checker
169
- puts
175
+ err.puts "#{spell_checker}\n\n" if spell_checker
170
176
  err.puts Usage.call(result)
171
177
  exit(1)
172
178
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
- - Luca Guidi
8
- autorequire:
7
+ - Hanakai team
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-07-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: bundler
@@ -16,68 +15,51 @@ dependencies:
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '1.6'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '3'
18
+ version: '0'
23
19
  type: :development
24
20
  prerelease: false
25
21
  version_requirements: !ruby/object:Gem::Requirement
26
22
  requirements:
27
23
  - - ">="
28
24
  - !ruby/object:Gem::Version
29
- version: '1.6'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '3'
25
+ version: '0'
33
26
  - !ruby/object:Gem::Dependency
34
27
  name: rake
35
28
  requirement: !ruby/object:Gem::Requirement
36
29
  requirements:
37
- - - "~>"
30
+ - - ">="
38
31
  - !ruby/object:Gem::Version
39
- version: '13.0'
32
+ version: '0'
40
33
  type: :development
41
34
  prerelease: false
42
35
  version_requirements: !ruby/object:Gem::Requirement
43
36
  requirements:
44
- - - "~>"
37
+ - - ">="
45
38
  - !ruby/object:Gem::Version
46
- version: '13.0'
39
+ version: '0'
47
40
  - !ruby/object:Gem::Dependency
48
41
  name: rspec
49
42
  requirement: !ruby/object:Gem::Requirement
50
43
  requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '3.7'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '3.7'
61
- - !ruby/object:Gem::Dependency
62
- name: simplecov
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
44
+ - - ">="
66
45
  - !ruby/object:Gem::Version
67
- version: 0.17.1
46
+ version: '0'
68
47
  type: :development
69
48
  prerelease: false
70
49
  version_requirements: !ruby/object:Gem::Requirement
71
50
  requirements:
72
- - - "~>"
51
+ - - ">="
73
52
  - !ruby/object:Gem::Version
74
- version: 0.17.1
53
+ version: '0'
75
54
  description: Common framework to build command line interfaces with Ruby
76
55
  email:
77
- - me@lucaguidi.com
56
+ - info@hanakai.org
78
57
  executables: []
79
58
  extensions: []
80
- extra_rdoc_files: []
59
+ extra_rdoc_files:
60
+ - CHANGELOG.md
61
+ - LICENSE
62
+ - README.md
81
63
  files:
82
64
  - CHANGELOG.md
83
65
  - LICENSE
@@ -105,7 +87,7 @@ metadata:
105
87
  changelog_uri: https://github.com/dry-rb/dry-cli/blob/main/CHANGELOG.md
106
88
  source_code_uri: https://github.com/dry-rb/dry-cli
107
89
  bug_tracker_uri: https://github.com/dry-rb/dry-cli/issues
108
- post_install_message:
90
+ funding_uri: https://github.com/sponsors/hanami
109
91
  rdoc_options: []
110
92
  require_paths:
111
93
  - lib
@@ -113,15 +95,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
113
95
  requirements:
114
96
  - - ">="
115
97
  - !ruby/object:Gem::Version
116
- version: '3.1'
98
+ version: '3.2'
117
99
  required_rubygems_version: !ruby/object:Gem::Requirement
118
100
  requirements:
119
101
  - - ">="
120
102
  - !ruby/object:Gem::Version
121
103
  version: '0'
122
104
  requirements: []
123
- rubygems_version: 3.3.27
124
- signing_key:
105
+ rubygems_version: 3.6.9
125
106
  specification_version: 4
126
107
  summary: Common framework to build command line interfaces with Ruby
127
108
  test_files: []