example.odin 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. package core_flags_example
  2. import "base:runtime"
  3. import "core:flags"
  4. import "core:fmt"
  5. import "core:net"
  6. import "core:os"
  7. import "core:time/datetime"
  8. Fixed_Point1_1 :: struct {
  9. integer: u8,
  10. fractional: u8,
  11. }
  12. Optimization_Level :: enum {
  13. Slow,
  14. Fast,
  15. Warp_Speed,
  16. Ludicrous_Speed,
  17. }
  18. // It's simple but powerful.
  19. my_custom_type_setter :: proc(
  20. data: rawptr,
  21. data_type: typeid,
  22. unparsed_value: string,
  23. args_tag: string,
  24. ) -> (
  25. error: string,
  26. handled: bool,
  27. alloc_error: runtime.Allocator_Error,
  28. ) {
  29. if data_type == Fixed_Point1_1 {
  30. handled = true
  31. ptr := cast(^Fixed_Point1_1)data
  32. // precision := flags.get_subtag(args_tag, "precision")
  33. if len(unparsed_value) == 3 {
  34. ptr.integer = unparsed_value[0] - '0'
  35. ptr.fractional = unparsed_value[2] - '0'
  36. } else {
  37. error = "Incorrect format. Must be in the form of `i.f`."
  38. }
  39. // Perform sanity checking here in the type parsing phase.
  40. //
  41. // The validation phase is flag-specific.
  42. if !(0 <= ptr.integer && ptr.integer < 10) || !(0 <= ptr.fractional && ptr.fractional < 10) {
  43. error = "Incorrect format. Must be between `0.0` and `9.9`."
  44. }
  45. }
  46. return
  47. }
  48. my_custom_flag_checker :: proc(
  49. model: rawptr,
  50. name: string,
  51. value: any,
  52. args_tag: string,
  53. ) -> (error: string) {
  54. if name == "iterations" {
  55. v := value.(int)
  56. if !(1 <= v && v < 5) {
  57. error = "Iterations only supports 1 ..< 5."
  58. }
  59. }
  60. return
  61. }
  62. Distinct_Int :: distinct int
  63. main :: proc() {
  64. Options :: struct {
  65. file: os.Handle `args:"pos=0,required,file=r" usage:"Input file."`,
  66. output: os.Handle `args:"pos=1,file=cw" usage:"Output file."`,
  67. hub: net.Host_Or_Endpoint `usage:"Internet address to contact for updates."`,
  68. schedule: datetime.DateTime `usage:"Launch tasks at this time."`,
  69. opt: Optimization_Level `usage:"Optimization level."`,
  70. todo: [dynamic]string `usage:"Todo items."`,
  71. accuracy: Fixed_Point1_1 `args:"required" usage:"Lenience in FLOP calculations."`,
  72. iterations: int `usage:"Run this many times."`,
  73. // Note how the parser will transform this flag's name into `special-int`.
  74. special_int: Distinct_Int `args:"indistinct" usage:"Able to set distinct types."`,
  75. quat: quaternion256,
  76. bits: bit_set[0..<8],
  77. // Many different requirement styles:
  78. // gadgets: [dynamic]string `args:"required=1" usage:"gadgets"`,
  79. // widgets: [dynamic]string `args:"required=<3" usage:"widgets"`,
  80. // foos: [dynamic]string `args:"required=2<4"`,
  81. // bars: [dynamic]string `args:"required=3<4"`,
  82. // bots: [dynamic]string `args:"required"`,
  83. // (Maps) Only available in Odin style:
  84. // assignments: map[string]u8 `args:"name=assign" usage:"Number of jobs per worker."`,
  85. // (Variadic) Only available in UNIX style:
  86. // bots: [dynamic]string `args:"variadic=2,required"`,
  87. verbose: bool `usage:"Show verbose output."`,
  88. debug: bool `args:"hidden" usage:"print debug info"`,
  89. varg: [dynamic]string `usage:"Any extra arguments go here."`,
  90. }
  91. opt: Options
  92. style : flags.Parsing_Style = .Odin
  93. flags.register_type_setter(my_custom_type_setter)
  94. flags.register_flag_checker(my_custom_flag_checker)
  95. flags.parse_or_exit(&opt, os.args, style)
  96. fmt.printfln("%#v", opt)
  97. if opt.output != 0 {
  98. os.write_string(opt.output, "Hellope!\n")
  99. }
  100. }