typedargs 0.1.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f905abf1feb54c54d778f3e7239251181f2945bfd8347207f8d7a1e4bb093c81
4
- data.tar.gz: 2ecbbddd89b00e902fcf7963628831d6a16f5cdf2ea7e5aec52d2e7b164470eb
3
+ metadata.gz: 9b1ff45511cabd1ddd347f7bf662753fefb1c1aa53a9dbb06ea258a94617c24b
4
+ data.tar.gz: 3b6a22c83f792a6a3c87416479c529aa09a48d21523c84140f32960a2bc01964
5
5
  SHA512:
6
- metadata.gz: 4edb87ba2b567ff67af4ef5a86e4a9d3318c181b2c326e0f99c40424980f0634311e039dff710c92f884eb171032313e019d47910ddb71b41c694cc32b97ae21
7
- data.tar.gz: 41f77dafb3c330addda8b5b6189311f391eed4cdf069b5c13d1f8b2dadfd3ad20b523c6fe76229e4930dd5e5c4840c2301472867ea15cc61ae98b067ce3bfef8
6
+ metadata.gz: 2747b98351471ec61b2669ff3f7165ca8c96b4d36c31ab964be8e2781bc08584a9aca7824bee4faf301dbc74c891d5d58a124dfa063ff71e5459bcdf5d0f615b
7
+ data.tar.gz: b4b65d4e167065a4948fd0f3f577f57371c71012a24d2c949f38a5bd455e8d765e112b8723f97908653bfa3ce1fa9cafae55198a48a21ef720748c4b2f7f3d22
data/README.md CHANGED
@@ -1,324 +1,133 @@
1
- # TypedArgs
2
- *A tiny operator‑typed CLI language for structured data.*
1
+ # TypedArgs
3
2
 
4
- TypedArgs is not an option parser.
5
- It is a **mini‑language** for expressing structured data on the command line — scalars, arrays, hashes, and arrays of hashes — using a small set of explicit, shell‑safe operators.
6
-
7
- It runs anywhere MRuby runs: embedded systems, containers, CI runners, Windows, macOS, Linux, BusyBox, Alpine, and fully sandboxed MRuby VMs. No dependencies. No shell tricks. No heuristics. No guessing.
8
-
9
- TypedArgs behaves the same everywhere.
10
-
11
- ---
12
-
13
- # Why TypedArgs Exists
14
-
15
- Most CLI parsers try to *guess* what the user meant. TypedArgs refuses.
16
- Shells are inconsistent. Quoting rules differ. JSON on the command line is painful.
17
- Suffix‑typed flags collide with shells. YAML is too heavy.
18
- Users deserve a grammar that is:
19
-
20
- - **Explicit** — the operator defines the shape
21
- - **Portable** — works in every shell without quoting
22
- - **Deterministic** — same input, same output, always
23
- - **Minimal** — four operators, one mental model
24
- - **Structured** — arrays and hashes are first‑class citizens
25
-
26
- TypedArgs is the answer: a tiny algebra of flags.
27
-
28
- ---
29
-
30
- # The Operator Model
31
-
32
- TypedArgs is built on four operators.
33
- They define the shape of the value — nothing else is needed.
34
-
35
- | Operator | Meaning |
36
- |----------|---------|
37
- | `=` | scalar assignment |
38
- | `+=` | append scalar to array |
39
- | `:fields:=` | assign hash tuple |
40
- | `+:fields:=` | append hash tuple to array |
41
-
42
- This is the entire language.
43
-
44
- No suffixes.
45
- No brackets.
46
- No type inference.
47
- No shell‑sensitive characters.
48
- Just operators.
49
-
50
- ---
51
-
52
- # Installation
53
-
54
- TypedArgs is pure Ruby and MRuby‑core‑friendly.
55
- Drop the Ruby files into your MRuby build or load them into your VM.
56
-
57
- ---
58
-
59
- # Basic Usage
60
-
61
- ```ruby
62
- args = TypedArgs.opts("--mode=fast", "--debug=true")
63
-
64
- args["mode"] # => "fast"
65
- args["debug"] # => true
66
- ```
67
-
68
- If no arguments are passed, `TypedArgs.opts` defaults to `ARGV`.
69
- You must supply that array yourself in MRuby; see `tools/typedargs_test/test.c` for an example.
70
-
71
- ---
72
-
73
- # Grammar Overview
74
-
75
- TypedArgs defines a small, explicit grammar for keys and values.
76
- Everything is driven by operators.
77
-
78
- ---
79
-
80
- ## Scalars
3
+ Structured CLI arguments for mruby and CRuby. Lets you pass arrays, hashes, and arrays of records on the command line without quoting JSON or writing a config file.
81
4
 
