philiprehberger-cli_kit 0.3.0 → 0.4.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/CHANGELOG.md +13 -1
- data/README.md +15 -0
- data/lib/philiprehberger/cli_kit/parser.rb +22 -4
- data/lib/philiprehberger/cli_kit/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c4606c83ce0c95c7b047c9db662457bce97852169987a96a44566d4811e78313
|
|
4
|
+
data.tar.gz: 907327c09e57175ca6e1c07d03369fdfe5f157534836e64acf348b79dc439a5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '08bb60e7b9c05a9e6d5572a8a393f61b987c07a136f7cb1eaf6e6ac58168fea50230f5855d073c47bd0516b178d19e138d223ccc7ff4e529248b9aef16f08699'
|
|
7
|
+
data.tar.gz: 20864d8ed45d20aabe85d072ba1adcb44590c76f346329e51314b4163bce07951b2759327ef852112bccaec05f82705e28b5534502d5b5dde6e2b0efaddb4733
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-04-18
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `option :name, required: true` — DSL flag that raises `CliKit::Error` at parse time when the option is omitted; help output appends `(required)` to the option's description
|
|
14
|
+
|
|
15
|
+
## [0.3.1] - 2026-04-15
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- Compliance audit against Ruby package, gemspec, and README guides — no blocking issues found; reaffirmed gemspec metadata (5 URIs, `rubygems_mfa_required`, `required_ruby_version >= 3.1.0`, `Dir['lib/**/*.rb', 'LICENSE', 'README.md', 'CHANGELOG.md']`), README structure (10 sections with 3 badges and emoji Support list), Keep a Changelog format, full `.github/` scaffolding (issue templates, dependabot, PR template, CI matrix with publish job), and config files (`.rubocop.yml`, `.gitignore`, `Gemfile`, `Rakefile`)
|
|
19
|
+
|
|
10
20
|
## [0.3.0] - 2026-04-15
|
|
11
21
|
|
|
12
22
|
### Added
|
|
@@ -58,7 +68,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
58
68
|
- Animated spinner for long-running operations
|
|
59
69
|
- Positional argument collection
|
|
60
70
|
|
|
61
|
-
[Unreleased]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.
|
|
71
|
+
[Unreleased]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.4.0...HEAD
|
|
72
|
+
[0.4.0]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.3.1...v0.4.0
|
|
73
|
+
[0.3.1]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.3.0...v0.3.1
|
|
62
74
|
[0.3.0]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.2.1...v0.3.0
|
|
63
75
|
[0.2.1]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.2.0...v0.2.1
|
|
64
76
|
[0.2.0]: https://github.com/philiprehberger/rb-cli-kit/compare/v0.1.2...v0.2.0
|
data/README.md
CHANGED
|
@@ -105,6 +105,20 @@ port = Philiprehberger::CliKit.ask('Port:', error: 'Must be a number') do |answe
|
|
|
105
105
|
end
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
+
### Required options
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
result = Philiprehberger::CliKit.parse(ARGV) do
|
|
112
|
+
option :env, short: :e, required: true, desc: 'Target environment'
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Invoked without --env raises Philiprehberger::CliKit::Error:
|
|
116
|
+
# Missing required option(s): --env
|
|
117
|
+
#
|
|
118
|
+
# Help text appends "(required)" to the option's description:
|
|
119
|
+
# -e, --env VALUE Target environment (required)
|
|
120
|
+
```
|
|
121
|
+
|
|
108
122
|
### Repeatable Options
|
|
109
123
|
|
|
110
124
|
```ruby
|
|
@@ -176,6 +190,7 @@ end
|
|
|
176
190
|
| `.multi_select(message, choices, defaults:)` | Present numbered menu and return multiple selections |
|
|
177
191
|
| `.spinner(message) { ... }` | Show spinner during block execution |
|
|
178
192
|
| `Parser#option(name, multi: true)` | Collect repeated option values into an array |
|
|
193
|
+
| `Parser#option(name, required: true)` | Raise `CliKit::Error` at parse time when the option is omitted |
|
|
179
194
|
| `Parser#flags` | Hash of boolean flag values |
|
|
180
195
|
| `Parser#options` | Hash of option values (arrays when `multi: true`) |
|
|
181
196
|
| `Parser#arguments` | Array of positional arguments |
|
|
@@ -13,6 +13,7 @@ module Philiprehberger
|
|
|
13
13
|
@flags = {}
|
|
14
14
|
@options = {}
|
|
15
15
|
@arguments = []
|
|
16
|
+
@supplied_options = []
|
|
16
17
|
@command_name = nil
|
|
17
18
|
@program_name = nil
|
|
18
19
|
end
|
|
@@ -35,9 +36,12 @@ module Philiprehberger
|
|
|
35
36
|
# @param default [Object, nil] default value
|
|
36
37
|
# @param desc [String, nil] description for help text
|
|
37
38
|
# @param multi [Boolean] when true, collect repeated values into an array
|
|
39
|
+
# @param required [Boolean] when true, raise if the option is not supplied at parse time
|
|
38
40
|
# @return [void]
|
|
39
|
-
def option(name, short: nil, default: nil, desc: nil, multi: false)
|
|
40
|
-
@option_definitions[name] = {
|
|
41
|
+
def option(name, short: nil, default: nil, desc: nil, multi: false, required: false)
|
|
42
|
+
@option_definitions[name] = {
|
|
43
|
+
short: short, default: default, desc: desc, multi: multi, required: required
|
|
44
|
+
}
|
|
41
45
|
@options[name] = multi ? [] : default
|
|
42
46
|
end
|
|
43
47
|
|
|
@@ -131,6 +135,7 @@ module Philiprehberger
|
|
|
131
135
|
@arguments << arg
|
|
132
136
|
end
|
|
133
137
|
end
|
|
138
|
+
validate_required_options!
|
|
134
139
|
self
|
|
135
140
|
end
|
|
136
141
|
|
|
@@ -172,6 +177,7 @@ module Philiprehberger
|
|
|
172
177
|
|
|
173
178
|
def assign_option(name, value)
|
|
174
179
|
defn = @option_definitions[name]
|
|
180
|
+
@supplied_options << name
|
|
175
181
|
if defn && defn[:multi]
|
|
176
182
|
@options[name] = [] unless @options[name].is_a?(Array)
|
|
177
183
|
@options[name] << value unless value.nil?
|
|
@@ -180,6 +186,16 @@ module Philiprehberger
|
|
|
180
186
|
end
|
|
181
187
|
end
|
|
182
188
|
|
|
189
|
+
def validate_required_options!
|
|
190
|
+
missing = @option_definitions.each_with_object([]) do |(name, defn), acc|
|
|
191
|
+
acc << name if defn[:required] && !@supplied_options.include?(name)
|
|
192
|
+
end
|
|
193
|
+
return if missing.empty?
|
|
194
|
+
|
|
195
|
+
names = missing.map { |n| "--#{n.to_s.tr('_', '-')}" }.join(', ')
|
|
196
|
+
raise Error, "Missing required option(s): #{names}"
|
|
197
|
+
end
|
|
198
|
+
|
|
183
199
|
def format_flag_help(name, defn)
|
|
184
200
|
long = "--#{name.to_s.tr('_', '-')}"
|
|
185
201
|
if defn[:short]
|
|
@@ -204,8 +220,10 @@ module Philiprehberger
|
|
|
204
220
|
else
|
|
205
221
|
label = " #{long}"
|
|
206
222
|
end
|
|
207
|
-
|
|
208
|
-
|
|
223
|
+
desc = defn[:desc]
|
|
224
|
+
desc = desc ? "#{desc} (required)" : '(required)' if defn[:required]
|
|
225
|
+
if desc
|
|
226
|
+
"#{label.ljust(24)}#{desc}"
|
|
209
227
|
else
|
|
210
228
|
label
|
|
211
229
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: philiprehberger-cli_kit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Philip Rehberger
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Lightweight CLI toolkit combining argument parsing with flags and options,
|
|
14
14
|
interactive prompts with confirmation, and animated spinners for long-running operations.
|