argvise 0.0.3 → 0.0.5

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: e50f3f629a6b160ae07376bdade25677509ce0b6bb525e62b06170450bb39ea3
4
- data.tar.gz: a86b5387f5202ce188b1b652643444f206127eb300bd49661f297faeb820253e
3
+ metadata.gz: cc2e3625fabe3294535d920c085b82f1c2718032de5f3921a7a9f74424c1ca5f
4
+ data.tar.gz: 2005628bc2fc53ea8937a310111b4217289051e3c634d5960287ed9e4db4dca0
5
5
  SHA512:
6
- metadata.gz: 0c261cc3a5591aa7947f496dd60e8caa7ecf45f3b0cb85a6a22a786f0450f4763298963fbe883a7dced42618f6281051e2f6c8b3ad53f6773057cc0c4087de1b
7
- data.tar.gz: 124e02d8d29c6b23047bad71b89afc42a78407b1d9e6ec7ca4800c90e8adeacc29989c09b7a83354db4a5b7832d6e809bff88a86950334509ea96a5bfa72502c
6
+ metadata.gz: 1f78e1ea42b3d355ec65da36c69bbf31b7dfa7386c7483ed42c625ef15dc826f052e7009f040a47ef0f685a2f4d26de347edfeeba9c53c09cdb7941bc5b6915a
7
+ data.tar.gz: a9c6c99a0590f822f5dda6782a3a12c664008c8eff472c234f004e9b2fb69033e12dba58d8efd6c9bb77ec449cc97dab121cf875e80535f226f0ec29c3aea45c
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1
data/argvise.gemspec ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/argvise/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'argvise'
7
+ # spec.version = '0.0.1'
8
+ spec.version = Argvise::VERSION
9
+ spec.authors = ['2moe']
10
+ spec.email = ['m@tmoe.me']
11
+
12
+ spec.summary = 'Turns a hash into CLI arguments'
13
+ spec.description = 'Provides flexible command-line argument generation with support for complex data structures'
14
+ spec.license = 'Apache-2.0'
15
+ # spec.extra_rdoc_files = ['docs/rdoc/Readme.rdoc']
16
+ spec.required_ruby_version = '>= 3.1.0'
17
+ # spec.metadata['allowed_push_host'] = "TODO: Set to your gem server 'https://example.com'"
18
+
19
+ spec.homepage = 'https://github.com/2moe/argvise-gem'
20
+ spec.metadata['homepage_uri'] = spec.homepage
21
+ # spec.metadata['source_code_uri'] = spec.homepage
22
+ # spec.metadata['changelog_uri'] = "TODO: Put your gem's CHANGELOG.md URL here."
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ # gemspec = File.basename(__FILE__)
27
+ spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
28
+ ls.readlines("\x0", chomp: true).reject do |f|
29
+ # (f == gemspec) ||
30
+ f.start_with?(
31
+ # bin/ test/ Gemfile Rakefile assets docs/Readme-zh-
32
+ *%w[
33
+ spec/ features/ .git .github appveyor
34
+ ]
35
+ )
36
+ end
37
+ end
38
+ # spec.bindir = 'exe'
39
+ # spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
40
+ spec.require_paths = ['lib']
41
+
42
+ # Uncomment to register a new dependency of your gem
43
+ # spec.add_dependency "example-gem", "~> 1.0"
44
+
45
+ # For more information and examples about making a new gem, check out our
46
+ # guide at: https://bundler.io/guides/creating_gem.html
47
+ end
data/bin/build.rb ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # typed: ignore
3
+ # frozen_string_literal: true
4
+
5
+ require 'pathname'
6
+
7
+ Pathname(__dir__ || File.dirname(__FILE__))
8
+ .parent
9
+ .then { Dir.chdir(it) }
10
+
11
+ proj = 'argvise'
12
+
13
+ system <<~CMD
14
+ gem uninstall #{proj}
15
+ gem build #{proj}
16
+ gem install #{proj}
17
+ CMD
18
+
19
+ # gem push argvise-*.gem
data/bin/console.rb ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # lib_path = File.expand_path('../lib', __dir__)
5
+ # exec "irb -I #{lib_path} -r argvise"
6
+
7
+ require 'irb'
8
+ require_relative '../lib/argvise'
9
+
10
+ puts "Argvise: #{Argvise::VERSION}"
11
+
12
+ def puts_division_line
13
+ puts
14
+ puts '-' * 80
15
+ end
16
+
17
+ raw_cmd = {
18
+ compiler: nil,
19
+ build: nil,
20
+ pack_type: 'tar+zstd',
21
+ push: true,
22
+ v: true,
23
+ f: 'p2',
24
+ tag: ['v0.0.1', 'beta'],
25
+ platform: 'wasi/wasm',
26
+ label: {
27
+ maintainer: 'user',
28
+ description: 'Demo'
29
+ },
30
+ "/path/to/dir": nil
31
+ }
32
+
33
+ puts 'GNU-style + kebab_case_flags(false)'
34
+ raw_cmd
35
+ .then(&Argvise.new_proc)
36
+ .with_bsd_style(false)
37
+ .with_kebab_case_flags(false)
38
+ .build
39
+ .display
40
+
41
+ puts_division_line
42
+ # -----------
43
+
44
+ puts 'GNU-style + kebab_case_flags(true)'
45
+ raw_cmd
46
+ .then(&hash_to_argv)
47
+ .display
48
+
49
+ puts_division_line
50
+ # -----------
51
+
52
+ puts 'BSD-style + kebab_case_flags(true)'
53
+ raw_cmd
54
+ .then(&Argvise.new_proc)
55
+ .with_bsd_style
56
+ .with_kebab_case_flags
57
+ .build
58
+ .display
59
+
60
+ puts_division_line
61
+ # -----------
62
+
63
+ IRB.start
data/docs/Readme.md CHANGED
@@ -2,40 +2,153 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/argvise.svg?icon=si%3Arubygems)](https://rubygems.org/gems/argvise)
4
4
 
5
+ <!-- [![RubyDoc](https://img.shields.io/badge/-y?label=rubydoc&color=orange)](https://www.rubydoc.info/gems/argvise) -->
6
+
5
7
  A Ruby gem for converting hash structures into command-line argument arrays.
6
8
 
7
9
  > **Note:** This is *not* a command-line parser — quite the opposite. Argvise helps you **build** CLI commands programmatically.
8
10
 
11
+ ## Quick Start
12
+
13
+ ```ruby
14
+ # IRB
15
+ system "gem install argvise"
16
+ ```
17
+
18
+ ```ruby
19
+ # RUBY
20
+ require 'argvise'
21
+
22
+ { cargo: nil, b: nil, r: true, target: "wasm32-wasip2" }
23
+ .then(&hash_to_argv)
24
+
25
+ #=> ["cargo", "b", "-r", "--target", "wasm32-wasip2"]
26
+ ```
27
+
28
+ `raw_cmd_hash.then(&hash_to_argv)` is equivalent to:
29
+
30
+ ```ruby
31
+ { cargo: nil, b: nil, r: true, target: "wasm32-wasip2" }
32
+ .then(&Argvise.new_proc)
33
+ .with_bsd_style(false) #=> GNU style
34
+ .with_kebab_case_flags(true) #=> replace "--cli_flag" with "--cli-flag"
35
+ .build
36
+ ```
37
+
9
38
  ## Installation
10
39
 
11
40
  Add this line to your application's Gemfile:
12
41
 
13
42
  ```ruby
43
+ # Gemfile
44
+ #
14
45
  gem 'argvise'
15
46
  ```
16
47
 
17
48
  And then execute:
18
49
 
19
- ```bash
50
+ ```sh
51
+ # SHELL
52
+ #
20
53
  bundler install
21
54
  ```
22
55
 
23
56
  Or install it directly:
24
57
 
25
- ```bash
58
+ ```sh
59
+ # SHELL
60
+ #
26
61
  gem install argvise
27
62
  ```
28
63
 
29
- ## Usage
64
+ ## Conversion Rules
65
+
66
+ ### Common
67
+
68
+ | Hash Format | Result |
69
+ | ----------------------- | ---------------------------- |
70
+ | `{ "-k2": nil }` | `["-k2"]` |
71
+ | `{ "--r_a-w_": nil }` | `["--r_a-w_"]` |
72
+ | `{ key: nil }` | `["key"]` |
73
+ | `{ key: [] }` | `[]` |
74
+ | `{ key: {} }` | `[]` |
75
+ | `{ key: false }` | `[]` |
76
+ | `{ k: true }` | `["-k"]` |
77
+ | `{ k: "value" }` | `["-k", "value"]` |
78
+ | `{ k: ["a", "b"] }` | `["-k", "a", "-k", "b"]` |
79
+ | `{ k: { a: 1, b: 2 } }` | `["-k", "a=1", "-k", "b=2"]` |
80
+
81
+
82
+ ### GNU Style
83
+
84
+ | Hash Format | Result |
85
+ | ------------------------- | ---------------------------------- |
86
+ | `{ key: true }` | `["--key"]` |
87
+ | `{ key: "value" }` | `["--key", "value"]` |
88
+ | `{ key: ["a", "b"] }` | `["--key", "a", "--key", "b"]` |
89
+ | `{ key: { a: 1, b: 2 } }` | `["--key", "a=1", "--key", "b=2"]` |
90
+
91
+ ---
92
+
93
+ #### `with_kebab_case_flags(true)`:
94
+
95
+ | Hash Format | Result |
96
+ | ----------------- | ------------- |
97
+ | `{ key_a: true }` | `["--key-a"]` |
98
+
99
+ ---
100
+
101
+ #### `with_kebab_case_flags(false)`:
102
+
103
+ | Hash Format | Result |
104
+ | ----------------- | ------------- |
105
+ | `{ key_b: true }` | `["--key_b"]` |
106
+
107
+
108
+ ### BSD Style
30
109
 
31
- ### Basic Conversion
110
+ | Hash Format | Result |
111
+ | ------------------------- | -------------------------------- |
112
+ | `{ key: true }` | `["-key"]` |
113
+ | `{ key: "value" }` | `["-key", "value"]` |
114
+ | `{ key: ["a", "b"] }` | `["-key", "a", "-key", "b"]` |
115
+ | `{ key: { a: 1, b: 2 } }` | `["-key", "a=1", "-key", "b=2"]` |
116
+
117
+ ---
118
+
119
+ #### `with_kebab_case_flags(true)`:
120
+
121
+ | Hash Format | Result |
122
+ | ----------------- | ------------ |
123
+ | `{ key_c: true }` | `["-key-c"]` |
124
+
125
+ ---
126
+
127
+ #### `with_kebab_case_flags(false)`:
128
+
129
+ | Hash Format | Result |
130
+ | ----------------- | ------------ |
131
+ | `{ key_d: true }` | `["-key_d"]` |
132
+
133
+
134
+ ### Notes
135
+
136
+ > When the value of a flag key is `nil`, the `kebab_case_flags` option has
137
+ > no effect — i.e., the key will not be transformed.
138
+ >
139
+ > For example, the input `{"a_b-c": nil}` will result in `["a_b-c"]`,
140
+ > and **not** be automatically transformed into `["a-b-c"]`.
141
+
142
+ ## Examples
143
+
144
+ ### Basic Conversion (GNU Style)
32
145
 
33
146
  ```ruby
34
147
  require 'argvise'
35
148
 
36
- options = {
149
+ raw_cmd_hash = {
37
150
  docker: nil, #=> docker
38
- build: nil,
151
+ build: nil,
39
152
  push: true, #=> --push
40
153
  tag: ["ghcr.io/[user]/repo:latest", "ghcr.io/[user]/repo:v0.0.1"], #=> --tag ghcr... --tag ghcr..0.0.1
41
154
  platform: "wasi/wasm", #=> --platform wasi/wasm
@@ -47,12 +160,12 @@ options = {
47
160
  path: nil,
48
161
  }
49
162
 
50
- Argvise.build(options)
163
+ Argvise.build(raw_cmd_hash)
51
164
  # => [
52
- # "docker", "build", "--push",
53
- # "--tag", "ghcr.io/[user]/repo:latest", "--tag", "ghcr.io/[user]/repo:v0.0.1",
54
- # "--platform", "wasi/wasm",
55
- # "--label", "maintainer=user", "--label", "description=A Docker build example",
165
+ # "docker", "build", "--push",
166
+ # "--tag", "ghcr.io/[user]/repo:latest", "--tag", "ghcr.io/[user]/repo:v0.0.1",
167
+ # "--platform", "wasi/wasm",
168
+ # "--label", "maintainer=user", "--label", "description=A Docker build example",
56
169
  # "--file", "wasi.dockerfile", "path"
57
170
  # ]
58
171
  ```
@@ -64,56 +177,113 @@ Argvise.build(options)
64
177
  # => ["-v", "--dir", "/path/to/dir"]
65
178
  ```
66
179
 
67
- ## Supported Data Structures
180
+ ### Configurable builder
68
181
 
69
- ### 1. Simple Flags
182
+ > Required
183
+ > - argvise: >= v0.0.4
184
+ > - ruby: >= v3.1.0
70
185
 
71
186
  ```ruby
72
- { verbose: true }.then(&hash_to_argv) # => ["--verbose"]
187
+ raw_cmd = {
188
+ compiler: nil,
189
+ build: nil,
190
+ pack_type: 'tar+zstd',
191
+ push: true,
192
+ v: true,
193
+ f: 'p2',
194
+ tag: ['v0.0.1', 'beta'],
195
+ platform: 'wasi/wasm',
196
+ label: {
197
+ maintainer: 'user',
198
+ description: 'Demo'
199
+ },
200
+ "/path/to/dir": nil
201
+ }
202
+
203
+ p '----------------'
204
+ p "GNU-style + kebab case flags=false"
205
+ raw_cmd
206
+ .then(&Argvise.new_proc)
207
+ .with_bsd_style(false)
208
+ .with_kebab_case_flags(false)
209
+ .build
210
+ .display
211
+
212
+ #=> ["compiler", "build", "--pack_type", "tar+zstd", "--push", "-v", "-f", "p2", "--tag", "v0.0.1", "--tag", "beta", "--platform", "wasi/wasm", "--label", "maintainer=user", "--label", "description=Demo", "/path/to/dir"]
213
+
214
+ p '----------------'
215
+ p 'GNU-style + kebab-case-flags=true'
216
+ raw_cmd
217
+ .then(&hash_to_argv)
218
+ .display
219
+
220
+ #=> ["compiler", "build", "--pack-type", "tar+zstd", "--push", "-v", "-f", "p2", "--tag", "v0.0.1", "--tag", "beta", "--platform", "wasi/wasm", "--label", "maintainer=user", "--label", "description=Demo", "/path/to/dir"]
221
+
222
+ p '----------------'
223
+ p 'BSD-style + kebab-case-flags=true'
224
+ raw_cmd
225
+ .then(&Argvise.new_proc)
226
+ .with_bsd_style
227
+ .with_kebab_case_flags
228
+ .build
229
+ .display
230
+
231
+ #=> ["compiler", "build", "-pack-type", "tar+zstd", "-push", "-v", "-f", "p2", "-tag", "v0.0.1", "-tag", "beta", "-platform", "wasi/wasm", "-label", "maintainer=user", "-label", "description=Demo", "/path/to/dir"]
73
232
  ```
74
233
 
75
- ### 2. Boolean Values
234
+ ## Data Type
76
235
 
77
- ```ruby
78
- { silent: false }.then(&hash_to_argv) # => []
79
- ```
236
+ ### Boolean
80
237
 
81
- ### 3. Array Values
238
+ #### GNU style
82
239
 
83
- ```ruby
84
- { tag: %w[a b] }.then(&hash_to_argv)
85
- # => ["--tag", "a", "--tag", "b"]
86
- ```
240
+ - `{ verbose: true }` => "--verbose"
241
+ - `{ v: true }` => "-v"
242
+ - `{ v: false }` => no argument generated
87
243
 
88
- ### 4. Hash Values
244
+ #### BSD style
89
245
 
90
- ```ruby
91
- { label: { env: 'test', k2: 'v2' } }.then(&hash_to_argv)
92
- # => ["--label", "env=test", "--label", "k2=v2"]
93
- ```
246
+ - `{ verbose: true }` => "-verbose"
247
+ - `{ v: true }` => "-v"
248
+ - `{ v: false }` => no argument generated
94
249
 
95
- ## API Documentation
250
+ ### String
96
251
 
97
- ### `Argvise.build(options)`
252
+ #### GNU style
98
253
 
99
- Main method to convert hash to command-line arguments array
254
+ - `{ f: "a.txt" }` => `["-f", "a.txt"]`
255
+ - `{ file: "a.txt" }` => `["--file", "a.txt"]`
100
256
 
101
- **Parameters:**
257
+ #### BSD style
102
258
 
103
- - `options` (Hash) - The hash to be converted
259
+ - `{ f: "a.txt" }` => `["-f", "a.txt"]`
260
+ - `{ file: "a.txt" }` => `["-file", "a.txt"]`
104
261
 
105
- **Returns:**
262
+ ### Array
106
263
 
107
- - Array<String> generated command-line arguments
264
+ #### GNU style
108
265
 
109
- ### Conversion Rules
266
+ - `{ t: ["a", "b"] }` => `["-t", "a", "-t", "b"]`
267
+ - `{ tag: %w[a b] }` => `["--tag", "a", "--tag", "b"]`
110
268
 
111
- | Hash Format | Result Example |
112
- | ------------------------- | ---------------------------------- |
113
- | `{ key: nil }` | `["key"]` |
114
- | `{ key: false }` | `[]` |
115
- | `{ key: true }` | `["--key"]` |
116
- | `{ k: true }` | `["-k"]` |
117
- | `{ key: "value" }` | `["--key", "value"]` |
118
- | `{ key: ["a", "b"] }` | `["--key", "a", "--key", "b"]` |
119
- | `{ key: { a: 1, b: 2 } }` | `["--key", "a=1", "--key", "b=2"]` |
269
+ #### BSD style
270
+
271
+ - `{ t: ["a", "b"] }` => `["-t", "a", "-t", "b"]`
272
+ - `{ tag: %w[a b] }` => `["-tag", "a", "-tag", "b"]`
273
+
274
+ ### Hash
275
+
276
+ #### GNU style
277
+
278
+ - `{ e: { profile: 'test', lang: 'C'} }` => `["-e", "profile=test", "-e", "lang=C"]`
279
+ - `{ env: { profile: 'test', lang: 'C'} }` => `["--env", "profile=test", "--env", "lang=C"]`
280
+
281
+ #### BSD style
282
+
283
+ - `{ e: { profile: 'test', lang: 'C'} }` => `["-e", "profile=test", "-e", "lang=C"]`
284
+ - `{ env: { profile: 'test', lang: 'C'} }` => `["-env", "profile=test", "-env", "lang=C"]`
285
+
286
+ ## Nil => Raw
287
+
288
+ - `{ cargo: nil, b: nil}` => `["cargo", "b"]`
289
+ - `{ "-fv": nil}` => `["-fv"]`
@@ -1,5 +1,6 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  class Argvise
4
- VERSION = '0.0.3'
5
+ VERSION = '0.0.5'
5
6
  end
data/lib/argvise.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require_relative 'argvise/version'
data/lib/core.rb CHANGED
@@ -1,32 +1,163 @@
1
+ # rubocop:disable Style/Lambda, Lint/MissingCopEnableDirective
2
+ # typed: true
1
3
  # frozen_string_literal: true
2
4
 
3
- # rubocop:disable Style/Lambda, Lint/MissingCopEnableDirective
4
5
  # ------------------
5
6
  # Converts hash to command array
6
7
  #
7
- # Example
8
- # {cargo: nil, build: nil, v: true, target: "wasm32-wasip2"}.then { Argvise.build _1 }
9
- # # Output => ["cargo", "build", "-v", "--target", "wasm32-wasip2"]
8
+ # == Example
9
+ #
10
+ # { cargo: nil, b: nil, r: true, target: "wasm32-wasip2" }
11
+ # .then(&Argvise.new_proc)
12
+ # .with_bsd_style(false)
13
+ # .build
14
+ # .display
15
+ #
16
+ # #=> ["cargo", "b", "-r", "--target", "wasm32-wasip2"]
17
+ #
18
+ # == Conversion Rules:
19
+ #
20
+ # === GNU Style:
21
+ # - Boolean values:
22
+ # - `{ verbose: true }` => "--verbose"
23
+ # - `{ v: true }` => "-v"
24
+ # - `{ v: false }` => no argument generated
25
+ # - String values:
26
+ # - `{ f: "a.txt" }` => ["-f", "a.txt"]
27
+ # - `{ file: "a.txt" }` => ["--file", "a.txt"]
28
+ # - Array values:
29
+ # - `{ t: ["a", "b"] }` => `["-t", "a", "-t", "b"]`
30
+ # - `{ tag: %w[a b] }` => `["--tag", "a", "--tag", "b"]`
31
+ # - Hash values:
32
+ # - `{ L: { env: 'test' } }` => `["-L", "env=test"]`
33
+ # - `{ label: { env: 'test' } }` => `["--label", "env=test"]`
34
+ #
35
+ # === BSD Style:
36
+ # - Boolean values:
37
+ # - `{ verbose: true }` => "-verbose"
38
+ # - `{ v: true }` => "-v"
39
+ # - `{ v: false }` => no argument generated
40
+ # - String values:
41
+ # - `{ f: "a.txt" }` => ["-f", "a.txt"]
42
+ # - `{ file: "a.txt" }` => ["-file", "a.txt"]
43
+ # - Array values:
44
+ # - `{ t: ["a", "b"] }` => `["-t", "a", "-t", "b"]`
45
+ # - `{ tag: %w[a b] }` => `["-tag", "a", "-tag", "b"]`
46
+ # - Hash values:
47
+ # - `{ L: { env: 'test' } }` => `["-L", "env=test"]`
48
+ # - `{ label: { env: 'test' } }` => `["-label", "env=test"]`
49
+ #
50
+ # === Common:
51
+ # - Raw values:
52
+ # - `{ cargo: nil, b: nil}` => `["cargo", "b"]`
53
+ # - `{ "-fv": nil}` => `["-fv"]`
10
54
  #
11
- # Supported data structures:
12
- # - Simple flags: `{ verbose: true }` => "--verbose"
13
- # - Boolean values: `{ v: false }` => no argument generated
14
- # - Array values: `{ tag: %w[a b] }` => `["--tag", "a", "--tag", "b"]`
15
- # - Hash values: `{ label: { env: 'test' } }` => `["--label", "env=test"]`
55
+ # === About kebab_case_flags:
56
+ # - `with_kebab_case_flags(true)`:
57
+ # - `{enable_jit: true}` =>
58
+ # - GNU-style: `["--enable-jit"]`
59
+ # - BSD-style: `["-enable-jit"]`
60
+ # - `with_kebab_case_flags(false)`:
61
+ # - `{enable_jit: true}` =>
62
+ # - GNU-style: `["--enable_jit"]`
63
+ # - BSD-style: `["-enable_jit"]`
16
64
  class Argvise
17
- # Converts a hash into a command-line argument array
65
+ attr_accessor :bsd_style, :kebab_case_flags
66
+
67
+ # v0.0.3 default options
68
+ DEFAULT_OPTS = { bsd_style: false, kebab_case_flags: true }.freeze
69
+
70
+ class << self
71
+ # Converts a hash into a command-line argument array
72
+ #
73
+ # == Example
74
+ # require 'argvise'
75
+ # cmd = { ruby: nil, r: "argvise", verbose: true, e: true, "puts Argvise::VERSION": nil }
76
+ # opts = { bsd_style: false }
77
+ # Argvise.build(cmd, opts:)
78
+ #
79
+ # == Params
80
+ # - raw_cmd_hash [Hash] The hash to be converted (i.e., raw input data)
81
+ # - opts [Hash] See also: [self.new]
82
+ #
83
+ # == Returns
84
+ # [Array<String>] The generated array of command-line arguments
85
+ def build(
86
+ raw_cmd_hash,
87
+ opts: nil
88
+ )
89
+ opts ||= DEFAULT_OPTS
90
+ new(raw_cmd_hash, opts:).build
91
+ end
92
+
93
+ # Returns a Proc that wraps `Argvise.new`, allowing functional-style chaining.
94
+ #
95
+ # Useful for transforming a hash of CLI arguments into a command array.
96
+ #
97
+ # == Example
98
+ #
99
+ # require 'argvise'
100
+ # { ruby: nil, r: "argvise", e: true, "puts Argvise::VERSION": nil }
101
+ # .then(&Argvise.new_proc)
102
+ # .build
103
+ # .then{system *_1}
104
+ #
105
+ # > See also: [self.new]
106
+ def new_proc
107
+ ->(raw_cmd_hash) do
108
+ new(raw_cmd_hash)
109
+ end
110
+ end
111
+ # ----
112
+ end
113
+
114
+ # == Example
115
+ #
116
+ # require 'argvise'
117
+ # cmd = { ruby: nil, r: "argvise", verbose: true, e: true, "puts Argvise::VERSION": nil }
118
+ # opts = Argvise::DEFAULT_OPTS
119
+ # Argvise.new(cmd, opts:).build.then{system *_1}
18
120
  #
19
- # @param options [Hash] The hash to be converted
20
- # @return [Array<String>] The generated array of command-line arguments
121
+ # == opts
122
+ # [Hash]: { bsd_style: Boolean, kebab_case_flags: Boolean }
21
123
  #
22
- # sig { params(options: Hash).returns(T::Array[String]) }
23
- def self.build(options)
24
- new.build(options)
124
+ # - When `bsd_style` is set to `false`, the builder operates in **GNU-style mode**,
125
+ # which typically uses hyphenated flags.
126
+ #
127
+ # - If `kebab_case_flags` is set to `true`, any underscores (`_`) in flag names
128
+ # will be automatically converted to hyphens (`-`).
129
+ # - For example, a flag like `--enable_jit` will be transformed into `--enable-jit`.
130
+ #
131
+ # When the value of a flag key is `nil`, the `kebab_case_flags` option has no effect
132
+ # — i.e., the key will not be transformed.
133
+ #
134
+ # For example, the input `{"a_b-c": nil}` will result in `["a_b-c"]`,
135
+ # and **not** be automatically transformed into `["a-b-c"]`.
136
+ #
137
+ def initialize(
138
+ raw_cmd_hash,
139
+ opts: nil
140
+ )
141
+ opts = DEFAULT_OPTS.merge(opts || {})
142
+
143
+ @raw_cmd_hash = raw_cmd_hash
144
+ @bsd_style = opts[:bsd_style]
145
+ @kebab_case_flags = opts[:kebab_case_flags]
146
+ end
147
+
148
+ def with_bsd_style(value = true) # rubocop:disable Style/OptionalBooleanParameter
149
+ @bsd_style = value
150
+ self
151
+ end
152
+
153
+ def with_kebab_case_flags(value = true) # rubocop:disable Style/OptionalBooleanParameter
154
+ @kebab_case_flags = value
155
+ self
25
156
  end
26
157
 
27
- def build(options)
28
- # options.each_pair.flat_map { |k, v| process_pair(k.to_s, v) }
29
- options.each_with_object([]) do |(k, v), memo|
158
+ def build
159
+ # @raw_cmd_hash.each_pair.flat_map { |k, v| process_pair(k.to_s, v) }
160
+ @raw_cmd_hash.each_with_object([]) do |(k, v), memo|
30
161
  memo.concat(process_pair(k.to_s, v))
31
162
  end
32
163
  end
@@ -44,13 +175,42 @@ class Argvise
44
175
  generate_args(flag, value)
45
176
  end
46
177
 
47
- # Builds the command-line flag prefix (automatically detects short or long options)
178
+ # Builds the command-line flag prefix (automatically detects short or long raw_cmd_hash)
179
+ #
180
+ # GNU Style:
181
+ # - short key, e.g., {v: true} => "-v"
182
+ # - long key, e.g., {verbose: true} => "--verbose"
183
+ #
184
+ # BSD Style:
185
+ # - short key, e.g., {verbose: true} => "-verbose"
186
+ # - no long key
187
+ #
188
+ # @kebab_case_flags==true:
189
+ # - "_" => "-"
190
+ # - e.g., {enable_jit: true} =>
191
+ # - BSD-style: "-enable-jit"
192
+ # - GNU-style: "--enable-jit"
48
193
  #
49
- # short key, e.g., {v: true} => "-v"
50
- # long key, e.g., {verbose: true} => "--verbose"
51
- def build_flag(key)
52
- prefix = key.length == 1 ? '-' : '--'
53
- "#{prefix}#{key.tr('_', '-')}"
194
+ # @kebab_case_flags==false:
195
+ # - e.g., {enable_jit: true} =>
196
+ # - BSD-style: "-enable_jit"
197
+ # - GNU-style: "--enable_jit"
198
+ def build_flag(key) # rubocop:disable Metrics/MethodLength
199
+ prefix =
200
+ if @bsd_style
201
+ '-'
202
+ else
203
+ key.length == 1 ? '-' : '--'
204
+ end
205
+
206
+ flag =
207
+ if @kebab_case_flags
208
+ key.tr('_', '-')
209
+ else
210
+ key
211
+ end
212
+
213
+ "#{prefix}#{flag}"
54
214
  end
55
215
 
56
216
  # Generates the corresponding argument array based on the value type
@@ -95,12 +255,21 @@ end
95
255
 
96
256
  # A convenient lambda method: converts a hash into command-line arguments
97
257
  #
98
- # Example:
99
- # { v: true, path: '/path/to/dir' }.then(&hash_to_argv) # => ["-v", "--path", "/path/to/dir"]
258
+ # == Example:
259
+ # { v: true, path: '/path/to/dir' }.then(&hash_to_argv)
260
+ # #=> ["-v", "--path", "/path/to/dir"]
261
+ #
262
+ # == raw_cmd_hash.then(&hash_to_argv) is equivalent to:
263
+ #
264
+ # raw_cmd_hash
265
+ # .then(&Argvise.new_proc)
266
+ # .with_bsd_style(false)
267
+ # .with_kebab_case_flags(true)
268
+ # .build
100
269
  #
101
- # sig { returns(T.proc.params(options: Hash).returns(T::Array[String])) }
270
+ # sig { returns(T.proc.params(raw_cmd_hash: Hash).returns(T::Array[String])) }
102
271
  def hash_to_argv
103
- ->(options) do
104
- Argvise.build(options)
272
+ ->(raw_cmd_hash) do
273
+ Argvise.build(raw_cmd_hash)
105
274
  end
106
275
  end
data/rbi/lib/argvise.rbi CHANGED
@@ -1,12 +1,35 @@
1
+ # rubocop:disable Style/Documentation, Lint/MissingCopEnableDirective
1
2
  # typed: true
2
3
  # frozen_string_literal: true
3
4
 
4
5
  class Argvise
5
6
  class << self
6
- sig { params(options: Hash).returns(T::Array[String]) }
7
- def build(options); end
7
+ sig do
8
+ params(
9
+ raw_cmd_hash: Hash,
10
+ opts: T.nilable(T::Hash[Symbol, T::Boolean])
11
+ ).returns(T::Array[String])
12
+ end
13
+ def build(raw_cmd_hash, opts: nil); end
8
14
  end
15
+
16
+ sig do
17
+ params(
18
+ raw_cmd_hash: Hash,
19
+ opts: T.nilable(T::Hash[Symbol, T::Boolean])
20
+ ).void
21
+ end
22
+ def initialize(raw_cmd_hash, opts: nil); end
23
+
24
+ sig { params(value: T::Boolean).returns(self) }
25
+ def with_bsd_style(value = true); end # rubocop:disable Style/OptionalBooleanParameter
26
+
27
+ sig { params(value: T::Boolean).returns(self) }
28
+ def with_kebab_case_flags(value = true); end # rubocop:disable Style/OptionalBooleanParameter
29
+
30
+ sig { returns(T::Array[String]) }
31
+ def build; end
9
32
  end
10
33
 
11
- sig { returns(T.proc.params(options: Hash).returns(T::Array[String])) }
34
+ sig { returns(T.proc.params(raw_cmd_hash: T::Hash[T.any(Symbol, String), T.untyped]).returns(T::Array[String])) }
12
35
  def hash_to_argv; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: argvise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - 2moe
@@ -17,7 +17,11 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - ".rubocop.yml"
20
21
  - License
22
+ - argvise.gemspec
23
+ - bin/build.rb
24
+ - bin/console.rb
21
25
  - docs/Readme.md
22
26
  - lib/argvise.rb
23
27
  - lib/argvise/version.rb
@@ -35,14 +39,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
35
39
  requirements:
36
40
  - - ">="
37
41
  - !ruby/object:Gem::Version
38
- version: 3.0.0
42
+ version: 3.1.0
39
43
  required_rubygems_version: !ruby/object:Gem::Requirement
40
44
  requirements:
41
45
  - - ">="
42
46
  - !ruby/object:Gem::Version
43
47
  version: '0'
44
48
  requirements: []
45
- rubygems_version: 3.6.9
49
+ rubygems_version: 3.7.2
46
50
  specification_version: 4
47
51
  summary: Turns a hash into CLI arguments
48
52
  test_files: []