82
5
  ```
83
6
  --mode=fast
84
- --count=5
85
- --debug=true
86
- --foo=nil
87
- ```
88
-
89
- Values may be:
90
-
91
- - strings
92
- - integers
93
- - floats
94
- - booleans (`true` / `false`)
95
- - `nil`
96
-
97
- ---
98
-
99
- ## Dotted Keys
100
-
101
- ```
102
- --db.user=root
103
- --cache.redis.host=localhost
104
- ```
105
-
106
- Keys may contain:
107
-
108
- - letters
109
- - digits
110
- - underscore
111
- - dash
112
- - dot
113
-
114
- Keys may **not** start with a digit or dash.
115
- Dotted keys are treated as **flat strings**, not nested hashes.
116
-
117
- ---
118
-
119
- ## Arrays (`+=`)
120
-
121
- ```
122
- --item+=a
123
- --item+=b
124
- ```
125
-
126
- Result:
127
-
128
- ```ruby
129
- { "item" => ["a", "b"] }
130
- ```
131
-
132
- `+=` always appends.
133
- If the key didn’t exist, an array is created.
134
-
135
- ---
136
-
137
- ## Hash Tuples (`:fields:=`)
138
-
139
- ```
7
+ --item+=apple --item+=banana
140
8
  --range:min,max:=5,10
141
- ```
142
-
143
- Result:
144
-
145
- ```ruby
146
- { "range" => { "min" => 5, "max" => 10 } }
147
- ```
148
-
149
- Arity is enforced:
150
- If you declare two fields, you must supply two values.
151
-
152
- ---
153
-
154
- ## Arrays of Hashes (`+:fields:=`)
155
-
156
- ```
157
9
  --servers+:name,port:=alpha,80
158
10
  --servers+:name,port:=beta,443
159
11
  ```
160
12
 
161
- Result:
13
+ becomes
162
14
 
163
15
  ```ruby
164
16
  {
17
+ "mode" => "fast",
18
+ "item" => ["apple", "banana"],
19
+ "range" => {"min" => 5, "max" => 10},
165
20
  "servers" => [
166
- { "name" => "alpha", "port" => 80 },
167
- { "name" => "beta", "port" => 443 }
21
+ {"name" => "alpha", "port" => 80},
22
+ {"name" => "beta", "port" => 443}
168
23
  ]
169
24
  }
170
25
  ```
171
26
 
172
- `+:` always appends a hash to an array.
173
-
174
- ---
27
+ It's a small, dependency-free parser that runs anywhere mruby runs (embedded, BusyBox, Alpine, sandboxed VMs) and on CRuby ≥ 2.5.
175
28
 
176
- ## Short‑Flag Aliases
29
+ ## When you'd want this
177
30
 
178
- ```ruby
179
- TypedArgs.alias("-v", "--verbose")
180
- TypedArgs.opts("-v")
181
- # => { "verbose" => true }
182
- ```
183
-
184
- Aliases expand before parsing.
185
- They can target dotted keys and any operator form.
186
-
187
- ---
188
-
189
- # Error Reporting
190
-
191
- TypedArgs provides compiler‑style diagnostics with caret indicators.
192
-
193
- Example:
194
-
195
- ```
196
- --range:min,max:=5
197
- ^
198
- Syntax error: Arity mismatch: expected 2, got 1
199
- ```
31
+ You have a CLI that takes input that's genuinely structured — a list of servers, a set of feature toggles, a hash of coordinates — and the alternatives don't fit:
200
32
 
