flags: Rename variadic to manifold (breaking change)

This commit is contained in:
Feoramund
2025-06-09 11:27:27 -04:00
parent 87247b8bb7
commit e20db8df89
8 changed files with 36 additions and 35 deletions
+1 -1
View File
@@ -19,7 +19,7 @@ SUBTAG_NAME :: "name"
SUBTAG_POS :: "pos" SUBTAG_POS :: "pos"
SUBTAG_REQUIRED :: "required" SUBTAG_REQUIRED :: "required"
SUBTAG_HIDDEN :: "hidden" SUBTAG_HIDDEN :: "hidden"
SUBTAG_VARIADIC :: "variadic" SUBTAG_MANIFOLD :: "manifold"
SUBTAG_FILE :: "file" SUBTAG_FILE :: "file"
SUBTAG_PERMS :: "perms" SUBTAG_PERMS :: "perms"
SUBTAG_INDISTINCT :: "indistinct" SUBTAG_INDISTINCT :: "indistinct"
+5 -4
View File
@@ -32,7 +32,7 @@ Under the `args` tag, there are the following subtags:
- `pos=N`: place positional argument `N` into this flag. - `pos=N`: place positional argument `N` into this flag.
- `hidden`: hide this flag from the usage documentation. - `hidden`: hide this flag from the usage documentation.
- `required`: cause verification to fail if this argument is not set. - `required`: cause verification to fail if this argument is not set.
- `variadic`: take all remaining arguments when set, UNIX-style only. - `manifold=N`: take several arguments at once, UNIX-style only.
- `file`: for `os.Handle` types, file open mode. - `file`: for `os.Handle` types, file open mode.
- `perms`: for `os.Handle` types, file open permissions. - `perms`: for `os.Handle` types, file open permissions.
- `indistinct`: allow the setting of distinct types by their base type. - `indistinct`: allow the setting of distinct types by their base type.
@@ -47,8 +47,9 @@ you want to require 3 and only 3 arguments in a dynamic array, you would
specify `required=3<4`. specify `required=3<4`.
`variadic` may be given a number (`variadic=N`) above 1 to limit how many extra `manifold` may be given a number (`manifold=N`) above 1 to limit how many extra
arguments it consumes. arguments it consumes at once. If this number is not specified, it will take as
many arguments as can be converted to the underlying element type.
`file` determines the file open mode for an `os.Handle`. `file` determines the file open mode for an `os.Handle`.
@@ -160,7 +161,7 @@ at parse time.
--flag --flag
--flag=argument --flag=argument
--flag argument --flag argument
--flag argument repeating-argument --flag argument (manifold-argument)
`-flag` may also be substituted for `--flag`. `-flag` may also be substituted for `--flag`.
+2 -2
View File
@@ -107,9 +107,9 @@ main :: proc() {
// assignments: map[string]u8 `args:"name=assign" usage:"Number of jobs per worker."`, // assignments: map[string]u8 `args:"name=assign" usage:"Number of jobs per worker."`,
// (Variadic) Only available in UNIX style: // (Manifold) Only available in UNIX style:
// bots: [dynamic]string `args:"variadic=2,required"`, // bots: [dynamic]string `args:"manifold=2,required"`,
verbose: bool `usage:"Show verbose output."`, verbose: bool `usage:"Show verbose output."`,
debug: bool `args:"hidden" usage:"print debug info"`, debug: bool `args:"hidden" usage:"print debug info"`,
+2 -2
View File
@@ -117,8 +117,8 @@ set_unix_flag :: proc(model: ^$T, parser: ^Parser, name: string) -> (future_args
case runtime.Type_Info_Dynamic_Array: case runtime.Type_Info_Dynamic_Array:
future_args = 1 future_args = 1
if tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok { if tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok {
if length, is_variadic := get_struct_subtag(tag, SUBTAG_VARIADIC); is_variadic { if length, is_manifold := get_struct_subtag(tag, SUBTAG_MANIFOLD); is_manifold {
// Variadic arrays may specify how many arguments they consume at once. // Manifold arrays may specify how many arguments they consume at once.
// Otherwise, they take everything that's left. // Otherwise, they take everything that's left.
if value, value_ok := strconv.parse_u64_of_base(length, 10); value_ok { if value, value_ok := strconv.parse_u64_of_base(length, 10); value_ok {
future_args = cast(int)value future_args = cast(int)value
+6 -6
View File
@@ -109,24 +109,24 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_
} }
} }
if length, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic { if length, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold {
if value, parse_ok := strconv.parse_u64_of_base(length, 10); parse_ok { if value, parse_ok := strconv.parse_u64_of_base(length, 10); parse_ok {
fmt.assertf(value > 0, fmt.assertf(value > 0,
"%T.%s has `%s` set to %i. It must be greater than zero.", "%T.%s has `%s` set to %i. It must be greater than zero.",
model_type, field.name, value, SUBTAG_VARIADIC, loc = loc) model_type, field.name, value, SUBTAG_MANIFOLD, loc = loc)
fmt.assertf(value != 1, fmt.assertf(value != 1,
"%T.%s has `%s` set to 1. This has no effect.", "%T.%s has `%s` set to 1. This is equivalent to not defining `%s`.",
model_type, field.name, SUBTAG_VARIADIC, loc = loc) model_type, field.name, SUBTAG_MANIFOLD, SUBTAG_MANIFOLD, loc = loc)
} }
#partial switch specific_type_info in field.type.variant { #partial switch specific_type_info in field.type.variant {
case runtime.Type_Info_Dynamic_Array: case runtime.Type_Info_Dynamic_Array:
fmt.assertf(style != .Odin, fmt.assertf(style != .Odin,
"%T.%s has `%s` defined, but this only makes sense in UNIX-style parsing mode.", "%T.%s has `%s` defined, but this only makes sense in UNIX-style parsing mode.",
model_type, field.name, SUBTAG_VARIADIC, loc = loc) model_type, field.name, SUBTAG_MANIFOLD, loc = loc)
case: case:
fmt.panicf("%T.%s has `%s` defined, but this only makes sense on dynamic arrays.", fmt.panicf("%T.%s has `%s` defined, but this only makes sense on dynamic arrays.",
model_type, field.name, SUBTAG_VARIADIC, loc = loc) model_type, field.name, SUBTAG_MANIFOLD, loc = loc)
} }
} }
+2 -2
View File
@@ -6,7 +6,7 @@ package flags
Parsing_Style :: enum { Parsing_Style :: enum {
// Odin-style: `-flag`, `-flag:option`, `-map:key=value` // Odin-style: `-flag`, `-flag:option`, `-map:key=value`
Odin, Odin,
// UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument repeating-argument` // UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument (manifold-argument)`
Unix, Unix,
} }
@@ -61,7 +61,7 @@ parse :: proc(
} }
case .Unix: case .Unix:
// Support for `-flag argument (repeating-argument ...)` // Support for `-flag argument (manifold-argument ...)`
future_args: int future_args: int
current_flag: string current_flag: string
+8 -8
View File
@@ -30,8 +30,8 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty
is_positional: bool, is_positional: bool,
is_required: bool, is_required: bool,
is_boolean: bool, is_boolean: bool,
is_variadic: bool, is_manifold: bool,
variadic_length: int, manifold_length: int,
} }
// //
@@ -120,10 +120,10 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty
flag.is_required = true flag.is_required = true
flag.required_min, flag.required_max, _ = parse_requirements(requirement) flag.required_min, flag.required_max, _ = parse_requirements(requirement)
} }
if length_str, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic { if length_str, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold {
flag.is_variadic = true flag.is_manifold = true
if length, parse_ok := strconv.parse_u64_of_base(length_str, 10); parse_ok { if length, parse_ok := strconv.parse_u64_of_base(length_str, 10); parse_ok {
flag.variadic_length = cast(int)length flag.manifold_length = cast(int)length
} }
} }
} }
@@ -147,15 +147,15 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty
case runtime.Type_Info_Dynamic_Array: case runtime.Type_Info_Dynamic_Array:
requirement_spec := describe_array_requirements(flag) requirement_spec := describe_array_requirements(flag)
if flag.is_variadic || flag.name == INTERNAL_VARIADIC_FLAG { if flag.is_manifold || flag.name == INTERNAL_VARIADIC_FLAG {
if flag.variadic_length == 0 { if flag.manifold_length == 0 {
flag.type_description = fmt.tprintf("<%v, ...>%s", flag.type_description = fmt.tprintf("<%v, ...>%s",
specific_type_info.elem.id, specific_type_info.elem.id,
requirement_spec) requirement_spec)
} else { } else {
flag.type_description = fmt.tprintf("<%v, %i at once>%s", flag.type_description = fmt.tprintf("<%v, %i at once>%s",
specific_type_info.elem.id, specific_type_info.elem.id,
flag.variadic_length, flag.manifold_length,
requirement_spec) requirement_spec)
} }
} else { } else {
+10 -10
View File
@@ -966,9 +966,9 @@ test_unix :: proc(t: ^testing.T) {
} }
@(test) @(test)
test_unix_variadic :: proc(t: ^testing.T) { test_unix_manifold :: proc(t: ^testing.T) {
S :: struct { S :: struct {
a: [dynamic]int `args:"variadic"`, a: [dynamic]int `args:"manifold"`,
} }
s: S s: S
@@ -989,9 +989,9 @@ test_unix_variadic :: proc(t: ^testing.T) {
} }
@(test) @(test)
test_unix_variadic_limited :: proc(t: ^testing.T) { test_unix_manifold_limited :: proc(t: ^testing.T) {
S :: struct { S :: struct {
a: [dynamic]int `args:"variadic=2"`, a: [dynamic]int `args:"manifold=2"`,
b: int, b: int,
} }
s: S s: S
@@ -1029,10 +1029,10 @@ test_unix_positional :: proc(t: ^testing.T) {
} }
@(test) @(test)
test_unix_positional_with_variadic :: proc(t: ^testing.T) { test_unix_positional_with_manifold :: proc(t: ^testing.T) {
S :: struct { S :: struct {
varg: [dynamic]int, varg: [dynamic]int,
v: [dynamic]int `args:"variadic"`, v: [dynamic]int `args:"manifold"`,
} }
s: S s: S
@@ -1049,7 +1049,7 @@ test_unix_positional_with_variadic :: proc(t: ^testing.T) {
} }
@(test) @(test)
test_unix_double_dash_variadic :: proc(t: ^testing.T) { test_unix_double_dash_varargs :: proc(t: ^testing.T) {
S :: struct { S :: struct {
varg: [dynamic]string, varg: [dynamic]string,
i: int, i: int,
@@ -1337,7 +1337,7 @@ very nicely.
@(test) @(test)
test_usage_write_unix :: proc(t: ^testing.T) { test_usage_write_unix :: proc(t: ^testing.T) {
Expected_Output :: `Usage: Expected_Output :: `Usage:
varg required-number [number] [name] --bars --bots --foos --gadgets --variadic-flag --widgets [--array] [--count] [--greek] [--verbose] ... varg required-number [number] [name] --bars --bots --foos --gadgets --manifold-flag --widgets [--array] [--count] [--greek] [--verbose] ...
Flags: Flags:
--required-number <int>, required | some number --required-number <int>, required | some number
--number <int> | some other number --number <int> | some other number
@@ -1349,7 +1349,7 @@ Flags:
--bots <string>, at least 1 | <This flag has not been documented yet.> --bots <string>, at least 1 | <This flag has not been documented yet.>
--foos <string>, between 2 and 3 | <This flag has not been documented yet.> --foos <string>, between 2 and 3 | <This flag has not been documented yet.>
--gadgets <string>, at least 1 | <This flag has not been documented yet.> --gadgets <string>, at least 1 | <This flag has not been documented yet.>
--variadic-flag <int, ...>, at least 2 | <This flag has not been documented yet.> --manifold-flag <int, ...>, at least 2 | <This flag has not been documented yet.>
--widgets <string>, at most 2 | <This flag has not been documented yet.> --widgets <string>, at most 2 | <This flag has not been documented yet.>
| |
--array <rune>, multiple | <This flag has not been documented yet.> --array <rune>, multiple | <This flag has not been documented yet.>
@@ -1378,7 +1378,7 @@ very nicely.
greek: Custom_Enum, greek: Custom_Enum,
array: [dynamic]rune, array: [dynamic]rune,
variadic_flag: [dynamic]int `args:"variadic,required=2"`, manifold_flag: [dynamic]int `args:"manifold,required=2"`,
gadgets: [dynamic]string `args:"required=1"`, gadgets: [dynamic]string `args:"required=1"`,
widgets: [dynamic]string `args:"required=<3"`, widgets: [dynamic]string `args:"required=<3"`,