commandline.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package fairwind
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "os"
  6. "reflect"
  7. "strings"
  8. )
  9. type CommandHandler func(Parameters) error
  10. type Parameter struct {
  11. Kind reflect.Kind
  12. Required bool
  13. Value reflect.Value `json:"-"`
  14. }
  15. type Parameters map[string]*Parameter
  16. type Command struct {
  17. Name string
  18. Documentation string
  19. Parameters Parameters
  20. Handler CommandHandler `json:"-"`
  21. Commands []Command
  22. }
  23. func (this *Command) Execute() {
  24. parts := os.Args[1:]
  25. if len(parts) == 0 {
  26. this.manual()
  27. return
  28. }
  29. currentCommand := this
  30. index := -1
  31. for i, part := range parts {
  32. if strings.Contains(part, "--") {
  33. index = i
  34. break
  35. }
  36. found := false
  37. for _, iteratedCommand := range currentCommand.Commands {
  38. if iteratedCommand.Name != part {
  39. continue
  40. }
  41. currentCommand = &iteratedCommand
  42. found = true
  43. break
  44. }
  45. if !found {
  46. fmt.Println("Command not found")
  47. os.Exit(1)
  48. }
  49. }
  50. parameters := Parameters{}
  51. fail := false
  52. if index >= 0 {
  53. for i := index; i < len(parts); i++ {
  54. part := parts[i]
  55. keyValue := strings.Split(part, "=")
  56. if len(keyValue) != 2 {
  57. fmt.Printf("Invalid argument: %s\n", part)
  58. os.Exit(1)
  59. }
  60. key := keyValue[0]
  61. value := keyValue[1]
  62. parameter, ok := currentCommand.Parameters[key]
  63. if !ok {
  64. fmt.Printf("Invalid argument: %s=%s\n", key, value)
  65. fail = true
  66. continue
  67. }
  68. switch parameter.Kind {
  69. case reflect.String:
  70. parameters[key[2:]] = &Parameter{
  71. Value: reflect.ValueOf(value),
  72. }
  73. }
  74. }
  75. }
  76. if fail {
  77. os.Exit(1)
  78. }
  79. for key, parameter := range currentCommand.Parameters {
  80. if !parameter.Required {
  81. continue
  82. }
  83. _, ok := parameters[key[2:]]
  84. if !ok {
  85. fmt.Printf("Argument required: %s\n", key)
  86. fail = true
  87. }
  88. }
  89. if fail {
  90. os.Exit(1)
  91. }
  92. if currentCommand.Handler == nil {
  93. fmt.Println("Handler for command not set")
  94. os.Exit(1)
  95. }
  96. err := currentCommand.Handler(parameters)
  97. if err != nil {
  98. fmt.Printf("Execution error: %v\n", err)
  99. os.Exit(1)
  100. }
  101. }
  102. func (this *Command) manual() {
  103. buffer, err := json.Marshal(this)
  104. if err != nil {
  105. fmt.Printf("Execution error: %v\n", err)
  106. os.Exit(1)
  107. }
  108. fmt.Println(string(buffer))
  109. }