201
- Every error includes:
33
+ - JSON on argv means escaping `'{"servers":[{"name":"alpha"}]}'` past the shell.
34
+ - Repeating a flag with an ad-hoc convention (`--server alpha:80 --server beta:443`) means inventing a mini-syntax per tool.
35
+ - A config file is heavy when you only have three values to pass.
202
36
 
203
- - the original argument
204
- - a caret pointing to the exact byte
205
- - a clear error class
37
+ If your CLI takes scalars and the occasional list, a normal option parser is probably a better fit. TypedArgs earns its place when structure is the point.
206
38
 
207
- TypedArgs is self‑teaching.
39
+ ## The four operators
208
40
 
209
- ---
41
+ | Form | Meaning |
42
+ |---|---|
43
+ | `--key=value` | scalar |
44
+ | `--key+=value` | append to array |
45
+ | `--key:f1,f2:=v1,v2` | hash with named fields |
46
+ | `--key+:f1,f2:=v1,v2` | append a hash to an array |
210
47
 
211
- # Operator Semantics
48
+ Scalar values are auto-typed: integers, floats, `true`, `false`, `nil`, and otherwise strings. Tuple arity is enforced — declaring two fields means you must supply two values.
212
49
 
213
- TypedArgs applies flags **in order**.
214
- Later flags overwrite earlier ones unless using accumulation operators.
50
+ ## Usage
215
51
 
216
- ---
217
-
218
- ## Scalar Assignment (`=`)
219
-
220
- | Syntax | Meaning |
221
- |--------|---------|
222
- | `--key=value` | assign scalar |
223
-
224
- Overwrites previous value.
225
-
226
- ---
227
-
228
- ## Scalar Accumulation (`+=`)
52
+ ```ruby
53
+ require "typedargs"
229
54
 
230
- | Syntax | Meaning |
231
- |--------|---------|
232
- | `--key+=value` | append scalar to array |
55
+ args = TypedArgs.opts("--mode=fast", "--debug=true")
56
+ args["mode"] # => "fast"
57
+ args["debug"] # => true
58
+ ```
233
59
 
234
- Creates array if missing.
235
- Overwrites previous non‑array values.
60
+ Calling `TypedArgs.opts` with no arguments reads from `ARGV`. In mruby you provide `ARGV` yourself; see `tools/typedargs_test/test.c`.
236
61
 
237
- ---
62
+ ## Keys
238
63
 
239
- ## Hash Tuple Assignment (`:fields:=`)
64
+ Keys are letters, digits, underscore, dash, and dot. They can't start with a digit or dash. Dotted keys (`--db.host=localhost`) are stored as **flat strings**, not nested hashes — `args["db.host"]`, not `args["db"]["host"]`. Auto-nesting opens ambiguities the grammar avoids.
240
65
 
241
- | Syntax | Meaning |
242
- |--------|---------|
243
- | `--key:field1,field2:=v1,v2` | assign hash |
66
+ ## Short-flag aliases
244
67
 
245
- Overwrites previous value.
68
+ ```ruby
69
+ TypedArgs.alias("-v", "--verbose")
70
+ TypedArgs.opts("-v") # => {"verbose" => true}
71
+ TypedArgs.opts("-vfoo") # => {"verbose" => "foo"}
72
+ ```
246
73
 
247
- ---
74
+ The alias target can be any long-flag form, including operators:
248
75
 
249
- ## Array of Hashes (`+:fields:=`)
76
+ ```ruby
77
+ TypedArgs.alias("-r", "--range:min,max:=")
78
+ TypedArgs.opts("-r5,10") # => {"range" => {"min" => 5, "max" => 10}}
250
79
 
251
- | Syntax | Meaning |
252
- |--------|---------|
253
- | `--key+:field1,field2:=v1,v2` | append hash to array |
80
+ TypedArgs.alias("-S", "--servers+:name,port:=")
81
+ TypedArgs.opts("-Salpha,80", "-Sbeta,443")
82
+ # => {"servers" => [{"name"=>"alpha","port"=>80}, {"name"=>"beta","port"=>443}]}
83
+ ```
254
84
 
