Browse code

Extract option parsing to separate file

John Hawthorn authored on 20/06/2016 01:03:47
Showing 4 changed files

... ...
@@ -11,7 +11,7 @@ INSTALL=install
11 11
 INSTALL_PROGRAM=$(INSTALL)
12 12
 INSTALL_DATA=${INSTALL} -m 644
13 13
 
14
-OBJECTS=src/fzy.o src/match.o src/tty.o src/choices.o
14
+OBJECTS=src/fzy.o src/match.o src/tty.o src/choices.o src/options.o
15 15
 TESTOBJECTS=test/fzytest.c src/match.o src/choices.o
16 16
 
17 17
 all: fzy
... ...
@@ -2,21 +2,16 @@
2 2
 #include <string.h>
3 3
 #include <stdlib.h>
4 4
 #include <ctype.h>
5
-#include <getopt.h>
6 5
 #include <limits.h>
7 6
 
8 7
 #include "match.h"
9 8
 #include "tty.h"
10 9
 #include "choices.h"
10
+#include "options.h"
11 11
 
12 12
 #include "../config.h"
13 13
 
14
-static int flag_show_scores = 0;
15
-
16
-static size_t num_lines = 10;
17
-static size_t scrolloff = 1;
18
-
19
-static const char *prompt = "> ";
14
+options_t options;
20 15
 
21 16
 #define SEARCH_SIZE_MAX 4096
22 17
 static char search[SEARCH_SIZE_MAX + 1] = {0};
