From edb685f04be9aef407dc8abac7bb76fb51184f9f Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:35:43 -0400 Subject: Add package `core:flags` --- core/flags/example/example.odin | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 core/flags/example/example.odin (limited to 'core/flags/example/example.odin') diff --git a/core/flags/example/example.odin b/core/flags/example/example.odin new file mode 100644 index 000000000..b1d7b58d6 --- /dev/null +++ b/core/flags/example/example.odin @@ -0,0 +1,132 @@ +package core_flags_example + +import "base:runtime" +import "core:flags" +import "core:fmt" +import "core:net" +import "core:os" +import "core:time/datetime" + + +Fixed_Point1_1 :: struct { + integer: u8, + fractional: u8, +} + +Optimization_Level :: enum { + Slow, + Fast, + Warp_Speed, + Ludicrous_Speed, +} + +// It's simple but powerful. +my_custom_type_setter :: proc( + data: rawptr, + data_type: typeid, + unparsed_value: string, + args_tag: string, +) -> ( + error: string, + handled: bool, + alloc_error: runtime.Allocator_Error, +) { + if data_type == Fixed_Point1_1 { + handled = true + ptr := cast(^Fixed_Point1_1)data + + // precision := flags.get_subtag(args_tag, "precision") + + if len(unparsed_value) == 3 { + ptr.integer = unparsed_value[0] - '0' + ptr.fractional = unparsed_value[2] - '0' + } else { + error = "Incorrect format. Must be in the form of `i.f`." + } + + // Perform sanity checking here in the type parsing phase. + // + // The validation phase is flag-specific. + if !(0 <= ptr.integer && ptr.integer < 10) || !(0 <= ptr.fractional && ptr.fractional < 10) { + error = "Incorrect format. Must be between `0.0` and `9.9`." + } + } + + return +} + +my_custom_flag_checker :: proc( + model: rawptr, + name: string, + value: any, + args_tag: string, +) -> (error: string) { + if name == "iterations" { + v := value.(int) + if !(1 <= v && v < 5) { + error = "Iterations only supports 1 ..< 5." + } + } + + return +} + +Distinct_Int :: distinct int + +main :: proc() { + Options :: struct { + + file: os.Handle `args:"pos=0,required,file=r" usage:"Input file."`, + output: os.Handle `args:"pos=1,file=cw" usage:"Output file."`, + + hub: net.Host_Or_Endpoint `usage:"Internet address to contact for updates."`, + schedule: datetime.DateTime `usage:"Launch tasks at this time."`, + + opt: Optimization_Level `usage:"Optimization level."`, + todo: [dynamic]string `usage:"Todo items."`, + + accuracy: Fixed_Point1_1 `args:"required" usage:"Lenience in FLOP calculations."`, + iterations: int `usage:"Run this many times."`, + + // Note how the parser will transform this flag's name into `special-int`. + special_int: Distinct_Int `args:"indistinct" usage:"Able to set distinct types."`, + + quat: quaternion256, + + bits: bit_set[0..<8], + + // Many different requirement styles: + + // gadgets: [dynamic]string `args:"required=1" usage:"gadgets"`, + // widgets: [dynamic]string `args:"required=<3" usage:"widgets"`, + // foos: [dynamic]string `args:"required=2<4"`, + // bars: [dynamic]string `args:"required=3<4"`, + // bots: [dynamic]string `args:"required"`, + + // (Maps) Only available in Odin style: + + // assignments: map[string]u8 `args:"name=assign" usage:"Number of jobs per worker."`, + + // (Variadic) Only available in UNIX style: + + // bots: [dynamic]string `args:"variadic=2,required"`, + + verbose: bool `usage:"Show verbose output."`, + debug: bool `args:"hidden" usage:"print debug info"`, + + varg: [dynamic]string `usage:"Any extra arguments go here."`, + } + + opt: Options + style : flags.Parsing_Style = .Odin + + flags.register_type_setter(my_custom_type_setter) + flags.register_flag_checker(my_custom_flag_checker) + flags.parse_or_exit(&opt, os.args, style) + + fmt.printfln("%#v", opt) + + if opt.output != 0 { + os.write_string(opt.output, "Hellope!\n") + } +} -- cgit v1.2.3