Commit c92ca42
Changed files (2)
client.go
@@ -5,6 +5,7 @@ import (
"flag"
"fmt"
"github.com/BurntSushi/toml"
+ "github.com/richluby/commander"
"log"
"os"
"strconv"
@@ -49,7 +50,7 @@ func initUserSession() {
//client := &http.Client{}
fmt.Printf("%s", "Welcome to the question interface. Use 'help' for more information.")
var input string
- var command Command
+ var command commander.Command
var err error
reader := bufio.NewReader(os.Stdin)
for {
@@ -64,12 +65,19 @@ func initUserSession() {
continue
}
// select a command from the list of available commands
- if command, err = selectCommand(strings.TrimSpace(args[0])); err != nil {
+ if command, err = commander.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)
+ 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(args[1:]); err != nil {
+ if err = command.Run(command); err != nil {
log.Printf(COLOR_RED+"Error while executing command: %+v"+COLOR_RESET, err)
}
}
command.go
@@ -5,6 +5,7 @@ import (
"bytes"
"encoding/json"
"fmt"
+ "github.com/richluby/commander"
"io/ioutil"
"log"
"net/http"
@@ -13,108 +14,92 @@ import (
"strings"
)
-// Command stores the information for running a command
-type Command struct {
- Command,
- Description,
- Usage string
- Flags []Flag
- Run func(args []string) error
-}
-
-// Flag servers to store command flags for the program commands
-type Flag struct {
- Flag,
- Description,
- Usage,
- Value string
-}
-
-// selectCommand takes a string and converts it to the correct command
-func selectCommand(str string) (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)
-}
-
// commandArray contains the full list of commands available to the application
// note that subcommands are not currently supported
-var commandArray = []Command{
- Command{Command: "exit",
- Description: "Exit the self-assessment application and close the connection.",
- Run: func(args []string) error {
- fmt.Print("Exiting application.\n")
- os.Exit(0)
- return nil
- }},
- Command{Command: "score",
+var commandArray = []commander.Command{commander.Command{Command: "exit",
+ Description: "Exit the self-assessment application and close the connection.",
+ Run: func(command commander.Command) error {
+ fmt.Print("Exiting application.\n")
+ os.Exit(0)
+ return nil
+ }},
+ commander.Command{Command: "score",
Description: "Display the score for the user.",
- Run: func(args []string) error {
+ Run: func(command commander.Command) error {
fmt.Print("score was run.")
return nil
}},
- Command{Command: "test",
+ commander.Command{Command: "test",
Usage: "test [flags]",
- Flags: []Flag{Flag{
+ Flags: map[string]commander.Flag{"blueprint": commander.Flag{
Flag: "blueprint",
Usage: "--blueprint",
Description: "Allows to define a list of categories to use",
- Value: "NONE"},
- Flag{
+ Value: "false"},
+ "questions": commander.Flag{
Flag: "questions",
Usage: "--questions [n]",
+ HasArgs: true,
Description: "Specify the number of questions to pull. Default is 20.",
Value: ""}},
Description: "Execute a test. Given a number, will go through a test with [n] questions." +
" Type 'exit' to stop test.",
Run: executeTest},
- Command{
+ commander.Command{
Command: "user",
Usage: "user <username> <token>",
+ Flags: map[string]commander.Flag{"username": commander.Flag{Flag: "username",
+ Description: "The username to use for this session",
+ Value: "anonymous",
+ Usage: ""}},
Description: "Set the user name to utilize during this session. If not set, anonymous will be used." +
COLOR_GREEN + " token" + COLOR_RESET + " is a unique, non-secret key to prevent duplicate users from occurring.",
- Run: func(args []string) error {
- if len(args) < 1 {
- return fmt.Errorf("Could not set the user due to empty username.")
- } else if len(args) < 2 {
- return fmt.Errorf("Could not set the user due to the lack of a user token.")
- }
- clientConfig.USER = args[0]
- return nil
- }}}
+ Run: setUserName}}
+
+// sets the user name for this session
+func setUserName(command commander.Command) error {
+ if command.Flags["username"].Value == "" {
+ return fmt.Errorf("Could not set the user due to empty username.")
+ } else if command.Flags[""].Value == "" {
+ return fmt.Errorf("Could not set the user due to the lack of a user token.")
+ }
+ clientConfig.USER = command.Flags["username"].Value
+ return nil
+}
// helpCommand prints the help for the list of available commands.
// it cannot exist in the initialization due to initialization loops
-var helpCommand = Command{Command: "help",
+var helpCommand = commander.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.",
- Run: func(args []string) error {
- for _, command := range commandArray {
- if len(args) > 0 && args[0] != command.Command { // only print help for desired command
- continue
- }
- if strings.Compare(command.Usage, "") == 0 { // print command help
- fmt.Printf("> %s\n\t%s\n", COLOR_GREEN+command.Command+COLOR_RESET, command.Description)
- } else {
- fmt.Printf("> %s\n\t%s\n", COLOR_GREEN+command.Usage+COLOR_RESET, command.Description)
- }
- if len(command.Flags) > 0 { // print flag help
- fmt.Print(COLOR_BOLD + "\tFLAGS\n" + COLOR_RESET)
- for _, commandFlag := range command.Flags {
- if commandFlag.Usage != "" {
- fmt.Printf("\t%s\n\t\t%s\n", COLOR_BLUE+commandFlag.Usage+COLOR_RESET, commandFlag.Description)
- } else {
- fmt.Printf("\t%s\n\t\t%s\n", COLOR_BLUE+commandFlag.Flag+COLOR_RESET, commandFlag.Description)
- }
+ Run: displayHelp}
+
+// displayHelp prints the help. if a command is specified,
+// help is displayed for that particular command
+func displayHelp(command commander.Command) error {
+ for _, checkCommand := range commandArray {
+ if command.Flags["command"].Value != "" && command.Flags["command"].Value != checkCommand.Command { // only print help for desired command
+ continue
+ }
+ if strings.Compare(checkCommand.Usage, "") == 0 { // print command help
+ fmt.Printf("> %s\n\t%s\n", COLOR_GREEN+checkCommand.Command+COLOR_RESET, checkCommand.Description)
+ } else {
+ fmt.Printf("> %s\n\t%s\n", COLOR_GREEN+checkCommand.Usage+COLOR_RESET, checkCommand.Description)
+ }
+ if len(checkCommand.Flags) > 0 { // print flag help
+ fmt.Print(COLOR_BOLD + "\tFLAGS\n" + COLOR_RESET)
+ for _, commandFlag := range checkCommand.Flags {
+ if commandFlag.Usage != "" {
+ fmt.Printf("\t%s\n\t\t%s\n", COLOR_BLUE+commandFlag.Usage+COLOR_RESET, commandFlag.Description)
+ } else {
+ fmt.Printf("\t%s\n\t\t%s\n", COLOR_BLUE+commandFlag.Flag+COLOR_RESET, commandFlag.Description)
}
}
}
- return nil
- }}
+ }
+ return nil
+}
// init initializes the commandArray to provide a single interface
func init() {
@@ -170,7 +155,7 @@ func postRecordsToServer(client *http.Client, recordArray *ClientTest) error {
}
// getRecordFromServer retrieves a record from the server
-func getRecordFromServer(client *http.Client, config CLIENT_CONFIG, numQuestions int) ([]ClientRecord, error) {
+func getRecordFromServer(client *http.Client, config CLIENT_CONFIG, numQuestions int, useBlueprint bool) ([]ClientRecord, error) {
// allows adding configuration for port specific (ie HTTPS) requests
resp, err := client.Get(clientConfig.SERVER_URL + API_ROOT + "/test" + "?questions=" + strconv.Itoa(numQuestions))
if err != nil {
@@ -189,7 +174,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(args []string) error {
+func getCategoriesFromServer(command commander.Command) error {
client := &http.Client{}
resp, err := client.Get(clientConfig.SERVER_URL + API_ROOT + "/questions/categories")
if err != nil {
@@ -206,29 +191,43 @@ func getCategoriesFromServer(args []string) error {
}
// parseTestCommandFlags parses the flags for the test command
-func parseTestCommandFlags(args []string) {
-
+func parseTestCommandFlags(command commander.Command) (int, bool, error) {
+ questions := 20
+ var err error
+ useBlueprint := false
+ for key, commandFlag := range command.Flags {
+ switch key {
+ case "blueprint":
+ if commandFlag.Value != "false" {
+ useBlueprint = true
+ }
+ case "questions":
+ if commandFlag.Value != "" {
+ questions, err = strconv.Atoi(commandFlag.Value)
+ }
+ }
+ }
+ return questions, useBlueprint, err
}
// executeTest runs a user through a test
// from retrieving the records to returning the answers
-func executeTest(args []string) error {
+func executeTest(command commander.Command) error {
client := &http.Client{}
var clientTest ClientTest
var err error
questions := 20
- if len(args) > 0 {
- questions, err = strconv.Atoi(args[0])
- if err != nil {
- return fmt.Errorf("Error while converting to number: %+v", err)
- }
+ useBluprint := false
+ questions, useBluprint, err = parseTestCommandFlags(command)
+ if err != nil {
+ return fmt.Errorf("Error while parsing flags for test: %+v", err)
}
- clientTest.Records, err = getRecordFromServer(client, clientConfig, questions)
+ clientTest.Records, err = getRecordFromServer(client, clientConfig, questions, useBluprint)
if err != nil {
return fmt.Errorf("Error while requesting test from server: %+v", err)
}
clientTest.Username = clientConfig.USER
- if err = getCategoriesFromServer(nil); err != nil {
+ if err = getCategoriesFromServer(commander.Command{}); err != nil {
return fmt.Errorf("Error while pulling server categories: %+v", err)
}
runTest(&clientTest)