... ...
@@ -24,7 +19,7 @@ static char search[SEARCH_SIZE_MAX + 1] = {0};
24 19
 static void clear(tty_t *tty) {
25 20
 	tty_setcol(tty, 0);
26 21
 	size_t line = 0;
27
-	while (line++ < num_lines) {
22
+	while (line++ < options.num_lines) {
28 23
 		tty_newline(tty);
29 24
 	}
30 25
 	tty_clearline(tty);
... ...
@@ -42,7 +37,7 @@ static void draw_match(tty_t *tty, const char *choice, int selected) {
42 37
 
43 38
 	size_t maxwidth = tty_getwidth(tty);
44 39
 
45
-	if (flag_show_scores)
40
+	if (options.show_scores)
46 41
 		tty_printf(tty, "(%5.2f) ", score);
47 42
 
48 43
 	if (selected)
... ...
@@ -66,16 +61,17 @@ static void draw_match(tty_t *tty, const char *choice, int selected) {
66 61
 }
67 62
 
68 63
 static void draw(tty_t *tty, choices_t *choices) {
64
+	unsigned int num_lines = options.num_lines;
69 65
 	size_t start = 0;
70 66
 	size_t current_selection = choices->selection;
71
-	if (current_selection + scrolloff >= num_lines) {
72
-		start = current_selection + scrolloff - num_lines + 1;
67
+	if (current_selection + options.scrolloff >= num_lines) {
68
+		start = current_selection + options.scrolloff - num_lines + 1;
73 69
 		if (start + num_lines >= choices_available(choices)) {
74 70
 			start = choices_available(choices) - num_lines;
75 71
 		}
76 72
 	}
77 73
 	tty_setcol(tty, 0);
78
-	tty_printf(tty, "%s%s", prompt, search);
74
+	tty_printf(tty, "%s%s", options.prompt, search);
79 75
 	tty_clearline(tty);
80 76
 	for (size_t i = start; i < start + num_lines; i++) {
81 77
 		tty_printf(tty, "\n");
... ...
@@ -86,7 +82,7 @@ static void draw(tty_t *tty, choices_t *choices) {
86 82
 		}
87 83
 	}
88 84
 	tty_moveup(tty, num_lines);
89
-	tty_setcol(tty, strlen(prompt) + strlen(search));
85
+	tty_setcol(tty, strlen(options.prompt) + strlen(search));
90 86
 	tty_flush(tty);
91 87
 }
92 88
 
... ...
@@ -167,119 +163,40 @@ static void run(tty_t *tty, choices_t *choices) {
167 163
 	} while (1);
168 164
 }
169 165
 
170
-static const char *usage_str =
171
-    ""
172
-    "Usage: fzy [OPTION]...\n"
173
-    " -l, --lines=LINES        Specify how many lines of results to show (default 10)\n"
174
-    " -p, --prompt=PROMPT      Input prompt (default '> ')\n"
175
-    " -q, --query=QUERY        Use QUERY as the initial search string\n"
176
-    " -e, --show-matches=QUERY Output the sorted matches of QUERY\n"
177
-    " -t, --tty=TTY            Specify file to use as TTY device (default /dev/tty)\n"
178
-    " -s, --show-scores        Show the scores of each match\n"
179
-    " -h, --help     Display this help and exit\n"
180
-    " -v, --version  Output version information and exit\n";
181
-
182
-static void usage(const char *argv0) {
183
-	fprintf(stderr, usage_str, argv0);
184
-}
185
-
186
-static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e'},
187
-				   {"query", required_argument, NULL, 'q'},
188
-				   {"lines", required_argument, NULL, 'l'},
189
-				   {"tty", required_argument, NULL, 't'},
190
-				   {"prompt", required_argument, NULL, 'p'},
191
-				   {"show-scores", no_argument, NULL, 's'},
192
-				   {"version", no_argument, NULL, 'v'},
193
-				   {"benchmark", optional_argument, NULL, 'b'},
194
-				   {"help", no_argument, NULL, 'h'},
195
-				   {NULL, 0, NULL, 0}};
196
-
197 166
 int main(int argc, char *argv[]) {
198
-	int benchmark = 0;
199
-	const char *filter = NULL;
200
-	const char *tty_filename = "/dev/tty";
201
-	char c;
202
-	while ((c = getopt_long(argc, argv, "vhse:q:l:t:p:", longopts, NULL)) != -1) {
203
-		switch (c) {
204
-			case 'v':
205
-				printf("%s " VERSION " (c) 2014 John Hawthorn\n", argv[0]);
206
-				exit(EXIT_SUCCESS);
207
-			case 's':
208
-				flag_show_scores = 1;
209
-				break;
210
-			case 'q':
211
-				strncpy(search, optarg, SEARCH_SIZE_MAX);
212
-				break;
213
-			case 'e':
214
-				filter = optarg;
215
-				break;
216
-			case 'b':
217
-				if (optarg) {
218
-					if (sscanf(optarg, "%d", &benchmark) != 1) {
219
-						usage(argv[0]);
220
-						exit(EXIT_FAILURE);
221
-					}
222
-				} else {
223
-					benchmark = 100;
224
-				}
225
-				break;
226
-			case 't':
227
-				tty_filename = optarg;
228
-				break;
229
-			case 'p':
230
-				prompt = optarg;
231
-				break;
232
-			case 'l': {
233
-				int l;
234
-				if (!strcmp(optarg, "max")) {
235
-					l = INT_MAX;
236
-				} else if (sscanf(optarg, "%d", &l) != 1 || l < 3) {
237
-					fprintf(stderr, "Invalid format for --lines: %s\n", optarg);
238
-					fprintf(stderr, "Must be integer in range 3..\n");
239
-					usage(argv[0]);
240
-					exit(EXIT_FAILURE);
241
-				}
242
-				num_lines = l;
243
-			} break;
244
-			case 'h':
245
-			default:
246
-				usage(argv[0]);
247
-				exit(EXIT_SUCCESS);
248
-		}
249
-	}
250
-	if (optind != argc) {
251
-		usage(argv[0]);
252
-		exit(EXIT_FAILURE);
253
-	}
167
+	options_parse(&options, argc, argv);
254 168
 
255 169
 	choices_t choices;
256 170
 	choices_init(&choices);
257 171
 	choices_fread(&choices, stdin);
258 172
 
259
-	if (benchmark) {
260
-		if (!filter) {
173
+	if (options.benchmark) {
174
+		if (!options.filter) {
261 175
 			fprintf(stderr, "Must specify -e/--show-matches with --benchmark\n");
262 176
 			exit(EXIT_FAILURE);
263 177
 		}
264
-		for (int i = 0; i < benchmark; i++)
265
-			choices_search(&choices, filter);
266
-	} else if (filter) {
267
-		choices_search(&choices, filter);
178
+		for (int i = 0; i < options.benchmark; i++)
179
+			choices_search(&choices, options.filter);
180
+	} else if (options.filter) {
181
+		choices_search(&choices, options.filter);
268 182
 		for (size_t i = 0; i < choices_available(&choices); i++) {
269
-			if (flag_show_scores)
183
+			if (options.show_scores)
270 184
 				printf("%f\t", choices_getscore(&choices, i));
271 185
 			printf("%s\n", choices_get(&choices, i));
272 186
 		}
273 187
 	} else {
274 188
 		/* interactive */
275 189
 		tty_t tty;
276
-		tty_init(&tty, tty_filename);
190
+		tty_init(&tty, options.tty_filename);
191
+
192
+		if (options.num_lines > choices.size)
193
+			options.num_lines = choices.size;
277 194
 
278
-		if (num_lines > choices.size)
279
-			num_lines = choices.size;
195
+		if (options.num_lines + 1 > tty_getheight(&tty))
196
+			options.num_lines = tty_getheight(&tty) - 1;
280 197
 
281
-		if (num_lines + 1 > tty_getheight(&tty))
282
-			num_lines = tty_getheight(&tty) - 1;
198
+		if (options.init_search)
199
+			strncpy(search, options.init_search, SEARCH_SIZE_MAX);
283 200
 
284 201
 		run(&tty, &choices);
285 202
 	}
286 203
new file mode 100644
... ...
@@ -0,0 +1,104 @@
1
+#include <getopt.h>
2
+#include <limits.h>
3
+#include <stdio.h>
4
+#include <stdlib.h>
5
+#include <string.h>
6
+
7
+#include "options.h"
8
+
9
+static const char *usage_str =
10
+    ""
11
+    "Usage: fzy [OPTION]...\n"
12
+    " -l, --lines=LINES        Specify how many lines of results to show (default 10)\n"
13
+    " -p, --prompt=PROMPT      Input prompt (default '> ')\n"
14
+    " -q, --query=QUERY        Use QUERY as the initial search string\n"
15
+    " -e, --show-matches=QUERY Output the sorted matches of QUERY\n"
16
+    " -t, --tty=TTY            Specify file to use as TTY device (default /dev/tty)\n"
17
+    " -s, --show-scores        Show the scores of each match\n"
18
+    " -h, --help     Display this help and exit\n"
19
+    " -v, --version  Output version information and exit\n";
20
+
21
+static void usage(const char *argv0) {
22
+	fprintf(stderr, usage_str, argv0);
23
+}
24
+
25
+static struct option longopts[] = {{"show-matches", required_argument, NULL, 'e'},
26
+				   {"query", required_argument, NULL, 'q'},
27
+				   {"lines", required_argument, NULL, 'l'},
28
+				   {"tty", required_argument, NULL, 't'},
29
+				   {"prompt", required_argument, NULL, 'p'},
30
+				   {"show-scores", no_argument, NULL, 's'},
31
+				   {"version", no_argument, NULL, 'v'},
32
+				   {"benchmark", optional_argument, NULL, 'b'},
33
+				   {"help", no_argument, NULL, 'h'},
34
+				   {NULL, 0, NULL, 0}};
35
+
36
+void options_set_defaults(options_t *options) {
37
+	/* set defaults */
38
+	options->benchmark = 0;
39
+	options->filter = NULL;
40
+	options->init_search = NULL;
41
+	options->tty_filename = "/dev/tty";
42
+	options->show_scores = 0;
43
+	options->num_lines = 10;
44
+	options->scrolloff = 1;
45
+	options->prompt = "> ";
46
+}
47
+
48
+void options_parse(options_t *options, int argc, char *argv[]) {
49
+	options_set_defaults(options);
50
+
51
+	char c;
52
+	while ((c = getopt_long(argc, argv, "vhse:q:l:t:p:", longopts, NULL)) != -1) {
53
+		switch (c) {
54
+			case 'v':
55
+				printf("%s " VERSION " (c) 2014 John Hawthorn\n", argv[0]);
56
+				exit(EXIT_SUCCESS);
57
+			case 's':
58
+				options->show_scores = 1;
59
+				break;
60
+			case 'q':
61
+				options->init_search = optarg;
62
+				break;
63
+			case 'e':
64
+				options->filter = optarg;
65
+				break;
66
+			case 'b':
67
+				if (optarg) {
68
+					if (sscanf(optarg, "%d", &options->benchmark) != 1) {
69
+						usage(argv[0]);
70
+						exit(EXIT_FAILURE);
71
+					}
72
+				} else {
73
+					options->benchmark = 100;
74
+				}
75
+				break;
76
+			case 't':
77
+				options->tty_filename = optarg;
78
+				break;
79
+			case 'p':
80
+				options->prompt = optarg;
81
+				break;
82
+			case 'l': {
83
+				int l;
84
+				if (!strcmp(optarg, "max")) {
85
+					l = INT_MAX;
86
+				} else if (sscanf(optarg, "%d", &l) != 1 || l < 3) {
87
+					fprintf(stderr, "Invalid format for --lines: %s\n", optarg);
88
+					fprintf(stderr, "Must be integer in range 3..\n");
89
+					usage(argv[0]);
90
+					exit(EXIT_FAILURE);
91
+				}
92
+				options->num_lines = l;
93
+			} break;
94
+			case 'h':
95
+			default:
96
+				usage(argv[0]);
97
+				exit(EXIT_SUCCESS);
98
+		}
99
+	}
100
+	if (optind != argc) {
101
+		usage(argv[0]);
102
+		exit(EXIT_FAILURE);
103
+	}
104
+}
0 105
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+typedef struct {
2
+	int benchmark;
3
+	const char *filter;
4
+	const char *init_search;
5
+	const char *tty_filename;
6
+	int show_scores;
7
+	unsigned int num_lines;
8
+	unsigned int scrolloff;
9
+	const char *prompt;
10
+} options_t;
11
+
12
+void options_parse(options_t *options, int argc, char *argv[]);