255
- Creates array if missing.
85
+ Aliases are textual rewrites performed before parsing. `TypedArgs.reset_aliases!` clears the alias map (useful in tests).
256
86
 
257
- ---
87
+ ## Override rules
258
88
 
259
- # Sequential Override Rules
89
+ Flags apply in argv order. Later flags overwrite earlier ones unless they're accumulating.
260
90
 
261
91
  | Sequence | Result |
262
- |----------|--------|
263
- | `--foo=1` `--foo+=2` | `[2]` |
264
- | `--foo+=1` `--foo+=2` | `[1,2]` |
265
- | `--foo:min,max:=1,2` `--foo:min,max:=3,4` | `{ "min"=>3,"max"=>4 }` |
266
- | `--foo+:min,max:=1,2` `--foo+:min,max:=3,4` | `[{"min"=>1,"max"=>2},{"min"=>3,"max"=>4}]` |
267
- | `--foo=1` `--foo+=2` `--foo:name:=alpha` `--foo=bar` | `"bar"` |
268
-
269
- TypedArgs is explicit:
270
- the operator determines the shape.
271
-
272
- ---
92
+ |---|---|
93
+ | `--foo=1` then `--foo+=2` | `[2]` |
94
+ | `--foo+=1` then `--foo+=2` | `[1, 2]` |
95
+ | `--foo:a,b:=1,2` then `--foo:a,b:=3,4` | `{"a"=>3, "b"=>4}` |
96
+ | `--foo+:a,b:=1,2` then `--foo+:a,b:=3,4` | `[{"a"=>1,"b"=>2}, {"a"=>3,"b"=>4}]` |
97
+ | `--foo=1`, `--foo+=2`, `--foo:n:=x`, `--foo=bar` | `"bar"` |
273
98
 
274
- # Conformance Suite
99
+ The operator on each flag determines the shape of the value at that key.
275
100
 
276
- TypedArgs ships with a full conformance suite covering:
101
+ ## Errors
277
102
 
278
- - scalars
279
- - arrays
280
- - hashes
281
- - arrays of hashes
282
- - dotted keys
283
- - alias expansion
284
- - invalid characters
285
- - invalid suffix placement
286
- - invalid field lists
287
- - tuple arity
288
- - invalid numbers
289
- - unterminated strings
290
- - invalid short flags
291
- - invalid dotted paths
292
- - empty keys
293
- - alias expansion to invalid keys
103
+ Invalid input raises a `TypedArgs::SyntaxError` subclass with a caret pointing at the offending byte:
294
104
 
295
- The suite **is the specification**.
296
- If an implementation passes the suite, it is TypedArgs.
105
+ ```
106
+ --range:min,max:=5
107
+ ^
108
+ Syntax error: Arity mismatch: expected 2, got 1
109
+ ```
297
110
 
298
- ---
111
+ The exception classes are `InvalidCharacterError`, `InvalidKeyStartError`, `UnterminatedStringError`, `ArityMismatchError`, `UnexpectedTokenError`, `InvalidSuffixPositionError`, `InvalidFieldListError`, and `InvalidNumberError`.
299
112
 
300
- # Design Philosophy
113
+ ## Caveats
301
114
 
302
- TypedArgs is intentionally:
115
+ The shell still owns word-splitting and metacharacter handling — `--secret=p$ssw0rd` will need quoting in bash regardless of what TypedArgs does after argv arrives. Strictness around scalars (e.g. `12.34.56` raises rather than parsing as a string) is intentional but stricter than most option parsers.
303
116
 
