diff options
Diffstat (limited to 'input.go')
-rw-r--r-- | input.go | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/input.go b/input.go new file mode 100644 index 0000000..6207c07 --- /dev/null +++ b/input.go @@ -0,0 +1,210 @@ +package saggytrousers + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + // "git.gabbott.dev/george/excelize/v2" + xl "anyxcelize" +) + +/* Public Functions */ +/* func GetString(prompt string) string + * func GetInt(prompt string) int + * func GetFloat64(prompt string) float64 + * func SelectSheet(file *xl.File, sheet string) string + * func SelectHeader(f *xl.File, sheet, choice string, exact bool) int + * func UserSelectHeader(f *xl.File, sheet string) ([]string, int) + * func ChooseFromHeader(header []string) int + * func ChooseFromHeaderPrompt(header []string, prompt string) int + * + */ + + func longest(choices []string) int { + l := 0 + for _, v := range choices { + if len(v) > l { + l = len(v) + } + } + return l + } + +// If prompt == "", then prompt with "The options are: \n". +func selectIndexFromArray(choices []string, prompt string, eachOnNewline bool) int { + Log(false, "selectIndexFromArray: choices %v; see below for prompt; eachOnNewline %v\n", choices, eachOnNewline) + length := longest(choices) + Log(true, "%v\n", prompt) + for i, v := range choices { + var separator string + if eachOnNewline { + separator = "\n" + } else if i != 0 && i % 3 == 0 { + separator = "\n\t" + } else { + separator = "\t" + } + fmt.Printf("%s%2d: %-*s", separator, i + 1, length, v) + } + + var answer int + Log(true, "\nWhat is your selection: ") + for { + answer = GetInt("") + Log(false, "selectIndexFromArray: user inputted %v (one-indexed)\n", answer) + if answer < 1 || answer > len(choices) { // one-indexed + Log(true, "Bad selection, try again: ") + continue + } + break + } + + Log(false, "selectIndexFromArray: returning %v (zero-indexed)\n", answer - 1) + return answer - 1 // zero-indexed +} + +func SelectIndexFromArray(choices []string, prompt string, eachOnNewline bool) int { + return selectIndexFromArray(choices, prompt, eachOnNewline) +} + +// Prompt the user with `prompt`, and then return the input. +func GetString(prompt string) string { + var reader = bufio.NewReader(os.Stdin) + + fmt.Printf("%s", prompt) + answer, _ := reader.ReadString('\n') + + Log(false, "GetString returned %v\n", answer) + return answer +} + +// Prompt the user with `prompt`, and then return the integer the user +// enters. If the user does not enter an integer it re-prompts until he does. +func GetInt(prompt string) int { + var reader = bufio.NewReader(os.Stdin) + + fmt.Printf("%s", prompt) + for { + answer, _ := reader.ReadString('\n') + answer = strings.TrimRight(answer, "\n") + answer = strings.TrimRight(answer, " ") + + i, err := strconv.Atoi(answer) + if err != nil { + fmt.Printf("Invalid number, please re-enter: ") + continue + } + + Log(false, "GetInt returned %v\n", i) + return i + } +} + +func GetFloat64(prompt string) float64 { + var reader = bufio.NewReader(os.Stdin) + + fmt.Printf("%s", prompt) + for { + answer, _ := reader.ReadString('\n') + answer = strings.TrimRight(answer, "\n") + answer = strings.TrimRight(answer, " ") + + i, err := strconv.ParseFloat(answer, 64) + if err != nil { + fmt.Printf("Invalid number, please re-enter: ") + continue + } + + return i + } +} + +// Given a list of sheets, prompt the user to select a sheet and return that +// which was selected. +func userSelectSheet(sheets []string) string { + var selected string + + fmt.Println("Please select the sheet that is to be used.") + selectedIdx := selectIndexFromArray(sheets, "", /* each on newline: */ false) + selected = sheets[selectedIdx] + + return selected +} + +// Takes a potentially sheet name, and returns that sheet if it is a valid name +// or prompt the user to select a valid sheet name if it is not. +func SelectSheet(file *xl.File, sheet string) string { + sheetsMap := file.GetSheetMap() + sheets := GetMapValues(sheetsMap) + + // If the passed `sheet` is correct, return it. + if InSlice(sheets, sheet) { + return sheet + } + + // If there is only one sheet in the file, return that. + if len(sheets) == 1 { + // fmt.Printf("Only one sheet: selecting [%s]", sheets[0]) + return sheets[0] + } + + return userSelectSheet(sheets) +} + +// Takes a potential choice from the header row. Returns the index of the +// choice if it is valid, else prompts the user similarly to UserSelectHeader. +func SelectHeader(f *xl.File, sheet, choice string, exact bool) int { + rows, err := f.Rows(sheet) + if err != nil { + fmt.Printf("SelectHeader(sheet: %s, choice: %s, exact: %v: could not get rows to get the header\n", sheet, choice, exact) + os.Exit(-1) + } + rows.Next() + header, err := rows.Columns() + if err != nil { + fmt.Println("SelectHeader: could not get the header.") + os.Exit(-1) + } + + index := Locate(header, choice) + if index != -1 { + return index + } + + // If cannot find, let the user select + fmt.Println("\nPlease select the correct field.") + index = selectIndexFromArray(header, "", /* each on new line: */ false) + + return index +} + +// Have the user select a column from the header, and return both the header +// and the index of the selected value. +func UserSelectHeader(f *xl.File, sheet string) ([]string, int) { + rows, err := f.Rows(sheet) + if err != nil { + fmt.Println("Could not get rows to get the header.") + os.Exit(-1) + } + + rows.Next() + header, err := rows.Columns() + if err != nil { + fmt.Println("Could not get the header.") + os.Exit(-1) + } + + fmt.Println("\nPlease select the correct field.") + index := selectIndexFromArray(header, "Please select the correct field: ", /* each on new line: */ false) + return header, index +} + +func ChooseFromHeader(header []string) int { + return selectIndexFromArray(header, "", /* each on new line: */ false) +} + +func ChooseFromHeaderPrompt(header []string, prompt string) int { + return selectIndexFromArray(header, prompt, /* each on new line: */ false) +} |