summaryrefslogtreecommitdiff
path: root/input.go
blob: 6207c07e123c436074d4bb019b315a9c150be1fc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
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)
}