simple_input 0.1.1 → 0.2.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 +4 -4
- data/LICENSE +21 -0
- data/README.md +231 -0
- data/examples/basic.rb +31 -0
- data/examples/convert.rb +58 -0
- data/examples/custom_validators.rb +35 -0
- data/examples/error_handling.rb +38 -0
- data/examples/validation_patterns.rb +50 -0
- data/lib/simple_prompt/version.rb +1 -1
- metadata +18 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7bc4897e13a98263144b74d7f41c52a5551a5fd82137700fc81f7fef5ca27271
|
|
4
|
+
data.tar.gz: 111cec79eef33fe0c657f79d42a29020b8764880513df2839d676fc926bf96bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f2a86db2a363fdef0d0b75c71b9c9b962af329a171f10ae97879a52950e6a75374ed569645217ec32356ff637f1b34ba085edf242040681be60eeed56635e335
|
|
7
|
+
data.tar.gz: 6a6b0061f158c692db24a9ab149ad79d71ea0d49adb49f43bef20973299cd40a7b7443962e45bf4ed467418ff1dd1537426362f2ad1031d68124b32f4ef6b803
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hiroaki Satou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Simple Input
|
|
2
|
+
|
|
3
|
+
this is a simple prompt library for ruby.
|
|
4
|
+
inspired by golang's huh! library's input component.
|
|
5
|
+
https://github.com/charmbracelet/huh
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
- Ruby 3.4+
|
|
10
|
+
- Bundler
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
git clone <this-repo>
|
|
16
|
+
cd simple-input
|
|
17
|
+
bundle install
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
or
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
gem install simple-input
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Basic Input
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
require_relative 'input'
|
|
32
|
+
|
|
33
|
+
name = Input.new_input
|
|
34
|
+
.title('What is your name?')
|
|
35
|
+
.prompt('> ')
|
|
36
|
+
.validate(:not_empty)
|
|
37
|
+
.run
|
|
38
|
+
|
|
39
|
+
puts "Hello, #{name}!"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Custom Prompt
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
email = Input.new_input
|
|
46
|
+
.title('Enter your email')
|
|
47
|
+
.prompt('email> ')
|
|
48
|
+
.validate { |val| val.include?('@') ? nil : 'Please enter a valid email' }
|
|
49
|
+
.run
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Multiple Validators
|
|
53
|
+
|
|
54
|
+
Validators run in order. The first error found is displayed.
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
password = Input.new_input
|
|
58
|
+
.title('Create a password')
|
|
59
|
+
.prompt('password> ')
|
|
60
|
+
.validate(:not_empty)
|
|
61
|
+
.validate { |val| val.length < 8 ? 'Must be at least 8 characters' : nil }
|
|
62
|
+
.run
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Custom Validator Provider
|
|
66
|
+
|
|
67
|
+
By default, symbol validators (e.g., `:not_empty`) resolve against `DefaultValidators`. You can swap in your own module with `with_validators`:
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
module MyValidators
|
|
71
|
+
module_function
|
|
72
|
+
|
|
73
|
+
def email(val)
|
|
74
|
+
val.match?(/\A[^@\s]+@[^@\s]+\z/) ? nil : 'Invalid email format'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def min_length(val)
|
|
78
|
+
val.length >= 3 ? nil : 'Must be at least 3 characters'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
username = Input.new_input
|
|
83
|
+
.with_validators(MyValidators)
|
|
84
|
+
.validate(:min_length)
|
|
85
|
+
.run
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Validation Types
|
|
89
|
+
|
|
90
|
+
You can pass validators in three ways:
|
|
91
|
+
|
|
92
|
+
| Type | Example |
|
|
93
|
+
|------|---------|
|
|
94
|
+
| **Symbol** | `.validate(:not_empty)` - looks up method on the validator provider |
|
|
95
|
+
| **Proc/Lambda** | `.validate(-> (val) { val.empty? ? 'required' : nil })` |
|
|
96
|
+
| **Block** | `.validate { \|val\| val.empty? ? 'required' : nil }` |
|
|
97
|
+
|
|
98
|
+
Validators are functions that take a `String` and return `nil` (valid) or an error message `String`.
|
|
99
|
+
|
|
100
|
+
### Value Conversion
|
|
101
|
+
|
|
102
|
+
Use `convert_func` to transform the input value before it's returned. This is useful for converting strings to integers, floats, arrays, or any other type.
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
# Convert to integer
|
|
106
|
+
age = Input.new_input
|
|
107
|
+
.title('How old are you?')
|
|
108
|
+
.validate(:not_empty)
|
|
109
|
+
.validate { |val| val.match?(/^\d+$/) ? nil : 'Must be a number' }
|
|
110
|
+
.convert_func { |val| val.to_i }
|
|
111
|
+
.run
|
|
112
|
+
|
|
113
|
+
puts age.class # => Integer
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
# Convert to array
|
|
118
|
+
tags = Input.new_input
|
|
119
|
+
.title('Enter tags (comma-separated)')
|
|
120
|
+
.convert_func { |val| val.split(',').map(&:strip) }
|
|
121
|
+
.run
|
|
122
|
+
|
|
123
|
+
puts tags.inspect # => ["ruby", "cli", "prompt"]
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
You can pass a converter in two ways:
|
|
127
|
+
|
|
128
|
+
| Type | Example |
|
|
129
|
+
|------|---------|
|
|
130
|
+
| **Proc/Lambda** | `.convert_func(-> (val) { val.to_i })` |
|
|
131
|
+
| **Block** | `.convert_func { \|val\| val.to_i }` |
|
|
132
|
+
|
|
133
|
+
Converters are functions that take a `String` and return any type. Validation happens before conversion.
|
|
134
|
+
|
|
135
|
+
**Important:** If conversion fails with an exception, an error message will be displayed prompting you to add validation. Always validate input before conversion to prevent errors:
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
# ❌ Bad - conversion can fail without validation
|
|
139
|
+
age = Input.new_input
|
|
140
|
+
.convert_func { |val| Integer(val) } # Raises exception on invalid input
|
|
141
|
+
.run
|
|
142
|
+
|
|
143
|
+
# ✅ Good - validate before conversion
|
|
144
|
+
age = Input.new_input
|
|
145
|
+
.validate(:not_empty)
|
|
146
|
+
.validate { |val| val.match?(/^\d+$/) ? nil : 'Must be a number' }
|
|
147
|
+
.convert_func { |val| val.to_i }
|
|
148
|
+
.run
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Signal Handling
|
|
152
|
+
|
|
153
|
+
- **Ctrl-C** - Prints `(canceled)` and exits gracefully
|
|
154
|
+
- **Ctrl-D (EOF)** - Returns an empty string
|
|
155
|
+
|
|
156
|
+
## API
|
|
157
|
+
|
|
158
|
+
| Method | Description |
|
|
159
|
+
|--------|-------------|
|
|
160
|
+
| `Input.new_input` | Factory method to create a new Input (`.new` is private) |
|
|
161
|
+
| `#title(text)` | Set the title displayed above the prompt |
|
|
162
|
+
| `#prompt(text)` | Set the prompt string (default: `"> "`) |
|
|
163
|
+
| `#validate(validator, &block)` | Add a validator (Symbol, Proc, or block) |
|
|
164
|
+
| `#with_validators(provider)` | Set a custom validator provider module |
|
|
165
|
+
| `#convert_func(converter, &block)` | Set a converter function to transform the input value |
|
|
166
|
+
| `#run` | Start the interactive input loop and return the result |
|
|
167
|
+
|
|
168
|
+
All methods (except `#run`) return `self` for chaining.
|
|
169
|
+
|
|
170
|
+
## Running Examples
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Basic usage and validation
|
|
174
|
+
ruby examples/basic.rb
|
|
175
|
+
|
|
176
|
+
# Custom validator providers
|
|
177
|
+
ruby examples/custom_validators.rb
|
|
178
|
+
|
|
179
|
+
# Value conversion (string to int, array, etc.)
|
|
180
|
+
ruby examples/convert.rb
|
|
181
|
+
|
|
182
|
+
# Common validation patterns (email, password, range, choice)
|
|
183
|
+
ruby examples/validation_patterns.rb
|
|
184
|
+
|
|
185
|
+
# Error handling and conversion safety
|
|
186
|
+
ruby examples/error_handling.rb
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Testing
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
bundle exec rspec
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Testing with `with_context` (Private Method)
|
|
196
|
+
|
|
197
|
+
The `Input` class has a private method `with_context(reader, writer)` that allows injecting custom IO objects for testing. Since `new` is also private (enforcing use of `Input.new_input`), tests use `send` to access `with_context`:
|
|
198
|
+
|
|
199
|
+
```ruby
|
|
200
|
+
def build_input(input_text)
|
|
201
|
+
reader = StringIO.new(input_text)
|
|
202
|
+
writer = StringIO.new
|
|
203
|
+
input = Input.new_input
|
|
204
|
+
input.send(:with_context, reader, writer)
|
|
205
|
+
[input, writer]
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Usage in tests
|
|
209
|
+
it 'returns the user input' do
|
|
210
|
+
input, = build_input("hello\n")
|
|
211
|
+
result = input.run
|
|
212
|
+
expect(result).to eq('hello')
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'shows validation errors' do
|
|
216
|
+
input, writer = build_input("\nhello\n")
|
|
217
|
+
result = input.validate(:not_empty).run
|
|
218
|
+
expect(result).to eq('hello')
|
|
219
|
+
expect(writer.string).to include('入力してください')
|
|
220
|
+
end
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
This pattern lets you:
|
|
224
|
+
- Simulate user input via `StringIO` as the reader
|
|
225
|
+
- Capture all terminal output via `StringIO` as the writer
|
|
226
|
+
- Test the full input loop including validation re-prompting without interactive terminal input
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|
data/examples/basic.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../input'
|
|
4
|
+
|
|
5
|
+
# Basic usage - simple text input
|
|
6
|
+
name = Input.new_input
|
|
7
|
+
.title('What is your name?')
|
|
8
|
+
.prompt('> ')
|
|
9
|
+
.validate(:not_empty)
|
|
10
|
+
.run
|
|
11
|
+
|
|
12
|
+
puts "Hello, #{name}!"
|
|
13
|
+
|
|
14
|
+
# With custom validation
|
|
15
|
+
email = Input.new_input
|
|
16
|
+
.title('Enter your email')
|
|
17
|
+
.prompt('email> ')
|
|
18
|
+
.validate { |val| val.include?('@') ? nil : 'Please enter a valid email' }
|
|
19
|
+
.run
|
|
20
|
+
|
|
21
|
+
puts "Your email: #{email}"
|
|
22
|
+
|
|
23
|
+
# Multiple validators
|
|
24
|
+
password = Input.new_input
|
|
25
|
+
.title('Create a password')
|
|
26
|
+
.prompt('password> ')
|
|
27
|
+
.validate(:not_empty)
|
|
28
|
+
.validate { |val| val.length < 8 ? 'Password must be at least 8 characters' : nil }
|
|
29
|
+
.run
|
|
30
|
+
|
|
31
|
+
puts "Password set! (#{password.length} characters)"
|
data/examples/convert.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../input'
|
|
4
|
+
|
|
5
|
+
# Convert string to integer with proper validation
|
|
6
|
+
# Validation prevents conversion errors
|
|
7
|
+
age = Input.new_input
|
|
8
|
+
.title('How old are you?')
|
|
9
|
+
.prompt('age> ')
|
|
10
|
+
.validate(:not_empty)
|
|
11
|
+
.validate { |val| val.match?(/^\d+$/) ? nil : 'Please enter a valid number' }
|
|
12
|
+
.convert_func { |val| val.to_i }
|
|
13
|
+
.run
|
|
14
|
+
|
|
15
|
+
puts "You are #{age} years old (type: #{age.class})"
|
|
16
|
+
|
|
17
|
+
# Example: Without validation, conversion can fail
|
|
18
|
+
# This will show an error message prompting you to add validation
|
|
19
|
+
puts "\n--- Example of conversion error (try entering 'abc') ---"
|
|
20
|
+
number = Input.new_input
|
|
21
|
+
.title('Enter a number (without validation)')
|
|
22
|
+
.prompt('> ')
|
|
23
|
+
.convert_func { |val| Integer(val) } # Integer() raises exception on invalid input
|
|
24
|
+
.run
|
|
25
|
+
|
|
26
|
+
puts "Number: #{number}"
|
|
27
|
+
|
|
28
|
+
# Convert to uppercase
|
|
29
|
+
name = Input.new_input
|
|
30
|
+
.title('What is your name?')
|
|
31
|
+
.prompt('name> ')
|
|
32
|
+
.validate(:not_empty)
|
|
33
|
+
.convert_func { |val| val.upcase }
|
|
34
|
+
.run
|
|
35
|
+
|
|
36
|
+
puts "Hello, #{name}!"
|
|
37
|
+
|
|
38
|
+
# Convert to array by splitting
|
|
39
|
+
tags = Input.new_input
|
|
40
|
+
.title('Enter tags (comma-separated)')
|
|
41
|
+
.prompt('tags> ')
|
|
42
|
+
.validate(:not_empty)
|
|
43
|
+
.convert_func { |val| val.split(',').map(&:strip) }
|
|
44
|
+
.run
|
|
45
|
+
|
|
46
|
+
puts "Tags: #{tags.inspect} (type: #{tags.class})"
|
|
47
|
+
|
|
48
|
+
# Using Proc instead of block
|
|
49
|
+
to_float = proc { |val| val.to_f }
|
|
50
|
+
price = Input.new_input
|
|
51
|
+
.title('Enter price')
|
|
52
|
+
.prompt('$')
|
|
53
|
+
.validate(:not_empty)
|
|
54
|
+
.validate { |val| val.match?(/^\d+\.?\d*$/) ? nil : 'Please enter a valid price' }
|
|
55
|
+
.convert_func(to_float)
|
|
56
|
+
.run
|
|
57
|
+
|
|
58
|
+
puts "Price: $#{price} (type: #{price.class})"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../input'
|
|
4
|
+
|
|
5
|
+
# Define a custom validator provider
|
|
6
|
+
module MyValidators
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def email(val)
|
|
10
|
+
val.match?(/\A[^@\s]+@[^@\s]+\z/) ? nil : 'Invalid email format'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def min_length(val)
|
|
14
|
+
val.length >= 3 ? nil : 'Must be at least 3 characters'
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Use with_validators to swap in your custom provider
|
|
19
|
+
username = Input.new_input
|
|
20
|
+
.title('Choose a username')
|
|
21
|
+
.prompt('>> ')
|
|
22
|
+
.with_validators(MyValidators)
|
|
23
|
+
.validate(:min_length)
|
|
24
|
+
.run
|
|
25
|
+
|
|
26
|
+
puts "Username: #{username}"
|
|
27
|
+
|
|
28
|
+
email = Input.new_input
|
|
29
|
+
.title('Enter your email')
|
|
30
|
+
.prompt('>> ')
|
|
31
|
+
.with_validators(MyValidators)
|
|
32
|
+
.validate(:email)
|
|
33
|
+
.run
|
|
34
|
+
|
|
35
|
+
puts "Email: #{email}"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../input'
|
|
4
|
+
|
|
5
|
+
puts "=== Error Handling Example ===\n\n"
|
|
6
|
+
|
|
7
|
+
# Example 1: Conversion without validation (will show error on invalid input)
|
|
8
|
+
puts "Try entering 'abc' to see the error message:"
|
|
9
|
+
number = Input.new_input
|
|
10
|
+
.title('Enter a number (no validation)')
|
|
11
|
+
.prompt('> ')
|
|
12
|
+
.convert_func { |val| Integer(val) }
|
|
13
|
+
.run
|
|
14
|
+
|
|
15
|
+
puts "Number: #{number}\n\n"
|
|
16
|
+
|
|
17
|
+
# Example 2: Proper validation before conversion
|
|
18
|
+
puts "Now with validation:"
|
|
19
|
+
safe_number = Input.new_input
|
|
20
|
+
.title('Enter a number (with validation)')
|
|
21
|
+
.prompt('> ')
|
|
22
|
+
.validate(:not_empty)
|
|
23
|
+
.validate { |val| val.match?(/^-?\d+$/) ? nil : 'Must be a valid integer' }
|
|
24
|
+
.convert_func { |val| val.to_i }
|
|
25
|
+
.run
|
|
26
|
+
|
|
27
|
+
puts "Number: #{safe_number}\n\n"
|
|
28
|
+
|
|
29
|
+
# Example 3: Float conversion with validation
|
|
30
|
+
price = Input.new_input
|
|
31
|
+
.title('Enter price')
|
|
32
|
+
.prompt('$')
|
|
33
|
+
.validate(:not_empty)
|
|
34
|
+
.validate { |val| val.match?(/^\d+\.?\d*$/) ? nil : 'Must be a valid price (e.g., 10 or 10.99)' }
|
|
35
|
+
.convert_func { |val| val.to_f }
|
|
36
|
+
.run
|
|
37
|
+
|
|
38
|
+
puts "Price: $#{format('%.2f', price)}"
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../input'
|
|
4
|
+
|
|
5
|
+
puts "=== Validation Patterns Example ===\n\n"
|
|
6
|
+
|
|
7
|
+
# Pattern 1: Email validation
|
|
8
|
+
email = Input.new_input
|
|
9
|
+
.title('Enter your email address')
|
|
10
|
+
.prompt('email> ')
|
|
11
|
+
.validate(:not_empty)
|
|
12
|
+
.validate { |val| val.match?(/\A[^@\s]+@[^@\s]+\.[^@\s]+\z/) ? nil : 'Invalid email format' }
|
|
13
|
+
.run
|
|
14
|
+
|
|
15
|
+
puts "Email registered: #{email}\n\n"
|
|
16
|
+
|
|
17
|
+
# Pattern 2: Password with multiple rules
|
|
18
|
+
password = Input.new_input
|
|
19
|
+
.title('Create a secure password')
|
|
20
|
+
.prompt('password> ')
|
|
21
|
+
.validate(:not_empty)
|
|
22
|
+
.validate { |val| val.length >= 8 ? nil : 'Must be at least 8 characters' }
|
|
23
|
+
.validate { |val| val.match?(/[A-Z]/) ? nil : 'Must contain at least one uppercase letter' }
|
|
24
|
+
.validate { |val| val.match?(/[0-9]/) ? nil : 'Must contain at least one number' }
|
|
25
|
+
.run
|
|
26
|
+
|
|
27
|
+
puts "Password created! (#{password.length} characters)\n\n"
|
|
28
|
+
|
|
29
|
+
# Pattern 3: Range validation with conversion
|
|
30
|
+
age = Input.new_input
|
|
31
|
+
.title('Enter your age')
|
|
32
|
+
.prompt('age> ')
|
|
33
|
+
.validate(:not_empty)
|
|
34
|
+
.validate { |val| val.match?(/^\d+$/) ? nil : 'Must be a number' }
|
|
35
|
+
.validate { |val| val.to_i.between?(1, 120) ? nil : 'Age must be between 1 and 120' }
|
|
36
|
+
.convert_func { |val| val.to_i }
|
|
37
|
+
.run
|
|
38
|
+
|
|
39
|
+
puts "Age: #{age} (type: #{age.class})\n\n"
|
|
40
|
+
|
|
41
|
+
# Pattern 4: Choice validation
|
|
42
|
+
choice = Input.new_input
|
|
43
|
+
.title('Select your preferred language')
|
|
44
|
+
.prompt('(ruby/python/javascript)> ')
|
|
45
|
+
.validate(:not_empty)
|
|
46
|
+
.validate { |val| %w[ruby python javascript].include?(val.downcase) ? nil : 'Must be ruby, python, or javascript' }
|
|
47
|
+
.convert_func { |val| val.downcase.to_sym }
|
|
48
|
+
.run
|
|
49
|
+
|
|
50
|
+
puts "Selected language: #{choice} (type: #{choice.class})"
|
metadata
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: simple_input
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Hiroaki Satou
|
|
8
|
-
bindir:
|
|
8
|
+
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
@@ -93,16 +93,22 @@ dependencies:
|
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
95
|
version: 0.5.100
|
|
96
|
-
description:
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
email: hiroakisatou@example.com
|
|
96
|
+
description: Simple Input provides a fluent API for creating interactive command-line
|
|
97
|
+
prompts with validation and conversion support. Inspired by golang's huh! library's
|
|
98
|
+
input component.
|
|
99
|
+
email:
|
|
100
|
+
- ''
|
|
102
101
|
executables: []
|
|
103
102
|
extensions: []
|
|
104
103
|
extra_rdoc_files: []
|
|
105
104
|
files:
|
|
105
|
+
- LICENSE
|
|
106
|
+
- README.md
|
|
107
|
+
- examples/basic.rb
|
|
108
|
+
- examples/convert.rb
|
|
109
|
+
- examples/custom_validators.rb
|
|
110
|
+
- examples/error_handling.rb
|
|
111
|
+
- examples/validation_patterns.rb
|
|
106
112
|
- lib/simple_prompt.rb
|
|
107
113
|
- lib/simple_prompt/default_validators.rb
|
|
108
114
|
- lib/simple_prompt/input.rb
|
|
@@ -111,7 +117,9 @@ homepage: https://github.com/hiroakisatou/simple-prompt
|
|
|
111
117
|
licenses:
|
|
112
118
|
- MIT
|
|
113
119
|
metadata:
|
|
120
|
+
homepage_uri: https://github.com/hiroakisatou/simple-prompt
|
|
114
121
|
source_code_uri: https://github.com/hiroakisatou/simple-prompt
|
|
122
|
+
changelog_uri: https://github.com/hiroakisatou/simple-prompt/blob/main/CHANGELOG.md
|
|
115
123
|
rubygems_mfa_required: 'true'
|
|
116
124
|
rdoc_options: []
|
|
117
125
|
require_paths:
|
|
@@ -120,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
120
128
|
requirements:
|
|
121
129
|
- - ">="
|
|
122
130
|
- !ruby/object:Gem::Version
|
|
123
|
-
version:
|
|
131
|
+
version: 3.4.0
|
|
124
132
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
133
|
requirements:
|
|
126
134
|
- - ">="
|
|
@@ -129,5 +137,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
129
137
|
requirements: []
|
|
130
138
|
rubygems_version: 4.0.6
|
|
131
139
|
specification_version: 4
|
|
132
|
-
summary: A simple
|
|
140
|
+
summary: A simple prompt library for Ruby inspired by golang's huh! library
|
|
133
141
|
test_files: []
|