From e20db8df890366f874bf4a956311b92be2d1ac51 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 9 Jun 2025 08:45:16 -0400 Subject: [PATCH 1/5] flags: Rename `variadic` to `manifold` (breaking change) --- core/flags/constants.odin | 2 +- core/flags/doc.odin | 9 +++++---- core/flags/example/example.odin | 4 ++-- core/flags/internal_assignment.odin | 4 ++-- core/flags/internal_validation.odin | 12 ++++++------ core/flags/parsing.odin | 4 ++-- core/flags/usage.odin | 16 ++++++++-------- tests/core/flags/test_core_flags.odin | 20 ++++++++++---------- 8 files changed, 36 insertions(+), 35 deletions(-) diff --git a/core/flags/constants.odin b/core/flags/constants.odin index 6f5281928..68ac711c1 100644 --- a/core/flags/constants.odin +++ b/core/flags/constants.odin @@ -19,7 +19,7 @@ SUBTAG_NAME :: "name" SUBTAG_POS :: "pos" SUBTAG_REQUIRED :: "required" SUBTAG_HIDDEN :: "hidden" -SUBTAG_VARIADIC :: "variadic" +SUBTAG_MANIFOLD :: "manifold" SUBTAG_FILE :: "file" SUBTAG_PERMS :: "perms" SUBTAG_INDISTINCT :: "indistinct" diff --git a/core/flags/doc.odin b/core/flags/doc.odin index b97547806..b5c535d53 100644 --- a/core/flags/doc.odin +++ b/core/flags/doc.odin @@ -32,7 +32,7 @@ Under the `args` tag, there are the following subtags: - `pos=N`: place positional argument `N` into this flag. - `hidden`: hide this flag from the usage documentation. - `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. - `perms`: for `os.Handle` types, file open permissions. - `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`. -`variadic` may be given a number (`variadic=N`) above 1 to limit how many extra -arguments it consumes. +`manifold` may be given a number (`manifold=N`) above 1 to limit how many extra +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`. @@ -160,7 +161,7 @@ at parse time. --flag --flag=argument --flag argument - --flag argument repeating-argument + --flag argument (manifold-argument) `-flag` may also be substituted for `--flag`. diff --git a/core/flags/example/example.odin b/core/flags/example/example.odin index b1d7b58d6..1988eb3ee 100644 --- a/core/flags/example/example.odin +++ b/core/flags/example/example.odin @@ -107,9 +107,9 @@ main :: proc() { // 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."`, debug: bool `args:"hidden" usage:"print debug info"`, diff --git a/core/flags/internal_assignment.odin b/core/flags/internal_assignment.odin index 12ddb876f..3543dba37 100644 --- a/core/flags/internal_assignment.odin +++ b/core/flags/internal_assignment.odin @@ -117,8 +117,8 @@ set_unix_flag :: proc(model: ^$T, parser: ^Parser, name: string) -> (future_args case runtime.Type_Info_Dynamic_Array: future_args = 1 if tag, ok := reflect.struct_tag_lookup(field.tag, TAG_ARGS); ok { - if length, is_variadic := get_struct_subtag(tag, SUBTAG_VARIADIC); is_variadic { - // Variadic arrays may specify how many arguments they consume at once. + if length, is_manifold := get_struct_subtag(tag, SUBTAG_MANIFOLD); is_manifold { + // Manifold arrays may specify how many arguments they consume at once. // Otherwise, they take everything that's left. if value, value_ok := strconv.parse_u64_of_base(length, 10); value_ok { future_args = cast(int)value diff --git a/core/flags/internal_validation.odin b/core/flags/internal_validation.odin index afd05331c..42ea08c78 100644 --- a/core/flags/internal_validation.odin +++ b/core/flags/internal_validation.odin @@ -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 { fmt.assertf(value > 0, "%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, - "%T.%s has `%s` set to 1. This has no effect.", - model_type, field.name, SUBTAG_VARIADIC, loc = loc) + "%T.%s has `%s` set to 1. This is equivalent to not defining `%s`.", + model_type, field.name, SUBTAG_MANIFOLD, SUBTAG_MANIFOLD, loc = loc) } #partial switch specific_type_info in field.type.variant { case runtime.Type_Info_Dynamic_Array: fmt.assertf(style != .Odin, "%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: 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) } } diff --git a/core/flags/parsing.odin b/core/flags/parsing.odin index 2d8ce34eb..989a9a1a6 100644 --- a/core/flags/parsing.odin +++ b/core/flags/parsing.odin @@ -6,7 +6,7 @@ package flags Parsing_Style :: enum { // Odin-style: `-flag`, `-flag:option`, `-map:key=value` Odin, - // UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument repeating-argument` + // UNIX-style: `-flag` or `--flag`, `--flag=argument`, `--flag argument (manifold-argument)` Unix, } @@ -61,7 +61,7 @@ parse :: proc( } case .Unix: - // Support for `-flag argument (repeating-argument ...)` + // Support for `-flag argument (manifold-argument ...)` future_args: int current_flag: string diff --git a/core/flags/usage.odin b/core/flags/usage.odin index c42df7576..92cf21cdb 100644 --- a/core/flags/usage.odin +++ b/core/flags/usage.odin @@ -30,8 +30,8 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty is_positional: bool, is_required: bool, is_boolean: bool, - is_variadic: bool, - variadic_length: int, + is_manifold: bool, + manifold_length: int, } // @@ -120,10 +120,10 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty flag.is_required = true flag.required_min, flag.required_max, _ = parse_requirements(requirement) } - if length_str, is_variadic := get_struct_subtag(args_tag, SUBTAG_VARIADIC); is_variadic { - flag.is_variadic = true + if length_str, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold { + flag.is_manifold = true 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: requirement_spec := describe_array_requirements(flag) - if flag.is_variadic || flag.name == INTERNAL_VARIADIC_FLAG { - if flag.variadic_length == 0 { + if flag.is_manifold || flag.name == INTERNAL_VARIADIC_FLAG { + if flag.manifold_length == 0 { flag.type_description = fmt.tprintf("<%v, ...>%s", specific_type_info.elem.id, requirement_spec) } else { flag.type_description = fmt.tprintf("<%v, %i at once>%s", specific_type_info.elem.id, - flag.variadic_length, + flag.manifold_length, requirement_spec) } } else { diff --git a/tests/core/flags/test_core_flags.odin b/tests/core/flags/test_core_flags.odin index 8fcd6a8a7..9715c7e9a 100644 --- a/tests/core/flags/test_core_flags.odin +++ b/tests/core/flags/test_core_flags.odin @@ -966,9 +966,9 @@ test_unix :: proc(t: ^testing.T) { } @(test) -test_unix_variadic :: proc(t: ^testing.T) { +test_unix_manifold :: proc(t: ^testing.T) { S :: struct { - a: [dynamic]int `args:"variadic"`, + a: [dynamic]int `args:"manifold"`, } s: S @@ -989,9 +989,9 @@ test_unix_variadic :: proc(t: ^testing.T) { } @(test) -test_unix_variadic_limited :: proc(t: ^testing.T) { +test_unix_manifold_limited :: proc(t: ^testing.T) { S :: struct { - a: [dynamic]int `args:"variadic=2"`, + a: [dynamic]int `args:"manifold=2"`, b: int, } s: S @@ -1029,10 +1029,10 @@ test_unix_positional :: proc(t: ^testing.T) { } @(test) -test_unix_positional_with_variadic :: proc(t: ^testing.T) { +test_unix_positional_with_manifold :: proc(t: ^testing.T) { S :: struct { varg: [dynamic]int, - v: [dynamic]int `args:"variadic"`, + v: [dynamic]int `args:"manifold"`, } s: S @@ -1049,7 +1049,7 @@ test_unix_positional_with_variadic :: proc(t: ^testing.T) { } @(test) -test_unix_double_dash_variadic :: proc(t: ^testing.T) { +test_unix_double_dash_varargs :: proc(t: ^testing.T) { S :: struct { varg: [dynamic]string, i: int, @@ -1337,7 +1337,7 @@ very nicely. @(test) test_usage_write_unix :: proc(t: ^testing.T) { 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: --required-number , required | some number --number | some other number @@ -1349,7 +1349,7 @@ Flags: --bots , at least 1 | --foos , between 2 and 3 | --gadgets , at least 1 | - --variadic-flag , at least 2 | + --manifold-flag , at least 2 | --widgets , at most 2 | | --array , multiple | @@ -1378,7 +1378,7 @@ very nicely. greek: Custom_Enum, 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"`, widgets: [dynamic]string `args:"required=<3"`, From 7c5700996f7b8bc569e8b505b916f5fa05042635 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:58:54 -0400 Subject: [PATCH 2/5] flags: Mention `varg` in the documentation --- core/flags/doc.odin | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/flags/doc.odin b/core/flags/doc.odin index b5c535d53..0763c01a7 100644 --- a/core/flags/doc.odin +++ b/core/flags/doc.odin @@ -20,6 +20,13 @@ The format is similar to the Odin binary's way of handling compiler flags. -:= set map[key] to value +Unhandled Arguments: + +All unhandled positional arguments are placed into the `varg` field on a +struct, if it exists. In UNIX-style parsing, the existence of a `--` on the +command line will also pass all arguments afterwards into this field. + + Struct Tags: Users of the `core:encoding/json` package may be familiar with using tags to From cae43b801f01206ee26f85e80181658754f886e1 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 9 Jun 2025 10:59:20 -0400 Subject: [PATCH 3/5] Add more `core:flags` tests to codify behavior --- tests/core/flags/test_core_flags.odin | 104 ++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/tests/core/flags/test_core_flags.odin b/tests/core/flags/test_core_flags.odin index 9715c7e9a..dd2074144 100644 --- a/tests/core/flags/test_core_flags.odin +++ b/tests/core/flags/test_core_flags.odin @@ -1012,6 +1012,110 @@ test_unix_manifold_limited :: proc(t: ^testing.T) { testing.expect_value(t, s.b, 3) } +@(test) +test_unix_two_manifold_limited :: proc(t: ^testing.T) { + S :: struct { + a: [dynamic]int `args:"manifold=2"`, + b: [dynamic]int `args:"manifold=2"`, + c: int, + } + s: S + + args := [?]string { "-a", "11", "101", "-b", "3", "7", "-c", "9" } + + result := flags.parse(&s, args[:], .Unix) + defer { + delete(s.a) + delete(s.b) + } + testing.expect_value(t, result, nil) + testing.expect_value(t, len(s.a), 2) + testing.expect_value(t, len(s.b), 2) + + if len(s.a) < 2 || len(s.b) < 2 { + return + } + + testing.expect_value(t, s.a[0], 11) + testing.expect_value(t, s.a[1], 101) + testing.expect_value(t, s.b[0], 3) + testing.expect_value(t, s.b[1], 7) + testing.expect_value(t, s.c, 9) +} + +@(test) +test_unix_two_manifold_string :: proc(t: ^testing.T) { + // The expected behavior of a manifold flag is to consume all arguments as + // fitting for the element type. + S :: struct { + a: [dynamic]string `args:"manifold"`, + b: [dynamic]string `args:"manifold"`, + c: int, + } + s: S + + args := [?]string { "-a", "11", "101", "-b", "3", "7", "-c", "9" } + + result := flags.parse(&s, args[:], .Unix) + defer { + delete(s.a) + delete(s.b) + } + + testing.expect_value(t, result, nil) + testing.expect_value(t, len(s.a), 7) + testing.expect_value(t, len(s.b), 0) + + if len(s.a) != 7 { + return + } + + testing.expect_value(t, s.a[0], "11") + testing.expect_value(t, s.a[1], "101") + testing.expect_value(t, s.a[2], "-b") + testing.expect_value(t, s.a[3], "3") + testing.expect_value(t, s.a[4], "7") + testing.expect_value(t, s.a[5], "-c") + testing.expect_value(t, s.a[6], "9") +} + +@(test) +test_unix_two_manifold_int :: proc(t: ^testing.T) { + // If a manifold flag encounters an argument that it cannot convert to the + // element type, then this is an error. + S :: struct { + a: [dynamic]int `args:"manifold"`, + b: [dynamic]int `args:"manifold"`, + c: int, + } + s: S + + args := [?]string { "-a", "11", "101", "-b", "3", "7", "-c", "9" } + + result := flags.parse(&s, args[:], .Unix) + defer { + delete(s.a) + delete(s.b) + } + + err, ok := result.(flags.Parse_Error) + testing.expectf(t, ok, "unexpected result: %v", result) + if ok { + testing.expect_value(t, err.reason, flags.Parse_Error_Reason.Bad_Value) + } + + // It is expected that arguments which pass will still be available. + testing.expect_value(t, len(s.a), 2) + testing.expect_value(t, len(s.b), 0) + + if len(s.a) != 2 { + return + } + + testing.expect_value(t, s.a[0], 11) + testing.expect_value(t, s.a[1], 101) +} + @(test) test_unix_positional :: proc(t: ^testing.T) { S :: struct { From 2e199c669f539fe327dcc52a82d0216e66da974b Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:27:06 -0400 Subject: [PATCH 4/5] flags: Forbid combination of `pos` and `manifold` --- core/flags/internal_validation.odin | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/flags/internal_validation.odin b/core/flags/internal_validation.odin index 42ea08c78..b68df8cb5 100644 --- a/core/flags/internal_validation.odin +++ b/core/flags/internal_validation.odin @@ -59,7 +59,8 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ } } - if pos_str, has_pos := get_struct_subtag(args_tag, SUBTAG_POS); has_pos { + pos_str, has_pos := get_struct_subtag(args_tag, SUBTAG_POS) + if has_pos { #partial switch specific_type_info in field.type.variant { case runtime.Type_Info_Map: fmt.panicf("%T.%s has `%s` defined, and this does not make sense on a map type.", @@ -110,6 +111,10 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ } if length, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold { + fmt.assertf(!has_pos, + "%T.%s has both `%s` and `%s` defined. This is disallowed.\n\tSuggestion: Use a dynamic array field named `%s` to accept unspecified positional arguments.", + model_type, field.name, SUBTAG_POS, SUBTAG_MANIFOLD, INTERNAL_VARIADIC_FLAG, loc = loc) + if value, parse_ok := strconv.parse_u64_of_base(length, 10); parse_ok { fmt.assertf(value > 0, "%T.%s has `%s` set to %i. It must be greater than zero.", From 6dee422700130a8ea450a753e8e2a059f3ab2bd5 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Mon, 9 Jun 2025 12:55:00 -0400 Subject: [PATCH 5/5] flags: Rename `varg` to `overflow`, let it be renamed with config --- core/flags/constants.odin | 2 +- core/flags/doc.odin | 6 +- core/flags/errors.odin | 2 +- core/flags/example/example.odin | 2 +- core/flags/internal_assignment.odin | 4 +- core/flags/internal_parsing.odin | 2 +- core/flags/internal_validation.odin | 4 +- core/flags/usage.odin | 16 ++--- tests/core/flags/test_core_flags.odin | 90 +++++++++++++-------------- 9 files changed, 66 insertions(+), 62 deletions(-) diff --git a/core/flags/constants.odin b/core/flags/constants.odin index 68ac711c1..dc2663e2a 100644 --- a/core/flags/constants.odin +++ b/core/flags/constants.odin @@ -28,7 +28,7 @@ TAG_USAGE :: "usage" UNDOCUMENTED_FLAG :: "" -INTERNAL_VARIADIC_FLAG :: "varg" +INTERNAL_OVERFLOW_FLAG :: #config(ODIN_CORE_FLAGS_OVERFLOW_FLAG, "overflow") RESERVED_HELP_FLAG :: "help" RESERVED_HELP_FLAG_SHORT :: "h" diff --git a/core/flags/doc.odin b/core/flags/doc.odin index 0763c01a7..440acd52c 100644 --- a/core/flags/doc.odin +++ b/core/flags/doc.odin @@ -22,10 +22,14 @@ The format is similar to the Odin binary's way of handling compiler flags. Unhandled Arguments: -All unhandled positional arguments are placed into the `varg` field on a +All unhandled positional arguments are placed into the `overflow` field on a struct, if it exists. In UNIX-style parsing, the existence of a `--` on the command line will also pass all arguments afterwards into this field. +If desired, the name of the field may be changed from `overflow` to any string +by setting the `ODIN_CORE_FLAGS_OVERFLOW_FLAG` compile-time config option with +`-define:ODIN_CORE_FLAGS_OVERFLOW_FLAG=`. + Struct Tags: diff --git a/core/flags/errors.odin b/core/flags/errors.odin index 6e48f6ccf..3d34a95d3 100644 --- a/core/flags/errors.odin +++ b/core/flags/errors.odin @@ -4,7 +4,7 @@ import "core:os" Parse_Error_Reason :: enum { None, - // An extra positional argument was given, and there is no `varg` field. + // An extra positional argument was given, and there is no `overflow` field. Extra_Positional, // The underlying type does not support the string value it is being set to. Bad_Value, diff --git a/core/flags/example/example.odin b/core/flags/example/example.odin index 1988eb3ee..a3af44790 100644 --- a/core/flags/example/example.odin +++ b/core/flags/example/example.odin @@ -114,7 +114,7 @@ main :: proc() { verbose: bool `usage:"Show verbose output."`, debug: bool `args:"hidden" usage:"print debug info"`, - varg: [dynamic]string `usage:"Any extra arguments go here."`, + overflow: [dynamic]string `usage:"Any extra arguments go here."`, } opt: Options diff --git a/core/flags/internal_assignment.odin b/core/flags/internal_assignment.odin index 3543dba37..5999dbf2d 100644 --- a/core/flags/internal_assignment.odin +++ b/core/flags/internal_assignment.odin @@ -33,9 +33,9 @@ push_positional :: #force_no_inline proc (model: ^$T, parser: ^Parser, arg: stri field, index, has_pos_assigned := get_field_by_pos(model, pos) if !has_pos_assigned { - when intrinsics.type_has_field(T, INTERNAL_VARIADIC_FLAG) { + when intrinsics.type_has_field(T, INTERNAL_OVERFLOW_FLAG) { // Add it to the fallback array. - field = reflect.struct_field_by_name(T, INTERNAL_VARIADIC_FLAG) + field = reflect.struct_field_by_name(T, INTERNAL_OVERFLOW_FLAG) } else { return Parse_Error { .Extra_Positional, diff --git a/core/flags/internal_parsing.odin b/core/flags/internal_parsing.odin index 4e49f45b0..6d544e5af 100644 --- a/core/flags/internal_parsing.odin +++ b/core/flags/internal_parsing.odin @@ -95,7 +95,7 @@ parse_one_unix_arg :: proc(model: ^$T, parser: ^Parser, arg: string) -> ( // `--`, and only `--`. // Everything from now on will be treated as an argument. future_args = max(int) - current_flag = INTERNAL_VARIADIC_FLAG + current_flag = INTERNAL_OVERFLOW_FLAG return } } diff --git a/core/flags/internal_validation.odin b/core/flags/internal_validation.odin index b68df8cb5..cd903c3e5 100644 --- a/core/flags/internal_validation.odin +++ b/core/flags/internal_validation.odin @@ -80,7 +80,7 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ fmt.assertf(!reflect.is_boolean(field.type), "%T.%s is a required boolean. This is disallowed.", model_type, field.name, loc = loc) - fmt.assertf(field.name != INTERNAL_VARIADIC_FLAG, "%T.%s is defined as required. This is disallowed.", + fmt.assertf(field.name != INTERNAL_OVERFLOW_FLAG, "%T.%s is defined as required. This is disallowed.", model_type, field.name, loc = loc) if len(requirement) > 0 { @@ -113,7 +113,7 @@ validate_structure :: proc(model_type: $T, style: Parsing_Style, loc := #caller_ if length, is_manifold := get_struct_subtag(args_tag, SUBTAG_MANIFOLD); is_manifold { fmt.assertf(!has_pos, "%T.%s has both `%s` and `%s` defined. This is disallowed.\n\tSuggestion: Use a dynamic array field named `%s` to accept unspecified positional arguments.", - model_type, field.name, SUBTAG_POS, SUBTAG_MANIFOLD, INTERNAL_VARIADIC_FLAG, loc = loc) + model_type, field.name, SUBTAG_POS, SUBTAG_MANIFOLD, INTERNAL_OVERFLOW_FLAG, loc = loc) if value, parse_ok := strconv.parse_u64_of_base(length, 10); parse_ok { fmt.assertf(value > 0, diff --git a/core/flags/usage.odin b/core/flags/usage.odin index 92cf21cdb..a44baec81 100644 --- a/core/flags/usage.odin +++ b/core/flags/usage.odin @@ -38,10 +38,10 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty // POSITIONAL+REQUIRED, POSITIONAL, REQUIRED, NON_REQUIRED+NON_POSITIONAL, ... // sort_flags :: proc(i, j: Flag) -> slice.Ordering { - // `varg` goes to the end. - if i.name == INTERNAL_VARIADIC_FLAG { + // `overflow` goes to the end. + if i.name == INTERNAL_OVERFLOW_FLAG { return .Greater - } else if j.name == INTERNAL_VARIADIC_FLAG { + } else if j.name == INTERNAL_OVERFLOW_FLAG { return .Less } @@ -147,7 +147,7 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty case runtime.Type_Info_Dynamic_Array: requirement_spec := describe_array_requirements(flag) - if flag.is_manifold || flag.name == INTERNAL_VARIADIC_FLAG { + if flag.is_manifold || flag.name == INTERNAL_OVERFLOW_FLAG { if flag.manifold_length == 0 { flag.type_description = fmt.tprintf("<%v, ...>%s", specific_type_info.elem.id, @@ -177,7 +177,7 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty } } - if flag.name == INTERNAL_VARIADIC_FLAG { + if flag.name == INTERNAL_OVERFLOW_FLAG { flag.full_length = len(flag.type_description) } else if flag.is_boolean { flag.full_length = len(flag_prefix) + len(flag.name) + len(flag.type_description) @@ -201,13 +201,13 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty strings.write_string(&builder, program) for flag in visible_flags { - if keep_it_short && !(flag.is_required || flag.is_positional || flag.name == INTERNAL_VARIADIC_FLAG) { + if keep_it_short && !(flag.is_required || flag.is_positional || flag.name == INTERNAL_OVERFLOW_FLAG) { continue } strings.write_byte(&builder, ' ') - if flag.name == INTERNAL_VARIADIC_FLAG { + if flag.name == INTERNAL_OVERFLOW_FLAG { strings.write_string(&builder, "...") continue } @@ -252,7 +252,7 @@ write_usage :: proc(out: io.Writer, data_type: typeid, program: string = "", sty strings.write_byte(&builder, '\t') - if flag.name == INTERNAL_VARIADIC_FLAG { + if flag.name == INTERNAL_OVERFLOW_FLAG { strings.write_string(&builder, flag.type_description) } else { strings.write_string(&builder, flag_prefix) diff --git a/tests/core/flags/test_core_flags.odin b/tests/core/flags/test_core_flags.odin index dd2074144..0527d85c5 100644 --- a/tests/core/flags/test_core_flags.odin +++ b/tests/core/flags/test_core_flags.odin @@ -454,44 +454,44 @@ test_arrays :: proc(t: ^testing.T) { @(test) test_varargs :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]string, + overflow: [dynamic]string, } s: S args := [?]string { "abc", "foo", "bar" } result := flags.parse(&s, args[:]) - defer delete(s.varg) + defer delete(s.overflow) testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 3) + testing.expect_value(t, len(s.overflow), 3) - if len(s.varg) < 3 { + if len(s.overflow) < 3 { return } - testing.expect_value(t, s.varg[0], "abc") - testing.expect_value(t, s.varg[1], "foo") - testing.expect_value(t, s.varg[2], "bar") + testing.expect_value(t, s.overflow[0], "abc") + testing.expect_value(t, s.overflow[1], "foo") + testing.expect_value(t, s.overflow[2], "bar") } @(test) test_mixed_varargs :: proc(t: ^testing.T) { S :: struct { input: string `args:"pos=0"`, - varg: [dynamic]string, + overflow: [dynamic]string, } s: S args := [?]string { "abc", "foo", "bar" } result := flags.parse(&s, args[:]) - defer delete(s.varg) + defer delete(s.overflow) testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 2) + testing.expect_value(t, len(s.overflow), 2) - if len(s.varg) < 2 { + if len(s.overflow) < 2 { return } testing.expect_value(t, s.input, "abc") - testing.expect_value(t, s.varg[0], "foo") - testing.expect_value(t, s.varg[1], "bar") + testing.expect_value(t, s.overflow[0], "foo") + testing.expect_value(t, s.overflow[1], "bar") } @(test) @@ -718,23 +718,23 @@ test_tags_required_limit_max :: proc(t: ^testing.T) { test_tags_pos_out_of_order :: proc(t: ^testing.T) { S :: struct { a: int `args:"pos=2"`, - varg: [dynamic]int, + overflow: [dynamic]int, } s: S args := [?]string { "1", "2", "3", "4" } result := flags.parse(&s, args[:]) - defer delete(s.varg) + defer delete(s.overflow) testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 3) + testing.expect_value(t, len(s.overflow), 3) - if len(s.varg) < 3 { + if len(s.overflow) < 3 { return } testing.expect_value(t, s.a, 3) - testing.expect_value(t, s.varg[0], 1) - testing.expect_value(t, s.varg[1], 2) - testing.expect_value(t, s.varg[2], 4) + testing.expect_value(t, s.overflow[0], 1) + testing.expect_value(t, s.overflow[1], 2) + testing.expect_value(t, s.overflow[2], 4) } @(test) @@ -899,7 +899,7 @@ test_pos_nonoverlap :: proc(t: ^testing.T) { @(test) test_pos_many_args :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]int, + overflow: [dynamic]int, a: int `args:"pos=0,required"`, b: int `args:"pos=64,required"`, c: int `args:"pos=66,required"`, @@ -908,7 +908,7 @@ test_pos_many_args :: proc(t: ^testing.T) { s: S args: [dynamic]string - defer delete(s.varg) + defer delete(s.overflow) for i in 0 ..< 130 { append(&args, fmt.aprintf("%i", 1 + i)) } defer { @@ -922,14 +922,14 @@ test_pos_many_args :: proc(t: ^testing.T) { testing.expect_value(t, result, nil) testing.expect_value(t, s.a, 1) - for i in 1 ..< 63 { testing.expect_value(t, s.varg[i], 2 + i) } + for i in 1 ..< 63 { testing.expect_value(t, s.overflow[i], 2 + i) } testing.expect_value(t, s.b, 65) - testing.expect_value(t, s.varg[63], 66) + testing.expect_value(t, s.overflow[63], 66) testing.expect_value(t, s.c, 67) - testing.expect_value(t, s.varg[64], 68) - testing.expect_value(t, s.varg[65], 69) - testing.expect_value(t, s.varg[66], 70) - for i in 67 ..< 126 { testing.expect_value(t, s.varg[i], 4 + i) } + testing.expect_value(t, s.overflow[64], 68) + testing.expect_value(t, s.overflow[65], 69) + testing.expect_value(t, s.overflow[66], 70) + for i in 67 ..< 126 { testing.expect_value(t, s.overflow[i], 4 + i) } testing.expect_value(t, s.d, 130) } @@ -1135,7 +1135,7 @@ test_unix_positional :: proc(t: ^testing.T) { @(test) test_unix_positional_with_manifold :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]int, + overflow: [dynamic]int, v: [dynamic]int `args:"manifold"`, } s: S @@ -1144,18 +1144,18 @@ test_unix_positional_with_manifold :: proc(t: ^testing.T) { result := flags.parse(&s, args[:], .Unix) defer { - delete(s.varg) + delete(s.overflow) delete(s.v) } testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 1) + testing.expect_value(t, len(s.overflow), 1) testing.expect_value(t, len(s.v), 2) } @(test) test_unix_double_dash_varargs :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]string, + overflow: [dynamic]string, i: int, } s: S @@ -1164,19 +1164,19 @@ test_unix_double_dash_varargs :: proc(t: ^testing.T) { result := flags.parse(&s, args[:], .Unix) defer { - delete(s.varg) + delete(s.overflow) } testing.expect_value(t, result, nil) - testing.expect_value(t, len(s.varg), 3) + testing.expect_value(t, len(s.overflow), 3) testing.expect_value(t, s.i, 3) - if len(s.varg) != 3 { + if len(s.overflow) != 3 { return } - testing.expect_value(t, s.varg[0], "hellope") - testing.expect_value(t, s.varg[1], "-i") - testing.expect_value(t, s.varg[2], "5") + testing.expect_value(t, s.overflow[0], "hellope") + testing.expect_value(t, s.overflow[1], "-i") + testing.expect_value(t, s.overflow[2], "5") } @(test) @@ -1200,17 +1200,17 @@ test_unix_no_value :: proc(t: ^testing.T) { @(test) test_if_dynamic_cstrings_get_freed :: proc(t: ^testing.T) { S :: struct { - varg: [dynamic]cstring, + overflow: [dynamic]cstring, } s: S args := [?]string { "Hellope", "world!" } result := flags.parse(&s, args[:]) defer { - for v in s.varg { + for v in s.overflow { delete(v) } - delete(s.varg) + delete(s.overflow) } testing.expect_value(t, result, nil) } @@ -1428,7 +1428,7 @@ very nicely. debug: bool `args:"hidden" usage:"print debug info"`, verbose: bool, - varg: [dynamic]string, + overflow: [dynamic]string, } builder := strings.builder_make() @@ -1441,7 +1441,7 @@ very nicely. @(test) test_usage_write_unix :: proc(t: ^testing.T) { Expected_Output :: `Usage: - varg required-number [number] [name] --bars --bots --foos --gadgets --manifold-flag --widgets [--array] [--count] [--greek] [--verbose] ... + overflow required-number [number] [name] --bars --bots --foos --gadgets --manifold-flag --widgets [--array] [--count] [--greek] [--verbose] ... Flags: --required-number , required | some number --number | some other number @@ -1493,12 +1493,12 @@ very nicely. debug: bool `args:"hidden" usage:"print debug info"`, verbose: bool, - varg: [dynamic]string, + overflow: [dynamic]string, } builder := strings.builder_make() defer strings.builder_destroy(&builder) writer := strings.to_stream(&builder) - flags.write_usage(writer, S, "varg", .Unix) + flags.write_usage(writer, S, "overflow", .Unix) testing.expect_value(t, strings.to_string(builder), Expected_Output) }