rake_options 0.1.1 → 0.1.3
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/README.md +63 -71
- data/lib/rake_options/cli_parser.rb +43 -11
- data/lib/rake_options/help_generator.rb +17 -6
- data/lib/rake_options/version.rb +1 -1
- data/lib/rake_options.rb +5 -6
- data/spec/integration/rake_options_integration_spec.rb +34 -93
- data/spec/rake_options/cli_parser_spec.rb +26 -22
- data/spec/rake_options/help_generator_spec.rb +7 -13
- data/spec/rake_options_spec.rb +12 -21
- metadata +2 -6
- data/lib/rake_options/argument_parser.rb +0 -46
- data/lib/rake_options/bracket_parser.rb +0 -64
- data/spec/rake_options/argument_parser_spec.rb +0 -71
- data/spec/rake_options/bracket_parser_spec.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c23f2f501224d1849ee5255aafb6f023e12f6bacdeacdcd2a4909eb711e73adb
|
4
|
+
data.tar.gz: eaaa2f161b92704669317004e64dfee3267f4473095a561be9b8c71354d6362e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b507cb81d6ae6518115b35ce028779d7dbccbdebac5d328970ff2935269cf4d46041bc45927333d39efe897ede7646087873401095295635853e0d6e1a542560
|
7
|
+
data.tar.gz: 54a8901e28628730a2a15c8a2b53a06a89bdc0e1c621aa437dcef36890f4ee6f8c7cff07c32b3d299a6ce42360137661266426d1323995caa001fdd17052a67a
|
data/README.md
CHANGED
@@ -31,21 +31,24 @@ require 'rake_options'
|
|
31
31
|
|
32
32
|
desc "Build with custom options"
|
33
33
|
task :build do
|
34
|
-
|
35
|
-
|
36
|
-
"
|
37
|
-
|
34
|
+
# Simple array configuration: [flag_name, type]
|
35
|
+
config = [
|
36
|
+
["with-mysql-lib", :string],
|
37
|
+
["enable-feature", :string],
|
38
|
+
["port", :integer]
|
39
|
+
]
|
38
40
|
|
39
41
|
options = RakeOptions.command_line_args(config)
|
40
42
|
|
41
43
|
puts "MySQL lib path: #{options['with-mysql-lib']}"
|
42
44
|
puts "Feature: #{options['enable-feature']}"
|
45
|
+
puts "Port: #{options['port']}" # Automatically cast to integer
|
43
46
|
end
|
44
47
|
```
|
45
48
|
|
46
49
|
Run with:
|
47
50
|
```bash
|
48
|
-
rake build -- --with-mysql-lib=/usr/local/mysql/lib --enable-feature=caching
|
51
|
+
rake build -- --with-mysql-lib=/usr/local/mysql/lib --enable-feature=caching --port=3000
|
49
52
|
```
|
50
53
|
|
51
54
|
For values with spaces, use quotes:
|
@@ -53,39 +56,34 @@ For values with spaces, use quotes:
|
|
53
56
|
rake build -- --with-mysql-lib="/path/with spaces/lib"
|
54
57
|
```
|
55
58
|
|
56
|
-
###
|
59
|
+
### Type Casting
|
60
|
+
|
61
|
+
RakeOptions automatically casts values to the specified type:
|
57
62
|
|
58
63
|
```ruby
|
59
|
-
|
64
|
+
config = [
|
65
|
+
["port", :integer],
|
66
|
+
["enabled", :boolean],
|
67
|
+
["ratio", :float],
|
68
|
+
["name", :string]
|
69
|
+
]
|
60
70
|
|
61
|
-
|
62
|
-
task :deploy do
|
63
|
-
config = {
|
64
|
-
"environment" => "[environment=$env]",
|
65
|
-
"region" => "[region=$region]"
|
66
|
-
}
|
67
|
-
|
68
|
-
options = RakeOptions.command_line_args(config, notation: :bracket)
|
69
|
-
|
70
|
-
puts "Deploying to #{options['environment']} in #{options['region']}"
|
71
|
-
end
|
72
|
-
```
|
71
|
+
options = RakeOptions.command_line_args(config)
|
73
72
|
|
74
|
-
|
75
|
-
|
76
|
-
|
73
|
+
# Values are automatically cast:
|
74
|
+
options['port'] # => 3000 (Integer)
|
75
|
+
options['enabled'] # => true (Boolean)
|
76
|
+
options['ratio'] # => 1.5 (Float)
|
77
|
+
options['name'] # => "myapp" (String)
|
77
78
|
```
|
78
79
|
|
79
|
-
|
80
|
+
Supported types:
|
81
|
+
- `:string` - String values (default)
|
82
|
+
- `:integer` or `:int` - Integer values
|
83
|
+
- `:float` - Float values
|
84
|
+
- `:boolean` or `:bool` - Boolean values (true/false)
|
80
85
|
|
81
|
-
```ruby
|
82
|
-
config = {
|
83
|
-
"database" => "--config $file --env $environment"
|
84
|
-
}
|
85
86
|
|
86
|
-
options = RakeOptions.command_line_args(config)
|
87
|
-
# Extracts both file and environment from: --config=database.yml --env=production
|
88
|
-
```
|
89
87
|
|
90
88
|
### Automatic Help Documentation
|
91
89
|
|
@@ -96,18 +94,20 @@ readme_content = <<~HELP
|
|
96
94
|
Build Task Help
|
97
95
|
|
98
96
|
Available options:
|
99
|
-
--with-mysql-lib
|
100
|
-
--enable-feature
|
97
|
+
--with-mysql-lib=PATH Specify MySQL library path (string)
|
98
|
+
--enable-feature=NAME Enable a specific feature (string)
|
99
|
+
--port=NUMBER Port number (integer)
|
101
100
|
HELP
|
102
101
|
|
103
102
|
RakeOptions.initialize_readme(readme_content)
|
104
103
|
|
105
104
|
desc "Build with help support"
|
106
105
|
task :build do
|
107
|
-
config =
|
108
|
-
"with-mysql-lib"
|
109
|
-
"enable-feature"
|
110
|
-
|
106
|
+
config = [
|
107
|
+
["with-mysql-lib", :string],
|
108
|
+
["enable-feature", :string],
|
109
|
+
["port", :integer]
|
110
|
+
]
|
111
111
|
|
112
112
|
options = RakeOptions.command_line_args(config)
|
113
113
|
# Your build logic here
|
@@ -133,37 +133,40 @@ options[:with_mysql_lib]
|
|
133
133
|
|
134
134
|
## Configuration Format
|
135
135
|
|
136
|
-
The configuration
|
136
|
+
The configuration is a simple array of tuples:
|
137
137
|
|
138
138
|
```ruby
|
139
|
-
|
140
|
-
"
|
141
|
-
|
139
|
+
[
|
140
|
+
["flag-name", :type],
|
141
|
+
["another-flag", :type]
|
142
|
+
]
|
142
143
|
```
|
143
144
|
|
144
|
-
- **
|
145
|
-
- **
|
146
|
-
- **Variables**: Prefixed with `$` to indicate where values should be extracted
|
145
|
+
- **flag-name**: The CLI flag name (will become `--flag-name`)
|
146
|
+
- **type**: The data type (`:string`, `:integer`, `:float`, `:boolean`)
|
147
147
|
|
148
|
-
###
|
148
|
+
### Examples
|
149
149
|
|
150
150
|
```ruby
|
151
|
-
#
|
152
|
-
"mysql-path"
|
151
|
+
# String values
|
152
|
+
["mysql-path", :string]
|
153
|
+
|
154
|
+
# Integer values
|
155
|
+
["port", :integer]
|
153
156
|
|
154
|
-
#
|
155
|
-
"
|
157
|
+
# Boolean flags
|
158
|
+
["enabled", :boolean]
|
156
159
|
|
157
|
-
#
|
158
|
-
"
|
160
|
+
# Float values
|
161
|
+
["ratio", :float]
|
159
162
|
```
|
160
163
|
|
161
|
-
##
|
164
|
+
## Usage Format
|
162
165
|
|
163
|
-
|
166
|
+
RakeOptions uses standard CLI flag format:
|
164
167
|
|
165
168
|
```ruby
|
166
|
-
options = RakeOptions.command_line_args(config
|
169
|
+
options = RakeOptions.command_line_args(config)
|
167
170
|
```
|
168
171
|
|
169
172
|
Supports:
|
@@ -171,17 +174,6 @@ Supports:
|
|
171
174
|
- `--flag="value with spaces"`
|
172
175
|
- Multiple flags in one command
|
173
176
|
|
174
|
-
### Bracket Notation
|
175
|
-
|
176
|
-
```ruby
|
177
|
-
options = RakeOptions.command_line_args(config, notation: :bracket)
|
178
|
-
```
|
179
|
-
|
180
|
-
Supports:
|
181
|
-
- `[key=value]`
|
182
|
-
- `[key="value with spaces"]`
|
183
|
-
- Multiple bracket arguments
|
184
|
-
|
185
177
|
## Error Handling
|
186
178
|
|
187
179
|
RakeOptions provides clear error messages:
|
@@ -236,17 +228,17 @@ rake task -- --help
|
|
236
228
|
rake task -- --path="/path/with spaces"
|
237
229
|
```
|
238
230
|
|
239
|
-
###
|
231
|
+
### Flag name mismatch
|
240
232
|
|
241
|
-
**Problem**:
|
233
|
+
**Problem**: Arguments aren't being recognized.
|
242
234
|
|
243
|
-
**Solution**: Ensure
|
235
|
+
**Solution**: Ensure the flag name in ARGV matches the config:
|
244
236
|
```ruby
|
245
|
-
#
|
246
|
-
"option"
|
237
|
+
# Config
|
238
|
+
["my-option", :string]
|
247
239
|
|
248
|
-
# Command line must match
|
249
|
-
rake task -- --option=myvalue
|
240
|
+
# Command line must match exactly
|
241
|
+
rake task -- --my-option=myvalue
|
250
242
|
```
|
251
243
|
|
252
244
|
## Requirements
|
@@ -5,12 +5,14 @@ require_relative "template_engine"
|
|
5
5
|
module RakeOptions
|
6
6
|
class CLIParser
|
7
7
|
def initialize(config)
|
8
|
-
@config = config
|
8
|
+
@config = normalize_config(config)
|
9
9
|
@parsed_templates = {}
|
10
10
|
|
11
11
|
# Pre-parse all templates
|
12
|
-
@config.each do |key,
|
13
|
-
|
12
|
+
@config.each do |key, type|
|
13
|
+
# Auto-construct the full template from the key
|
14
|
+
full_template = "--#{key} $value"
|
15
|
+
@parsed_templates[key] = TemplateEngine.parse_template(full_template)
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -20,18 +22,13 @@ module RakeOptions
|
|
20
22
|
def parse(argv = ARGV)
|
21
23
|
result = {}
|
22
24
|
|
23
|
-
@config.each do |key,
|
25
|
+
@config.each do |key, type|
|
24
26
|
parsed_template = @parsed_templates[key]
|
25
27
|
extracted = TemplateEngine.extract_values(argv, parsed_template)
|
26
28
|
|
27
29
|
if extracted && !extracted.empty?
|
28
|
-
|
29
|
-
|
30
|
-
result[key] = extracted.values.first
|
31
|
-
else
|
32
|
-
# For multiple variables, store the hash
|
33
|
-
result[key] = extracted
|
34
|
-
end
|
30
|
+
raw_value = extracted.values.first
|
31
|
+
result[key] = cast_value(raw_value, type)
|
35
32
|
else
|
36
33
|
result[key] = nil
|
37
34
|
end
|
@@ -39,5 +36,40 @@ module RakeOptions
|
|
39
36
|
|
40
37
|
result
|
41
38
|
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Normalize config to hash format
|
43
|
+
# @param config [Array, Hash] Configuration
|
44
|
+
# @return [Hash] Normalized configuration
|
45
|
+
def normalize_config(config)
|
46
|
+
if config.is_a?(Array)
|
47
|
+
# Convert array of tuples to hash
|
48
|
+
config.to_h
|
49
|
+
else
|
50
|
+
config
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Cast value to specified type
|
55
|
+
# @param value [String] Raw string value
|
56
|
+
# @param type [Symbol] Target type
|
57
|
+
# @return [Object] Casted value
|
58
|
+
def cast_value(value, type)
|
59
|
+
return nil if value.nil?
|
60
|
+
|
61
|
+
case type
|
62
|
+
when :string
|
63
|
+
value.to_s
|
64
|
+
when :integer, :int
|
65
|
+
value.to_i
|
66
|
+
when :float
|
67
|
+
value.to_f
|
68
|
+
when :boolean, :bool
|
69
|
+
value.downcase == 'true' || value == '1'
|
70
|
+
else
|
71
|
+
value
|
72
|
+
end
|
73
|
+
end
|
42
74
|
end
|
43
75
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module RakeOptions
|
4
4
|
class HelpGenerator
|
5
5
|
def initialize(config, readme_content = nil)
|
6
|
-
@config = config
|
6
|
+
@config = normalize_config(config)
|
7
7
|
@readme_content = readme_content
|
8
8
|
end
|
9
9
|
|
@@ -26,13 +26,24 @@ module RakeOptions
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
# Normalize config to hash format
|
30
|
+
# @param config [Array, Hash] Configuration
|
31
|
+
# @return [Hash] Normalized configuration
|
32
|
+
def normalize_config(config)
|
33
|
+
if config.is_a?(Array)
|
34
|
+
config.to_h
|
35
|
+
else
|
36
|
+
config
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
29
40
|
# Auto-generate help from config
|
30
41
|
# @return [String] Auto-generated help text
|
31
42
|
def auto_generate_help
|
32
43
|
help_text = "Available Options:\n\n"
|
33
44
|
|
34
|
-
@config.each do |key,
|
35
|
-
help_text += format_option(key,
|
45
|
+
@config.each do |key, type|
|
46
|
+
help_text += format_option(key, type)
|
36
47
|
end
|
37
48
|
|
38
49
|
help_text
|
@@ -40,10 +51,10 @@ module RakeOptions
|
|
40
51
|
|
41
52
|
# Format individual option for display
|
42
53
|
# @param key [String] Option key
|
43
|
-
# @param
|
54
|
+
# @param type [Symbol] Value type
|
44
55
|
# @return [String] Formatted option line
|
45
|
-
def format_option(key,
|
46
|
-
"
|
56
|
+
def format_option(key, type)
|
57
|
+
" --#{key}=VALUE".ljust(42) + "(#{type})\n"
|
47
58
|
end
|
48
59
|
end
|
49
60
|
end
|
data/lib/rake_options/version.rb
CHANGED
data/lib/rake_options.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative "rake_options/version"
|
4
4
|
require_relative "rake_options/errors"
|
5
|
-
require_relative "rake_options/
|
5
|
+
require_relative "rake_options/cli_parser"
|
6
6
|
require_relative "rake_options/help_generator"
|
7
7
|
require_relative "rake_options/hash_with_indifferent_access"
|
8
8
|
|
@@ -11,18 +11,17 @@ module RakeOptions
|
|
11
11
|
attr_accessor :readme_content
|
12
12
|
|
13
13
|
# Parse command line arguments based on configuration
|
14
|
-
# @param config [
|
15
|
-
# @param notation [Symbol] Notation style (:cli or :bracket)
|
14
|
+
# @param config [Array] Argument configuration as array of [name, type] tuples
|
16
15
|
# @return [HashWithIndifferentAccess] Parsed arguments with indifferent access
|
17
|
-
def command_line_args(config
|
16
|
+
def command_line_args(config)
|
18
17
|
# Check for --help flag
|
19
18
|
if ARGV.include?("--help")
|
20
19
|
help_generator = HelpGenerator.new(config, readme_content)
|
21
20
|
help_generator.display_and_exit
|
22
21
|
end
|
23
22
|
|
24
|
-
# Parse arguments
|
25
|
-
parser =
|
23
|
+
# Parse arguments using CLI parser
|
24
|
+
parser = CLIParser.new(config)
|
26
25
|
result = parser.parse
|
27
26
|
|
28
27
|
# Wrap in HashWithIndifferentAccess
|
@@ -5,27 +5,27 @@ require "spec_helper"
|
|
5
5
|
RSpec.describe "RakeOptions Integration Tests" do
|
6
6
|
describe "Full CLI parsing workflow" do
|
7
7
|
let(:config) do
|
8
|
-
|
9
|
-
"with-mysql-lib"
|
10
|
-
"enable-feature"
|
11
|
-
"port"
|
12
|
-
|
8
|
+
[
|
9
|
+
["with-mysql-lib", :string],
|
10
|
+
["enable-feature", :string],
|
11
|
+
["port", :integer]
|
12
|
+
]
|
13
13
|
end
|
14
14
|
|
15
15
|
it "parses multiple CLI arguments in one invocation" do
|
16
16
|
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib", "--enable-feature=caching", "--port=3000"])
|
17
17
|
|
18
|
-
result = RakeOptions.command_line_args(config
|
18
|
+
result = RakeOptions.command_line_args(config)
|
19
19
|
|
20
20
|
expect(result["with-mysql-lib"]).to eq("/usr/local/lib")
|
21
21
|
expect(result["enable-feature"]).to eq("caching")
|
22
|
-
expect(result["port"]).to eq(
|
22
|
+
expect(result["port"]).to eq(3000)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "handles partial arguments gracefully" do
|
26
26
|
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib"])
|
27
27
|
|
28
|
-
result = RakeOptions.command_line_args(config
|
28
|
+
result = RakeOptions.command_line_args(config)
|
29
29
|
|
30
30
|
expect(result["with-mysql-lib"]).to eq("/usr/local/lib")
|
31
31
|
expect(result["enable-feature"]).to be_nil
|
@@ -35,7 +35,7 @@ RSpec.describe "RakeOptions Integration Tests" do
|
|
35
35
|
it "supports quoted values with spaces" do
|
36
36
|
stub_const("ARGV", ['--with-mysql-lib="/path/with spaces/lib"'])
|
37
37
|
|
38
|
-
result = RakeOptions.command_line_args(config
|
38
|
+
result = RakeOptions.command_line_args(config)
|
39
39
|
|
40
40
|
expect(result["with-mysql-lib"]).to eq("/path/with spaces/lib")
|
41
41
|
end
|
@@ -43,50 +43,13 @@ RSpec.describe "RakeOptions Integration Tests" do
|
|
43
43
|
it "allows symbol key access" do
|
44
44
|
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib"])
|
45
45
|
|
46
|
-
result = RakeOptions.command_line_args(config
|
46
|
+
result = RakeOptions.command_line_args(config)
|
47
47
|
|
48
48
|
expect(result[:with_mysql_lib]).to eq("/usr/local/lib")
|
49
49
|
expect(result["with-mysql-lib"]).to eq("/usr/local/lib")
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe "Full bracket parsing workflow" do
|
54
|
-
let(:config) do
|
55
|
-
{
|
56
|
-
"environment" => "[environment=$env]",
|
57
|
-
"region" => "[region=$reg]",
|
58
|
-
"instance-type" => "[instance-type=$type]"
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
it "parses multiple bracket arguments" do
|
63
|
-
stub_const("ARGV", ["[environment=production]", "[region=us-west-2]", "[instance-type=t2.micro]"])
|
64
|
-
|
65
|
-
result = RakeOptions.command_line_args(config, notation: :bracket)
|
66
|
-
|
67
|
-
expect(result["environment"]).to eq("production")
|
68
|
-
expect(result["region"]).to eq("us-west-2")
|
69
|
-
expect(result["instance-type"]).to eq("t2.micro")
|
70
|
-
end
|
71
|
-
|
72
|
-
it "handles quoted bracket values" do
|
73
|
-
stub_const("ARGV", ['[environment="staging environment"]'])
|
74
|
-
|
75
|
-
result = RakeOptions.command_line_args(config, notation: :bracket)
|
76
|
-
|
77
|
-
expect(result["environment"]).to eq("staging environment")
|
78
|
-
end
|
79
|
-
|
80
|
-
it "supports symbol key access with dashes/underscores" do
|
81
|
-
stub_const("ARGV", ["[instance-type=t2.micro]"])
|
82
|
-
|
83
|
-
result = RakeOptions.command_line_args(config, notation: :bracket)
|
84
|
-
|
85
|
-
expect(result[:instance_type]).to eq("t2.micro")
|
86
|
-
expect(result["instance-type"]).to eq("t2.micro")
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
53
|
describe "Help display integration" do
|
91
54
|
let(:config) do
|
92
55
|
{
|
@@ -134,27 +97,25 @@ RSpec.describe "RakeOptions Integration Tests" do
|
|
134
97
|
|
135
98
|
describe "Mixed scenarios" do
|
136
99
|
let(:config) do
|
137
|
-
|
138
|
-
"database"
|
139
|
-
"verbose"
|
140
|
-
|
100
|
+
[
|
101
|
+
["database", :string],
|
102
|
+
["verbose", :string]
|
103
|
+
]
|
141
104
|
end
|
142
105
|
|
143
|
-
it "handles
|
144
|
-
stub_const("ARGV", ["--
|
106
|
+
it "handles multiple arguments" do
|
107
|
+
stub_const("ARGV", ["--database=mydb", "--verbose=debug"])
|
145
108
|
|
146
|
-
result = RakeOptions.command_line_args(config
|
109
|
+
result = RakeOptions.command_line_args(config)
|
147
110
|
|
148
|
-
expect(result["database"]).to
|
149
|
-
expect(result["database"]["file"]).to eq("database.yml")
|
150
|
-
expect(result["database"]["environment"]).to eq("production")
|
111
|
+
expect(result["database"]).to eq("mydb")
|
151
112
|
expect(result["verbose"]).to eq("debug")
|
152
113
|
end
|
153
114
|
|
154
115
|
it "handles empty ARGV" do
|
155
116
|
stub_const("ARGV", [])
|
156
117
|
|
157
|
-
result = RakeOptions.command_line_args(config
|
118
|
+
result = RakeOptions.command_line_args(config)
|
158
119
|
|
159
120
|
expect(result["database"]).to be_nil
|
160
121
|
expect(result["verbose"]).to be_nil
|
@@ -163,48 +124,28 @@ RSpec.describe "RakeOptions Integration Tests" do
|
|
163
124
|
it "ignores unrecognized arguments" do
|
164
125
|
stub_const("ARGV", ["--unknown-flag=value", "--verbose=info"])
|
165
126
|
|
166
|
-
result = RakeOptions.command_line_args(config
|
127
|
+
result = RakeOptions.command_line_args(config)
|
167
128
|
|
168
129
|
expect(result["verbose"]).to eq("info")
|
169
130
|
expect(result["database"]).to be_nil
|
170
131
|
end
|
171
132
|
end
|
172
133
|
|
173
|
-
describe "Error scenarios" do
|
174
|
-
let(:config) do
|
175
|
-
{
|
176
|
-
"option" => "--option $value"
|
177
|
-
}
|
178
|
-
end
|
179
|
-
|
180
|
-
it "raises InvalidNotationError for unsupported notation" do
|
181
|
-
stub_const("ARGV", ["--option=value"])
|
182
|
-
|
183
|
-
expect { RakeOptions.command_line_args(config, notation: :invalid) }
|
184
|
-
.to raise_error(RakeOptions::InvalidNotationError, /Invalid notation/)
|
185
|
-
end
|
186
134
|
|
187
|
-
it "provides clear error message with supported notations" do
|
188
|
-
stub_const("ARGV", ["--option=value"])
|
189
|
-
|
190
|
-
expect { RakeOptions.command_line_args(config, notation: :xml) }
|
191
|
-
.to raise_error(RakeOptions::InvalidNotationError, /:cli, :bracket/)
|
192
|
-
end
|
193
|
-
end
|
194
135
|
|
195
136
|
describe "Real-world usage scenarios" do
|
196
137
|
context "deployment task" do
|
197
138
|
let(:deploy_config) do
|
198
|
-
|
199
|
-
"environment"
|
200
|
-
"region"
|
201
|
-
"version"
|
202
|
-
"dry-run"
|
203
|
-
|
139
|
+
[
|
140
|
+
["environment", :string],
|
141
|
+
["region", :string],
|
142
|
+
["version", :string],
|
143
|
+
["dry-run", :boolean]
|
144
|
+
]
|
204
145
|
end
|
205
146
|
|
206
147
|
it "handles typical deployment command" do
|
207
|
-
stub_const("ARGV", ["--
|
148
|
+
stub_const("ARGV", ["--environment=production", "--region=us-east-1", "--version=v1.2.3"])
|
208
149
|
|
209
150
|
result = RakeOptions.command_line_args(deploy_config)
|
210
151
|
|
@@ -217,17 +158,17 @@ RSpec.describe "RakeOptions Integration Tests" do
|
|
217
158
|
|
218
159
|
context "build task" do
|
219
160
|
let(:build_config) do
|
220
|
-
|
221
|
-
"with-mysql"
|
222
|
-
"with-ssl"
|
223
|
-
"prefix"
|
224
|
-
|
161
|
+
[
|
162
|
+
["with-mysql", :string],
|
163
|
+
["with-ssl", :string],
|
164
|
+
["prefix", :string]
|
165
|
+
]
|
225
166
|
end
|
226
167
|
|
227
168
|
it "handles build configuration" do
|
228
169
|
stub_const("ARGV", [
|
229
|
-
"--with-mysql
|
230
|
-
"--with-ssl
|
170
|
+
"--with-mysql=/usr/local/mysql/lib",
|
171
|
+
"--with-ssl=/usr/local/ssl/lib",
|
231
172
|
"--prefix=/opt/myapp"
|
232
173
|
])
|
233
174
|
|
@@ -7,9 +7,7 @@ RSpec.describe RakeOptions::CLIParser do
|
|
7
7
|
describe "#parse" do
|
8
8
|
context "with single flag" do
|
9
9
|
let(:config) do
|
10
|
-
|
11
|
-
"with-mysql-lib" => "--with-mysql-lib $path"
|
12
|
-
}
|
10
|
+
[["with-mysql-lib", :string]]
|
13
11
|
end
|
14
12
|
let(:parser) { described_class.new(config) }
|
15
13
|
|
@@ -30,10 +28,7 @@ RSpec.describe RakeOptions::CLIParser do
|
|
30
28
|
|
31
29
|
context "with multiple flags" do
|
32
30
|
let(:config) do
|
33
|
-
|
34
|
-
"with-mysql-lib" => "--with-mysql-lib $path",
|
35
|
-
"enable-feature" => "--enable-feature $name"
|
36
|
-
}
|
31
|
+
[["with-mysql-lib", :string], ["enable-feature", :string]]
|
37
32
|
end
|
38
33
|
let(:parser) { described_class.new(config) }
|
39
34
|
|
@@ -56,9 +51,7 @@ RSpec.describe RakeOptions::CLIParser do
|
|
56
51
|
|
57
52
|
context "with quoted values" do
|
58
53
|
let(:config) do
|
59
|
-
|
60
|
-
"message" => "--message $text"
|
61
|
-
}
|
54
|
+
[["message", :string]]
|
62
55
|
end
|
63
56
|
let(:parser) { described_class.new(config) }
|
64
57
|
|
@@ -72,9 +65,7 @@ RSpec.describe RakeOptions::CLIParser do
|
|
72
65
|
|
73
66
|
context "with unknown flags" do
|
74
67
|
let(:config) do
|
75
|
-
|
76
|
-
"known-flag" => "--known-flag $value"
|
77
|
-
}
|
68
|
+
[["known-flag", :string]]
|
78
69
|
end
|
79
70
|
let(:parser) { described_class.new(config) }
|
80
71
|
|
@@ -87,21 +78,34 @@ RSpec.describe RakeOptions::CLIParser do
|
|
87
78
|
end
|
88
79
|
end
|
89
80
|
|
90
|
-
context "with
|
81
|
+
context "with type casting" do
|
91
82
|
let(:config) do
|
92
|
-
|
93
|
-
"database" => "--config $file --env $environment"
|
94
|
-
}
|
83
|
+
[["port", :integer], ["enabled", :boolean], ["ratio", :float]]
|
95
84
|
end
|
96
85
|
let(:parser) { described_class.new(config) }
|
97
86
|
|
98
|
-
it "
|
99
|
-
argv = ["--
|
87
|
+
it "casts integer values" do
|
88
|
+
argv = ["--port=3000"]
|
100
89
|
result = parser.parse(argv)
|
101
90
|
|
102
|
-
expect(result["
|
103
|
-
expect(result["
|
104
|
-
|
91
|
+
expect(result["port"]).to eq(3000)
|
92
|
+
expect(result["port"]).to be_a(Integer)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "casts boolean values" do
|
96
|
+
argv = ["--enabled=true"]
|
97
|
+
result = parser.parse(argv)
|
98
|
+
|
99
|
+
expect(result["enabled"]).to eq(true)
|
100
|
+
expect(result["enabled"]).to be_a(TrueClass)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "casts float values" do
|
104
|
+
argv = ["--ratio=1.5"]
|
105
|
+
result = parser.parse(argv)
|
106
|
+
|
107
|
+
expect(result["ratio"]).to eq(1.5)
|
108
|
+
expect(result["ratio"]).to be_a(Float)
|
105
109
|
end
|
106
110
|
end
|
107
111
|
end
|
@@ -6,10 +6,7 @@ require "rake_options/help_generator"
|
|
6
6
|
RSpec.describe RakeOptions::HelpGenerator do
|
7
7
|
describe "#display_and_exit" do
|
8
8
|
let(:config) do
|
9
|
-
|
10
|
-
"with-mysql-lib" => "--with-mysql-lib $path",
|
11
|
-
"enable-feature" => "--enable-feature $name"
|
12
|
-
}
|
9
|
+
[["with-mysql-lib", :string], ["enable-feature", :string]]
|
13
10
|
end
|
14
11
|
|
15
12
|
context "with custom README" do
|
@@ -46,10 +43,7 @@ RSpec.describe RakeOptions::HelpGenerator do
|
|
46
43
|
|
47
44
|
describe "#generate_help_text" do
|
48
45
|
let(:config) do
|
49
|
-
|
50
|
-
"option1" => "--option1 $value",
|
51
|
-
"option2" => "--option2 $value"
|
52
|
-
}
|
46
|
+
[["option1", :string], ["option2", :string]]
|
53
47
|
end
|
54
48
|
|
55
49
|
context "with custom README" do
|
@@ -75,12 +69,12 @@ RSpec.describe RakeOptions::HelpGenerator do
|
|
75
69
|
end
|
76
70
|
|
77
71
|
describe "#format_option" do
|
78
|
-
let(:generator) { described_class.new(
|
72
|
+
let(:generator) { described_class.new([]) }
|
79
73
|
|
80
|
-
it "formats option with key and
|
81
|
-
formatted = generator.send(:format_option, "my-option",
|
82
|
-
expect(formatted).to include("--my-option
|
83
|
-
expect(formatted).to include("
|
74
|
+
it "formats option with key and type" do
|
75
|
+
formatted = generator.send(:format_option, "my-option", :string)
|
76
|
+
expect(formatted).to include("--my-option")
|
77
|
+
expect(formatted).to include("string")
|
84
78
|
end
|
85
79
|
end
|
86
80
|
end
|
data/spec/rake_options_spec.rb
CHANGED
@@ -4,44 +4,31 @@ require "spec_helper"
|
|
4
4
|
|
5
5
|
RSpec.describe RakeOptions do
|
6
6
|
let(:config) do
|
7
|
-
|
8
|
-
"with-mysql-lib" => "--with-mysql-lib $path",
|
9
|
-
"enable-feature" => "--enable-feature $name"
|
10
|
-
}
|
7
|
+
[["with-mysql-lib", :string], ["enable-feature", :string]]
|
11
8
|
end
|
12
9
|
|
13
10
|
describe ".command_line_args" do
|
14
|
-
context "
|
11
|
+
context "parsing arguments" do
|
15
12
|
it "parses CLI-style arguments" do
|
16
13
|
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib"])
|
17
|
-
result = described_class.command_line_args(config
|
14
|
+
result = described_class.command_line_args(config)
|
18
15
|
|
19
16
|
expect(result["with-mysql-lib"]).to eq("/usr/local/lib")
|
20
17
|
end
|
21
18
|
|
22
19
|
it "supports symbol key access" do
|
23
20
|
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib"])
|
24
|
-
result = described_class.command_line_args(config
|
21
|
+
result = described_class.command_line_args(config)
|
25
22
|
|
26
23
|
expect(result[:with_mysql_lib]).to eq("/usr/local/lib")
|
27
24
|
end
|
28
|
-
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
stub_const("ARGV", ["[with-mysql-lib=/usr/local/lib]"])
|
33
|
-
result = described_class.command_line_args(config, notation: :bracket)
|
34
|
-
|
35
|
-
expect(result["with-mysql-lib"]).to eq("/usr/local/lib")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context "with default notation" do
|
40
|
-
it "defaults to CLI notation" do
|
41
|
-
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib"])
|
26
|
+
it "parses multiple arguments" do
|
27
|
+
stub_const("ARGV", ["--with-mysql-lib=/usr/local/lib", "--enable-feature=caching"])
|
42
28
|
result = described_class.command_line_args(config)
|
43
29
|
|
44
30
|
expect(result["with-mysql-lib"]).to eq("/usr/local/lib")
|
31
|
+
expect(result["enable-feature"]).to eq("caching")
|
45
32
|
end
|
46
33
|
end
|
47
34
|
|
@@ -66,6 +53,10 @@ RSpec.describe RakeOptions do
|
|
66
53
|
end
|
67
54
|
|
68
55
|
describe ".initialize_readme" do
|
56
|
+
let(:simple_config) do
|
57
|
+
[["option", :string]]
|
58
|
+
end
|
59
|
+
|
69
60
|
it "stores readme content" do
|
70
61
|
readme = "Custom help text"
|
71
62
|
described_class.initialize_readme(readme)
|
@@ -78,7 +69,7 @@ RSpec.describe RakeOptions do
|
|
78
69
|
described_class.initialize_readme(readme)
|
79
70
|
stub_const("ARGV", ["--help"])
|
80
71
|
|
81
|
-
expect { described_class.command_line_args(
|
72
|
+
expect { described_class.command_line_args(simple_config) }
|
82
73
|
.to output(/My Custom Help/).to_stdout
|
83
74
|
.and raise_error(SystemExit)
|
84
75
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rake_options
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Randy Villanueva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-10-
|
11
|
+
date: 2025-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -51,8 +51,6 @@ files:
|
|
51
51
|
- README.md
|
52
52
|
- Rakefile
|
53
53
|
- lib/rake_options.rb
|
54
|
-
- lib/rake_options/argument_parser.rb
|
55
|
-
- lib/rake_options/bracket_parser.rb
|
56
54
|
- lib/rake_options/cli_parser.rb
|
57
55
|
- lib/rake_options/errors.rb
|
58
56
|
- lib/rake_options/hash_with_indifferent_access.rb
|
@@ -60,8 +58,6 @@ files:
|
|
60
58
|
- lib/rake_options/template_engine.rb
|
61
59
|
- lib/rake_options/version.rb
|
62
60
|
- spec/integration/rake_options_integration_spec.rb
|
63
|
-
- spec/rake_options/argument_parser_spec.rb
|
64
|
-
- spec/rake_options/bracket_parser_spec.rb
|
65
61
|
- spec/rake_options/cli_parser_spec.rb
|
66
62
|
- spec/rake_options/help_generator_spec.rb
|
67
63
|
- spec/rake_options/template_engine_spec.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "cli_parser"
|
4
|
-
require_relative "bracket_parser"
|
5
|
-
require_relative "errors"
|
6
|
-
|
7
|
-
module RakeOptions
|
8
|
-
class ArgumentParser
|
9
|
-
VALID_NOTATIONS = [:cli, :bracket].freeze
|
10
|
-
|
11
|
-
def initialize(config, notation)
|
12
|
-
@config = config
|
13
|
-
@notation = notation
|
14
|
-
validate_notation
|
15
|
-
end
|
16
|
-
|
17
|
-
# Parse ARGV and return structured options
|
18
|
-
# @return [Hash] Parsed options
|
19
|
-
def parse
|
20
|
-
parser = select_parser
|
21
|
-
parser.parse
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
# Select appropriate parser based on notation
|
27
|
-
# @return [CLIParser, BracketParser] Parser instance
|
28
|
-
def select_parser
|
29
|
-
case @notation
|
30
|
-
when :cli
|
31
|
-
CLIParser.new(@config)
|
32
|
-
when :bracket
|
33
|
-
BracketParser.new(@config)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# Validate notation parameter
|
38
|
-
# @raise [InvalidNotationError] if notation is invalid
|
39
|
-
def validate_notation
|
40
|
-
return if VALID_NOTATIONS.include?(@notation)
|
41
|
-
|
42
|
-
raise InvalidNotationError,
|
43
|
-
"Invalid notation ':#{@notation}'. Supported notations: #{VALID_NOTATIONS.map { |n| ":#{n}" }.join(', ')}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RakeOptions
|
4
|
-
class BracketParser
|
5
|
-
def initialize(config)
|
6
|
-
@config = config
|
7
|
-
end
|
8
|
-
|
9
|
-
# Parse bracket-style arguments from ARGV
|
10
|
-
# @param argv [Array] Command line arguments (defaults to ARGV)
|
11
|
-
# @return [Hash] Parsed values
|
12
|
-
def parse(argv = ARGV)
|
13
|
-
result = {}
|
14
|
-
|
15
|
-
# Extract all bracket arguments from argv
|
16
|
-
bracket_args = extract_bracket_args(argv)
|
17
|
-
|
18
|
-
# Match bracket args to config keys
|
19
|
-
@config.each do |key, _template|
|
20
|
-
# Look for matching bracket key
|
21
|
-
if bracket_args.key?(key)
|
22
|
-
result[key] = bracket_args[key]
|
23
|
-
else
|
24
|
-
result[key] = nil
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
result
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
# Find all [key=value] patterns in argv
|
34
|
-
# @param argv [Array] Command line arguments
|
35
|
-
# @return [Hash] Extracted key-value pairs
|
36
|
-
def extract_bracket_args(argv)
|
37
|
-
result = {}
|
38
|
-
|
39
|
-
argv.each do |arg|
|
40
|
-
# Match [key=value] or [key="value"]
|
41
|
-
match = arg.match(/^\[([^=]+)=(.+)\]$/)
|
42
|
-
next unless match
|
43
|
-
|
44
|
-
key = match[1]
|
45
|
-
value = parse_bracket_value(match[2])
|
46
|
-
result[key] = value
|
47
|
-
end
|
48
|
-
|
49
|
-
result
|
50
|
-
end
|
51
|
-
|
52
|
-
# Handle quoted and unquoted values in brackets
|
53
|
-
# @param value [String] Value from bracket
|
54
|
-
# @return [String] Parsed value
|
55
|
-
def parse_bracket_value(value)
|
56
|
-
# Remove surrounding quotes if present
|
57
|
-
if value.start_with?('"') && value.end_with?('"')
|
58
|
-
value[1..-2]
|
59
|
-
else
|
60
|
-
value
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
require "rake_options/argument_parser"
|
5
|
-
|
6
|
-
RSpec.describe RakeOptions::ArgumentParser do
|
7
|
-
let(:config) do
|
8
|
-
{
|
9
|
-
"option1" => "--option1 $value"
|
10
|
-
}
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "#initialize" do
|
14
|
-
context "with valid notation" do
|
15
|
-
it "accepts :cli notation" do
|
16
|
-
expect { described_class.new(config, :cli) }.not_to raise_error
|
17
|
-
end
|
18
|
-
|
19
|
-
it "accepts :bracket notation" do
|
20
|
-
expect { described_class.new(config, :bracket) }.not_to raise_error
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context "with invalid notation" do
|
25
|
-
it "raises InvalidNotationError" do
|
26
|
-
expect { described_class.new(config, :invalid) }.to raise_error(RakeOptions::InvalidNotationError)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "provides helpful error message" do
|
30
|
-
expect { described_class.new(config, :invalid) }.to raise_error(
|
31
|
-
RakeOptions::InvalidNotationError,
|
32
|
-
/Invalid notation ':invalid'. Supported notations: :cli, :bracket/
|
33
|
-
)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "#parse" do
|
39
|
-
context "with CLI notation" do
|
40
|
-
let(:parser) { described_class.new(config, :cli) }
|
41
|
-
|
42
|
-
it "uses CLIParser" do
|
43
|
-
expect(RakeOptions::CLIParser).to receive(:new).with(config).and_call_original
|
44
|
-
parser.parse
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context "with bracket notation" do
|
49
|
-
let(:parser) { described_class.new(config, :bracket) }
|
50
|
-
|
51
|
-
it "uses BracketParser" do
|
52
|
-
expect(RakeOptions::BracketParser).to receive(:new).with(config).and_call_original
|
53
|
-
parser.parse
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "#select_parser" do
|
59
|
-
it "returns CLIParser for :cli notation" do
|
60
|
-
parser = described_class.new(config, :cli)
|
61
|
-
selected = parser.send(:select_parser)
|
62
|
-
expect(selected).to be_a(RakeOptions::CLIParser)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "returns BracketParser for :bracket notation" do
|
66
|
-
parser = described_class.new(config, :bracket)
|
67
|
-
selected = parser.send(:select_parser)
|
68
|
-
expect(selected).to be_a(RakeOptions::BracketParser)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
require "rake_options/bracket_parser"
|
5
|
-
|
6
|
-
RSpec.describe RakeOptions::BracketParser do
|
7
|
-
describe "#parse" do
|
8
|
-
context "with simple key=value" do
|
9
|
-
let(:config) do
|
10
|
-
{
|
11
|
-
"environment" => "[environment=$env]",
|
12
|
-
"region" => "[region=$region]"
|
13
|
-
}
|
14
|
-
end
|
15
|
-
let(:parser) { described_class.new(config) }
|
16
|
-
|
17
|
-
it "parses [key=value] format" do
|
18
|
-
argv = ["[environment=production]", "[region=us-west-2]"]
|
19
|
-
result = parser.parse(argv)
|
20
|
-
|
21
|
-
expect(result["environment"]).to eq("production")
|
22
|
-
expect(result["region"]).to eq("us-west-2")
|
23
|
-
end
|
24
|
-
|
25
|
-
it "returns nil for missing arguments" do
|
26
|
-
argv = ["[environment=production]"]
|
27
|
-
result = parser.parse(argv)
|
28
|
-
|
29
|
-
expect(result["environment"]).to eq("production")
|
30
|
-
expect(result["region"]).to be_nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "with quoted values" do
|
35
|
-
let(:config) do
|
36
|
-
{
|
37
|
-
"message" => "[message=$text]"
|
38
|
-
}
|
39
|
-
end
|
40
|
-
let(:parser) { described_class.new(config) }
|
41
|
-
|
42
|
-
it "parses [key=\"value with spaces\"] format" do
|
43
|
-
argv = ['[message="Hello World"]']
|
44
|
-
result = parser.parse(argv)
|
45
|
-
|
46
|
-
expect(result["message"]).to eq("Hello World")
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "with multiple bracket arguments" do
|
51
|
-
let(:config) do
|
52
|
-
{
|
53
|
-
"env" => "[env=$environment]",
|
54
|
-
"region" => "[region=$reg]",
|
55
|
-
"instance" => "[instance=$type]"
|
56
|
-
}
|
57
|
-
end
|
58
|
-
let(:parser) { described_class.new(config) }
|
59
|
-
|
60
|
-
it "parses multiple bracket arguments" do
|
61
|
-
argv = ["[env=prod]", "[region=us-east-1]", "[instance=t2.micro]"]
|
62
|
-
result = parser.parse(argv)
|
63
|
-
|
64
|
-
expect(result["env"]).to eq("prod")
|
65
|
-
expect(result["region"]).to eq("us-east-1")
|
66
|
-
expect(result["instance"]).to eq("t2.micro")
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
context "with malformed brackets" do
|
71
|
-
let(:config) do
|
72
|
-
{
|
73
|
-
"valid" => "[valid=$val]"
|
74
|
-
}
|
75
|
-
end
|
76
|
-
let(:parser) { described_class.new(config) }
|
77
|
-
|
78
|
-
it "ignores malformed bracket arguments" do
|
79
|
-
argv = ["[valid=test]", "invalid=value", "[missing-bracket"]
|
80
|
-
result = parser.parse(argv)
|
81
|
-
|
82
|
-
expect(result["valid"]).to eq("test")
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|