304
- - **Explicit** — no guessing
305
- - **Portable** — no shell dependencies
306
- - **Minimal** — four operators, one grammar
307
- - **Deterministic** — predictable and stable
308
- - **Structured** — arrays and hashes are first‑class
117
+ ## Installation
309
118
 
310
- TypedArgs does **not** depend on:
119
+ For CRuby:
311
120
 
312
- - shell brace expansion
313
- - shell quoting rules
314
- - environment‑specific behavior
315
- - Bash‑only features
121
+ ```
122
+ gem install typedargs
123
+ ```
316
124
 
317
- The shell’s only job is to pass raw strings.
318
- TypedArgs does everything else.
125
+ For mruby, add to your `build_config.rb`:
319
126
 
320
- ---
127
+ ```ruby
128
+ conf.gem mgem: 'typedargs'
129
+ ```
321
130
 
322
- # License
131
+ ## License
323
132
 
324
- Apache2
133
+ Apache-2.0.
data/mrblib/alias.rb CHANGED
@@ -7,19 +7,38 @@ module TypedArgs
7
7
  @alias_map[short] = long
8
8
  end
9
9
 
10
- def resolve_name(raw)
11
- mapped = @alias_map[raw]
12
- mapped ? strip_leading_dashes(mapped) : strip_leading_dashes(raw)
10
+ def reset_aliases!
11
+ @alias_map = {}
13
12
  end
14
13
 
15
- private
16
- def strip_leading_dashes(str)
17
- i = 0
18
- n = str.bytesize
19
- while i < n && str[i,1] == "-"
20
- i += 1
14
+ # If `arg` is a short flag whose first 2 characters are registered as an
15
+ # alias, return the textually-expanded long-flag form. Otherwise return
16
+ # nil.
17
+ #
18
+ # Expansion rule:
19
+ # "-X" alone → alias_target
20
+ # "-X<payload>" → alias_target + payload (if target ends in "=")
21
+ # alias_target + "=" + payload (otherwise)
22
+ #
23
+ # This makes the README's claim literally true: aliases are textual
24
+ # substitutions performed before parsing, and they can target dotted
25
+ # keys and any operator form (`=`, `+=`, `:fields:=`, `+:fields:=`).
26
+ def expand_short_alias(arg)
27
+ return nil if arg.nil? || arg.length < 2
28
+ short_key = arg[0, 2]
29
+ target = @alias_map[short_key]
30
+ return nil if target.nil?
31
+
32
+ if arg.length > 2
33
+ payload = arg[2, arg.length - 2]
34
+ if target.length > 0 && target[target.length - 1, 1] == "="
35
+ target + payload
36
+ else
37
+ target + "=" + payload
38
+ end
39
+ else
40
+ target
21
41
  end
22
- str[i, n - i]
23
42
  end
24
43
  end
25
44
  end
data/mrblib/impl.rb CHANGED
@@ -12,7 +12,21 @@ module TypedArgs
12
12
  if long_flag?(a)
13
13
  parse_long(out, a)
14
14
  elsif short_flag?(a)
15
- parse_short(out, a)
15
+ # Alias expansion happens BEFORE parsing, per the README.
16
+ # If a 2-char short prefix is aliased, we textually rewrite
17
+ # the entire arg into a long-flag form and dispatch there.
18
+ expanded = Internal.expand_short_alias(a)
19
+ if expanded
20
+ if long_flag?(expanded)
21
+ parse_long(out, expanded)
22
+ else
23
+ # Alias target wasn't a long-flag form; treat the original
24
+ # arg as a short flag (best-effort fallback).
25
+ parse_short(out, a)
26
+ end
27
+ else
28
+ parse_short(out, a)
29
+ end
16
30
  end
17
31
  end
18
32
  i += 1
@@ -21,6 +35,7 @@ module TypedArgs
21
35
  end
22
36
 
23
37
  private
38
+
24
39
  def long_flag?(arg)
25
40
  arg.length >= 2 &&
26
41
  arg[0,1] == "-" &&
@@ -33,35 +48,28 @@ module TypedArgs
33
48
  !(arg.length >= 2 && arg[1,1] == "-")
