master
1package main
2
3import (
4 "fmt"
5 "strings"
6)
7
8// Command stores the information for running a command
9type Command struct {
10 Command,
11 Description,
12 Usage string
13 Flags map[string]Flag
14 PositionalParameters []string
15 Run func(Command) error
16}
17
18type Commands []Command
19
20// Flag servers to store command flags for the program commands
21// if HasArgs is true, then the flag MUST have an argument
22type Flag struct {
23 Flag,
24 Description,
25 Usage,
26 Value string
27 HasArgs bool
28 Args []string
29}
30
31// Swap swaps i and j
32func (commands Commands) Swap(i, j int) {
33 commands[i], commands[j] = commands[j], commands[i]
34}
35
36// Less returns true if i is less than j
37func (a Commands) Less(i, j int) bool {
38 return strings.Compare(a[i].Command, a[j].Command) < 0
39}
40
41// Len returns the number of commands contained
42// in this struct
43func (a Commands) Len() int {
44 return len(a)
45}
46
47// selectCommand takes a string and converts it to the correct command
48func SelectCommand(str string, commandArray []Command) (Command, error) {
49 for _, value := range commandArray {
50 if strings.Compare(value.Command, str) == 0 {
51 return value, nil
52 }
53 }
54 return Command{}, fmt.Errorf("No command found for: %s", str)
55}
56
57// expandShortOptions takes condensed short options and
58// expands them into properly formatted short options
59func expandShortOptions(shorts string) []string {
60 var options = make([]string, (len(shorts)-1)*2)
61 for char := range shorts {
62 options = append(options, "-"+string(char))
63 }
64 return options
65}
66
67// parseUserCommands takes a user string and parses it into separate
68// flags for the specified command, placing the values into the
69// specified struct. invalid flags cause an error
70func ParseUserCommands(args []string, command *Command) error {
71 flagString := ""
72 for len(args) > 0 {
73 if strings.HasPrefix(args[0], "-") {
74 if strings.HasPrefix(args[0], "--") {
75 flagString = args[0][2:]
76 } else if len(args[0]) > 2 { // multiple short options at once
77 args = append(expandShortOptions(args[0]), args...)
78 continue
79 } else { // only 1 short option
80 flagString = args[0][1:]
81 }
82 for key, flagValue := range command.Flags {
83 if flagString == flagValue.Flag {
84 if flagValue.HasArgs {
85 if len(args) < 2 {
86 return fmt.Errorf("Not enough arguments for %s", flagString)
87 }
88 flagValue.Value = args[1]
89 } else {
90 flagValue.Value = "true"
91 }
92 command.Flags[key] = flagValue
93 }
94 }
95 } else { // flags have been handled
96 command.PositionalParameters = args
97 }
98 args = args[1:]
99 }
100 return nil
101}