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) }