34
49
  end
35
50
 
36
-
37
- # In impl.rb, replace parse_long or parse_long-like logic with:
38
-
39
51
  def parse_long(out, arg)
40
- # body as character substring (character-mode)
41
- body = arg[2, arg.length - 2] # "--" removed, character-based
52
+ body = arg[2, arg.length - 2] # strip "--"
42
53
 
43
- # find '=' in character mode
44
54
  eq_idx = body.index("=")
45
-
46
55
  if eq_idx
47
- key_str = body[0, eq_idx] # character substring for key
48
- val_str = body[(eq_idx + 1), body.length - (eq_idx + 1)] # character substring for value
56
+ key_str = body[0, eq_idx]
57
+ val_str = body[(eq_idx + 1), body.length - (eq_idx + 1)]
49
58
  else
50
59
  key_str = body
51
60
  val_str = nil
52
61
  end
53
62
 
54
- # parse key in character mode
55
63
  key_lex = Lexer.new(key_str, 0, key_str.length, true)
56
64
  key_ast = KeyParser.new(key_lex).parse
57
65
 
58
- name = Internal.resolve_name(key_ast[:name])
66
+ # Long-flag keys are taken at face value; the alias map applies
67
+ # only to short flags (per README).
68
+ name = key_ast[:name]
59
69
 
60
- # script check (character indices)
61
70
  ScriptCheck.validate_key(key_str)
62
71
 
63
72
  if val_str
64
- # parse value in character mode (value lexer now also character-based)
65
73
  val_lex = Lexer.new(val_str, 0, val_str.length, false)
66
74
  vp = ValueParser.new(val_lex)
67
75
 
@@ -79,55 +87,34 @@ module TypedArgs
79
87
  assign(out, name, key_ast, value)
80
88
  end
81
89
 
82
-
90
+ # parse_short handles short flags that DO NOT have an alias.
91
+ # Aliased short flags are rewritten and dispatched to parse_long.
83
92
  def parse_short(out, arg)
84
- raw = arg[0,2]
85
- name = Internal.resolve_name(raw)
93
+ # Strip the leading dash; everything after it is the bare name
94
+ # candidate (until any attached value).
95
+ name = arg[1, arg.length - 1]
86
96
 
87
97
  if name.nil? || name.length == 0
88
98
  raise InvalidKeyStartError.new(
89
- "Invalid key start",
90
- 1,
91
- arg
99
+ "Invalid key start", 1, arg
92
100
  )
93
101
  end
94
102
 
95
- # first character validation (character-mode)
103
+ # Validate the first character of the short-flag name.
96
104
  c0 = name[0,1]
97
105
  unless c0 == "_" ||
98
106
  (c0 >= "A" && c0 <= "Z") ||
99
107
  (c0 >= "a" && c0 <= "z") ||
100
- (c0 > "\u007F") # treat non-ASCII single-char as letter candidate
108
+ (c0 > "\u007F")
101
109
  raise InvalidCharacterError.new(
102
- "Illegal character in short flag",
103
- 1,
104
- arg
110
+ "Illegal character in short flag", 1, arg
105
111
  )
106
112
  end
107
113
 
108
- # remaining characters validation (character-mode)
109
- j = 1
110
- while j < name.length
111
- ch = name[j,1]
112
- valid =
113
- ch == "_" ||
114
- (ch >= "A" && ch <= "Z") ||
115
- (ch >= "a" && ch <= "z") ||
116
- (ch >= "0" && ch <= "9") ||
117
- ch == "-" ||
118
- ch == "." ||
119
- (ch > "\u007F") # allow non-ASCII letters
120
- unless valid
121
- raise InvalidCharacterError.new(
122
- "Illegal character in short flag",
123
- 1,
124
- arg
125
- )
126
- end
127
- j += 1
128
- end
114
+ # The bare name is just the first character. Everything else
115
+ # (if any) is the attached value.
116
+ name = c0
129
117
 
130
- # attached value (character-mode)
131
118
  if arg.length > 2
