Commit 1d3de6e
Changed files (3)
client.go
@@ -5,7 +5,6 @@ import (
"flag"
"fmt"
"github.com/BurntSushi/toml"
- "github.com/richluby/commander"
"log"
"os"
"strconv"
@@ -47,10 +46,9 @@ func loadClientConfiguration(cfgFile string) CLIENT_CONFIG {
// initUserSession starts the interactive prompt for the user
func initUserSession() {
- //client := &http.Client{}
fmt.Printf("%s", "Welcome to the question interface. Use 'help' for more information.")
var input string
- var command commander.Command
+ var command Command
var err error
reader := bufio.NewReader(os.Stdin)
for {
@@ -65,17 +63,16 @@ func initUserSession() {
continue
}
// select a command from the list of available commands
- if command, err = commander.SelectCommand(strings.TrimSpace(args[0]), commandArray); err != nil {
+ if command, err = SelectCommand(strings.TrimSpace(args[0]), commandArray); err != nil {
log.Printf(COLOR_RED+"Error while parsing command: %+v"+COLOR_RESET, err)
continue
}
// parse the flags for the command
- err = commander.ParseUserCommands(args[1:], &command)
+ err = ParseUserCommands(args[1:], &command)
if err != nil {
log.Printf(COLOR_RED+"Error while parsing parameters: %+v"+COLOR_RESET, err)
continue
}
- log.Printf("Flags: %+v", command.Flags)
// execute the command and check for any errors that may have occurred
if err = command.Run(command); err != nil {
log.Printf(COLOR_RED+"Error while executing command: %+v"+COLOR_RESET, err)
command.go
@@ -5,7 +5,6 @@ import (
"bytes"
"encoding/json"
"fmt"
- "github.com/richluby/commander"
"io/ioutil"
"log"
"net/http"
@@ -16,27 +15,27 @@ import (
// commandArray contains the full list of commands available to the application
// note that subcommands are not currently supported
-var commandArray = []commander.Command{commander.Command{Command: "exit",
+var commandArray = []Command{Command{Command: "exit",
Description: "Exit the self-assessment application and close the connection.",
- Run: func(command commander.Command) error {
+ Run: func(command Command) error {
fmt.Print("Exiting application.\n")
os.Exit(0)
return nil
}},
- commander.Command{Command: "score",
+ Command{Command: "score",
Description: "Display the score for the user.",
- Run: func(command commander.Command) error {
+ Run: func(command Command) error {
fmt.Print("score was run.")
return nil
}},
- commander.Command{Command: "test",
+ Command{Command: "test",
Usage: "test [flags]",
- Flags: map[string]commander.Flag{"blueprint": commander.Flag{
+ Flags: map[string]Flag{"blueprint": Flag{
Flag: "blueprint",
Usage: "--blueprint",
Description: "Allows to define a list of categories to use",
Value: "false"},
- "questions": commander.Flag{
+ "questions": Flag{
Flag: "questions",
Usage: "--questions [n]",
HasArgs: true,
@@ -45,10 +44,10 @@ var commandArray = []commander.Command{commander.Command{Command: "exit",
Description: "Execute a test. Given a number, will go through a test with [n] questions." +
" Type 'exit' to stop test.",
Run: executeTest},
- commander.Command{
+ Command{
Command: "user",
Usage: "user <username> <token>",
- Flags: map[string]commander.Flag{"username": commander.Flag{Flag: "username",
+ Flags: map[string]Flag{"username": Flag{Flag: "username",
Description: "The username to use for this session",
Value: "anonymous",
Usage: ""}},
@@ -57,7 +56,7 @@ var commandArray = []commander.Command{commander.Command{Command: "exit",
Run: setUserName}}
// sets the user name for this session
-func setUserName(command commander.Command) error {
+func setUserName(command Command) error {
if command.Flags["username"].Value == "" {
return fmt.Errorf("Could not set the user due to empty username.")
} else if command.Flags[""].Value == "" {
@@ -69,7 +68,7 @@ func setUserName(command commander.Command) error {
// helpCommand prints the help for the list of available commands.
// it cannot exist in the initialization due to initialization loops
-var helpCommand = commander.Command{Command: "help",
+var helpCommand = Command{Command: "help",
Usage: "help [command]",
Description: "Display help for all known commands. If " + COLOR_GREEN + "command" + COLOR_RESET + " is specified, " +
"displays help for that command.",
@@ -77,9 +76,9 @@ var helpCommand = commander.Command{Command: "help",
// displayHelp prints the help. if a command is specified,
// help is displayed for that particular command
-func displayHelp(command commander.Command) error {
+func displayHelp(command Command) error {
for _, checkCommand := range commandArray {
- if command.Flags["command"].Value != "" && command.Flags["command"].Value != checkCommand.Command { // only print help for desired command
+ if len(command.PositionalParameters) > 0 && command.PositionalParameters[0] != checkCommand.Command { // only print help for desired command
continue
}
if strings.Compare(checkCommand.Usage, "") == 0 { // print command help
@@ -174,7 +173,7 @@ func getRecordFromServer(client *http.Client, config CLIENT_CONFIG, numQuestions
// getCategoriesFromServer requests a new list of the available
// categories from the server. functionality provided for
// command integration as well
-func getCategoriesFromServer(command commander.Command) error {
+func getCategoriesFromServer(command Command) error {
client := &http.Client{}
resp, err := client.Get(clientConfig.SERVER_URL + API_ROOT + "/questions/categories")
if err != nil {
@@ -191,7 +190,7 @@ func getCategoriesFromServer(command commander.Command) error {
}
// parseTestCommandFlags parses the flags for the test command
-func parseTestCommandFlags(command commander.Command) (int, bool, error) {
+func parseTestCommandFlags(command Command) (int, bool, error) {
questions := 20
var err error
useBlueprint := false
@@ -212,7 +211,7 @@ func parseTestCommandFlags(command commander.Command) (int, bool, error) {
// executeTest runs a user through a test
// from retrieving the records to returning the answers
-func executeTest(command commander.Command) error {
+func executeTest(command Command) error {
client := &http.Client{}
var clientTest ClientTest
var err error
@@ -227,7 +226,7 @@ func executeTest(command commander.Command) error {
return fmt.Errorf("Error while requesting test from server: %+v", err)
}
clientTest.Username = clientConfig.USER
- if err = getCategoriesFromServer(commander.Command{}); err != nil {
+ if err = getCategoriesFromServer(Command{}); err != nil {
return fmt.Errorf("Error while pulling server categories: %+v", err)
}
runTest(&clientTest)
commandParser.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Command stores the information for running a command
+type Command struct {
+ Command,
+ Description,
+ Usage string
+ Flags map[string]Flag
+ PositionalParameters []string
+ Run func(Command) error
+}
+
+// Flag servers to store command flags for the program commands
+// if HasArgs is true, then the flag MUST have an argument
+type Flag struct {
+ Flag,
+ Description,
+ Usage,
+ Value string
+ HasArgs bool
+ Args []string
+}
+
+// selectCommand takes a string and converts it to the correct command
+func SelectCommand(str string, commandArray []Command) (Command, error) {
+ for _, value := range commandArray {
+ if strings.Compare(value.Command, str) == 0 {
+ return value, nil
+ }
+ }
+ return Command{}, fmt.Errorf("No command found for: %s", str)
+}
+
+// expandShortOptions takes condensed short options and
+// expands them into properly formatted short options
+func expandShortOptions(shorts string) []string {
+ var options = make([]string, len(shorts)-1)
+ for char := range shorts {
+ options = append(options, "-"+string(char))
+ }
+ return options
+}
+
+// parseUserCommands takes a user string and parses it into separate
+// flags for the specified command, placing the values into the
+// specified struct. invalid flags cause an error
+func ParseUserCommands(args []string, command *Command) error {
+ flagString := ""
+ for len(args) > 0 {
+ if strings.HasPrefix(args[0], "-") {
+ if strings.HasPrefix(args[0], "--") {
+ flagString = args[0][2:]
+ } else if len(args[0]) > 2 { // multiple short options at once
+ args = append(expandShortOptions(args[0]), args...)
+ continue
+ } else { // only 1 short option
+ flagString = args[0][1:]
+ }
+ for key, flagValue := range command.Flags {
+ if flagString == flagValue.Flag {
+ if flagValue.HasArgs {
+ if len(args) < 2 {
+ return fmt.Errorf("Not enough arguments for %s", flagString)
+ }
+ flagValue.Value = args[1]
+ }
+ command.Flags[key] = flagValue
+ }
+ }
+ } else { // flags have been handled
+ command.PositionalParameters = args
+ }
+ args = args[1:]
+ }
+ return nil
+}