parsing.odin 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package flags
  2. import "core:strings"
  3. _ :: strings
  4. @(private)
  5. parse_one_arg :: proc(data: ^$T, arg: string, pos: ^int, set_args: ^[dynamic]string) -> (err: Error) {
  6. arg := arg
  7. if strings.has_prefix(arg, "-") {
  8. arg = arg[1:]
  9. if colon := strings.index_byte(arg, ':'); colon != -1 {
  10. flag := arg[:colon]
  11. arg = arg[1 + colon:]
  12. if equals := strings.index_byte(arg, '='); equals != -1 {
  13. // -map:key=value
  14. key := arg[:equals]
  15. value := arg[1 + equals:]
  16. set_key_value(data, flag, key, value) or_return
  17. append(set_args, flag)
  18. } else {
  19. // -flag:option
  20. set_option(data, flag, arg) or_return
  21. append(set_args, flag)
  22. }
  23. } else if equals := strings.index_byte(arg, '='); equals != -1 {
  24. // -flag=option, alternative syntax
  25. flag := arg[:equals]
  26. arg = arg[1 + equals:]
  27. set_option(data, flag, arg) or_return
  28. append(set_args, flag)
  29. } else {
  30. // -flag
  31. set_flag(data, arg) or_return
  32. append(set_args, arg)
  33. }
  34. } else {
  35. // positional
  36. err = add_positional(data, pos^, arg)
  37. pos^ += 1
  38. }
  39. return
  40. }
  41. // Parse a slice of command-line arguments into an annotated struct.
  42. //
  43. // If `validate_args` is set, an error will be returned if all required
  44. // arguments are not set. This step is only completed if there were no errors
  45. // from parsing.
  46. //
  47. // If `strict` is set, an error will cause parsing to stop and the procedure
  48. // will return with the message. Otherwise, parsing will continue and only the
  49. // last error will be returned.
  50. parse :: proc(data: ^$T, args: []string, validate_args: bool = true, strict: bool = true) -> (err: Error) {
  51. // For checking required arguments.
  52. set_args: [dynamic]string
  53. defer delete(set_args)
  54. // Positional argument tracker.
  55. pos := 0
  56. if strict {
  57. for arg in args {
  58. parse_one_arg(data, arg, &pos, &set_args) or_return
  59. }
  60. } else {
  61. for arg in args {
  62. this_error := parse_one_arg(data, arg, &pos, &set_args)
  63. if this_error != nil {
  64. err = this_error
  65. }
  66. }
  67. }
  68. if err == nil && validate_args {
  69. return validate(data, pos, set_args[:])
  70. }
  71. return err
  72. }