132
119
  val_str = arg[2, arg.length - 2]
133
120
  val_lex = Lexer.new(val_str, 0, val_str.length, false)
@@ -140,7 +127,6 @@ module TypedArgs
140
127
  out[name] = value
141
128
  end
142
129
 
143
-
144
130
  def build_hash(fields, vals)
145
131
  h = {}
146
132
  i = 0
@@ -156,10 +142,8 @@ module TypedArgs
156
142
  when :scalar
157
143
  out[name] = value
158
144
  when :hash
159
- existing = out[name]
160
- h = existing.is_a?(Hash) ? existing : {}
161
- value.each { |k, v| h[k] = v }
162
- out[name] = h
145
+ # Hash tuple assignment overwrites the previous value, per README.
146
+ out[name] = value
163
147
  when :array_scalar
164
148
  existing = out[name]
165
149
  arr = existing.is_a?(Array) ? existing : []
data/mrblib/lexer.rb CHANGED
@@ -43,7 +43,7 @@ module TypedArgs
43
43
  start = i
44
44
  i += 1
45
45
 
46
- # scan UTF8 codepoints until closing quote
46
+ # scan UTF-8 codepoints until closing quote
47
47
  while i < end_i
48
48
  cp, ni = Internal.utf8_next(s, i)
49
49
 
@@ -88,7 +88,7 @@ module TypedArgs
88
88
  @i = j
89
89
  return Token.new(:IDENT, val, i)
90
90
  else
91
- # raw value: scan until whitespace or comma
91
+ # raw value: scan until comma (the only intra-arg terminator)
92
92
  start = i
93
93
  while i < end_i
94
94
  cc = s[i,1]
data/mrblib/typedargs.rb CHANGED
@@ -27,6 +27,11 @@ module TypedArgs
27
27
  Internal.register_alias(short, long)
28
28
  end
29
29
 
30
+ # Clear all registered aliases. Useful for test isolation.
31
+ def reset_aliases!
32
+ Internal.reset_aliases!
33
+ end
34
+
30
35
  def opts(*argv)
31
36
  args = argv.empty? ? ::ARGV : argv
32
37
  Internal::Impl.parse(args)
data/mrblib/utf8.rb CHANGED
@@ -1,11 +1,5 @@
1
1
  module TypedArgs
2
2
  module Internal
3
- SCRIPT_ASCII = 1
4
- SCRIPT_LATIN = 1
5
- SCRIPT_GREEK = 3
6
- SCRIPT_CYRILLIC = 4
7
- SCRIPT_OTHER = 5
8
-
9
3
  def self.printable_byte?(b)
10
4
  return true if b >= 0x20 && b <= 0x7E
11
5
  return false if b >= 0x80 && b <= 0x9F
@@ -61,7 +61,7 @@ module TypedArgs
61
61
  if Object.const_defined?(:Float)
62
62
  return s.to_f if float_string?(s)
63
63
  end
64
- raise InvalidNumberError.new("Invalid number", @tok.pos, s)
64
+ raise InvalidNumberError.new("Invalid number", @tok.pos, @lx.str)
65
65
  end
66
66
 
67
67
  def integer_string?(s)
data/mrblib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module TypedArgs
2
+ VERSION="0.3.0"
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typedargs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Asmod4n
@@ -27,6 +27,7 @@ files:
27
27
  - mrblib/typedargs.rb
28
28
  - mrblib/utf8.rb
29
29
  - mrblib/value_parser.rb
30
+ - mrblib/version.rb
30
31
  homepage: https://github.com/Asmod4n/mruby-typedargs
31
32
  licenses:
32
33
  - Apache-2.0
@@ -46,7 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
46
47
  - !ruby/object:Gem::Version
47
48
  version: '0'
48
49
  requirements: []
49
- rubygems_version: 4.0.3
50
+ rubygems_version: 3.6.9
50
51
  specification_version: 4
51
52
  summary: A tiny, deterministic operator-typed CLI language.
52
53
  test_files: []