Browse code

Extract tty interface to own file

John Hawthorn authored on 20/06/2016 06:08:00
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 src/options.o
14
+OBJECTS=src/fzy.o src/match.o src/tty.o src/choices.o src/options.o src/tty_interface.o
15 15
 TESTOBJECTS=test/fzytest.c src/match.o src/choices.o
16 16
 
17 17
 all: fzy
... ...
@@ -8,161 +8,12 @@
8 8
 #include "tty.h"
9 9
 #include "choices.h"
10 10
 #include "options.h"
11
+#include "tty_interface.h"
11 12
 
12 13
 #include "../config.h"
13 14
 
14 15
 options_t options;
15 16
 
16
-#define SEARCH_SIZE_MAX 4096
17
-static char search[SEARCH_SIZE_MAX + 1] = {0};
18
-
19
-static void clear(tty_t *tty, options_t *options) {
20
-	tty_setcol(tty, 0);
21
-	size_t line = 0;
22
-	while (line++ < options->num_lines) {
23
-		tty_newline(tty);
24
-	}
25
-	tty_clearline(tty);
26
-	tty_moveup(tty, line - 1);
27
-	tty_flush(tty);
28
-}
29
-
30
-static void draw_match(tty_t *tty, const char *choice, int selected, options_t *options) {
31
-	int n = strlen(search);
32
-	size_t positions[n + 1];
33
-	for (int i = 0; i < n + 1; i++)
34
-		positions[i] = -1;
35
-
36
-	double score = match_positions(search, choice, &positions[0]);
37
-
38
-	size_t maxwidth = tty_getwidth(tty);
39
-
40
-	if (options->show_scores)
41
-		tty_printf(tty, "(%5.2f) ", score);
42
-
43
-	if (selected)
44
-		tty_setinvert(tty);
45
-
46
-	for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
47
-		if (i + 1 < maxwidth) {
48
-			if (positions[p] == i) {
49
-				tty_setfg(tty, TTY_COLOR_HIGHLIGHT);
50
-				p++;
51
-			} else {
52
-				tty_setfg(tty, TTY_COLOR_NORMAL);
53
-			}
54
-			tty_printf(tty, "%c", choice[i]);
55
-		} else {
56
-			tty_printf(tty, "$");
57
-			break;
58
-		}
59
-	}
60
-	tty_setnormal(tty);
61
-}
62
-
63
-static void draw(tty_t *tty, choices_t *choices, options_t *options) {
64
-	unsigned int num_lines = options->num_lines;
65
-	size_t start = 0;
66
-	size_t current_selection = choices->selection;
67
-	if (current_selection + options->scrolloff >= num_lines) {
68
-		start = current_selection + options->scrolloff - num_lines + 1;
69
-		if (start + num_lines >= choices_available(choices)) {
70
-			start = choices_available(choices) - num_lines;
71
-		}
72
-	}
73
-	tty_setcol(tty, 0);
74
-	tty_printf(tty, "%s%s", options->prompt, search);
75
-	tty_clearline(tty);
76
-	for (size_t i = start; i < start + num_lines; i++) {
77
-		tty_printf(tty, "\n");
78
-		tty_clearline(tty);
79
-		const char *choice = choices_get(choices, i);
80
-		if (choice) {
81
-			draw_match(tty, choice, i == choices->selection, options);
82
-		}
83
-	}
84
-	tty_moveup(tty, num_lines);
85
-	tty_setcol(tty, strlen(options->prompt) + strlen(search));
86
-	tty_flush(tty);
87
-}
88
-
89
-static void emit(choices_t *choices) {
90
-	const char *selection = choices_get(choices, choices->selection);
91
-	if (selection) {
92
-		/* output the selected result */
93
-		printf("%s\n", selection);
94
-	} else {
95
-		/* No match, output the query instead */
96
-		printf("%s\n", search);
97
-	}
98
-}
99
-
100
-#define KEY_CTRL(key) ((key) - ('@'))
101
-#define KEY_DEL 127
102
-#define KEY_ESC 27
103
-
104
-static void run(tty_t *tty, choices_t *choices, options_t *options) {
105
-	choices_search(choices, search);
106
-	char ch;
107
-	do {
108
-		draw(tty, choices, options);
109
-		ch = tty_getchar(tty);
110
-		size_t search_size = strlen(search);
111
-		if (isprint(ch)) {
112
-			if (search_size < SEARCH_SIZE_MAX) {
113
-				search[search_size++] = ch;
114
-				search[search_size] = '\0';
115
-				choices_search(choices, search);
116
-			}
117
-		} else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
118
-			if (search_size)
119
-				search[--search_size] = '\0';
120
-			choices_search(choices, search);
121
-		} else if (ch == KEY_CTRL('U')) { /* C-U */
122
-			search_size = 0;
123
-			search[0] = '\0';
124
-			choices_search(choices, search);
125
-		} else if (ch == KEY_CTRL('W')) { /* C-W */
126
-			if (search_size)
127
-				search[--search_size] = '\0';
128
-			while (search_size && !isspace(search[--search_size]))
129
-				search[search_size] = '\0';
130
-			choices_search(choices, search);
131
-		} else if (ch == KEY_CTRL('N')) { /* C-N */
132
-			choices_next(choices);
133
-		} else if (ch == KEY_CTRL('P')) { /* C-P */
134
-			choices_prev(choices);
135
-		} else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
136
-			strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX);
137
-			choices_search(choices, search);
138
-		} else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
139
-			clear(tty, options);
140
-			tty_close(tty);
141
-			exit(EXIT_FAILURE);
142
-		} else if (ch == KEY_CTRL('M')) { /* CR */
143
-			clear(tty, options);
144
-
145
-			/* ttyout should be flushed before outputting on stdout */
146
-			tty_close(tty);
147
-
148
-			emit(choices);
149
-
150
-			/* Return to eventually exit successfully */
151
-			return;
152
-		} else if (ch == KEY_ESC) { /* ESC */
153
-			ch = tty_getchar(tty);
154
-			if (ch == '[' || ch == 'O') {
155
-				ch = tty_getchar(tty);
156
-				if (ch == 'A') { /* UP ARROW */
157
-					choices_prev(choices);
158
-				} else if (ch == 'B') { /* DOWN ARROW */
159
-					choices_next(choices);
160
-				}
161
-			}
162
-		}
163
-	} while (1);
164
-}
165
-
166 17
 int main(int argc, char *argv[]) {
167 18
 	options_parse(&options, argc, argv);
168 19
 
... ...
@@ -195,10 +46,7 @@ int main(int argc, char *argv[]) {
195 46
 		if (options.num_lines + 1 > tty_getheight(&tty))
196 47
 			options.num_lines = tty_getheight(&tty) - 1;
197 48
 
198
-		if (options.init_search)
199
-			strncpy(search, options.init_search, SEARCH_SIZE_MAX);
200
-
201
-		run(&tty, &choices, &options);
49
+		tty_interface_run(&tty, &choices, &options);
202 50
 	}
203 51
 
204 52
 	choices_destroy(&choices);
205 53
new file mode 100644
... ...
@@ -0,0 +1,160 @@
1
+#include <ctype.h>
2
+#include <stdio.h>
3
+#include <stdlib.h>
4
+#include <string.h>
5
+
6
+#include "match.h"
7
+#include "tty_interface.h"
8
+#include "../config.h"
9
+
10
+static char search[SEARCH_SIZE_MAX + 1];
11
+
12
+static void clear(tty_t *tty, options_t *options) {
13
+	tty_setcol(tty, 0);
14
+	size_t line = 0;
15
+	while (line++ < options->num_lines) {
16
+		tty_newline(tty);
17
+	}
18
+	tty_clearline(tty);
19
+	tty_moveup(tty, line - 1);
20
+	tty_flush(tty);
21
+}
22
+
23
+static void draw_match(tty_t *tty, const char *choice, int selected, options_t *options) {
24
+	int n = strlen(search);
25
+	size_t positions[n + 1];
26
+	for (int i = 0; i < n + 1; i++)
27
+		positions[i] = -1;
28
+
29
+	double score = match_positions(search, choice, &positions[0]);
30
+
31
+	size_t maxwidth = tty_getwidth(tty);
32
+
33
+	if (options->show_scores)
34
+		tty_printf(tty, "(%5.2f) ", score);
35
+
36
+	if (selected)
37
+		tty_setinvert(tty);
38
+
39
+	for (size_t i = 0, p = 0; choice[i] != '\0'; i++) {
40
+		if (i + 1 < maxwidth) {
41
+			if (positions[p] == i) {
42
+				tty_setfg(tty, TTY_COLOR_HIGHLIGHT);
43
+				p++;
44
+			} else {
45
+				tty_setfg(tty, TTY_COLOR_NORMAL);
46
+			}
47
+			tty_printf(tty, "%c", choice[i]);
48
+		} else {
49
+			tty_printf(tty, "$");
50
+			break;
51
+		}
52
+	}
53
+	tty_setnormal(tty);
54
+}
55
+
56
+static void draw(tty_t *tty, choices_t *choices, options_t *options) {
57
+	unsigned int num_lines = options->num_lines;
58
+	size_t start = 0;
59
+	size_t current_selection = choices->selection;
60
+	if (current_selection + options->scrolloff >= num_lines) {
61
+		start = current_selection + options->scrolloff - num_lines + 1;
62
+		if (start + num_lines >= choices_available(choices)) {
63
+			start = choices_available(choices) - num_lines;
64
+		}
65
+	}
66
+	tty_setcol(tty, 0);
67
+	tty_printf(tty, "%s%s", options->prompt, search);
68
+	tty_clearline(tty);
69
+	for (size_t i = start; i < start + num_lines; i++) {
70
+		tty_printf(tty, "\n");
71
+		tty_clearline(tty);
72
+		const char *choice = choices_get(choices, i);
73
+		if (choice) {
74
+			draw_match(tty, choice, i == choices->selection, options);
75
+		}
76
+	}
77
+	tty_moveup(tty, num_lines);
78
+	tty_setcol(tty, strlen(options->prompt) + strlen(search));
79
+	tty_flush(tty);
80
+}
81
+
82
+static void emit(choices_t *choices) {
83
+	const char *selection = choices_get(choices, choices->selection);
84
+	if (selection) {
85
+		/* output the selected result */
86
+		printf("%s\n", selection);
87
+	} else {
88
+		/* No match, output the query instead */
89
+		printf("%s\n", search);
90
+	}
91
+}
92
+
93
+#define KEY_CTRL(key) ((key) - ('@'))
94
+#define KEY_DEL 127
95
+#define KEY_ESC 27
96
+
97
+void tty_interface_run(tty_t *tty, choices_t *choices, options_t *options) {
98
+	if (options->init_search)
99
+		strncpy(search, options->init_search, SEARCH_SIZE_MAX);
100
+
101
+	choices_search(choices, search);
102
+	char ch;
103
+	do {
104
+		draw(tty, choices, options);
105
+		ch = tty_getchar(tty);
106
+		size_t search_size = strlen(search);
107
+		if (isprint(ch)) {
108
+			if (search_size < SEARCH_SIZE_MAX) {
109
+				search[search_size++] = ch;
110
+				search[search_size] = '\0';
111
+				choices_search(choices, search);
112
+			}
113
+		} else if (ch == KEY_DEL || ch == KEY_CTRL('H')) { /* DEL || Backspace (C-H) */
114
+			if (search_size)
115
+				search[--search_size] = '\0';
116
+			choices_search(choices, search);
117
+		} else if (ch == KEY_CTRL('U')) { /* C-U */
118
+			search_size = 0;
119
+			search[0] = '\0';
120
+			choices_search(choices, search);
121
+		} else if (ch == KEY_CTRL('W')) { /* C-W */
122
+			if (search_size)
123
+				search[--search_size] = '\0';
124
+			while (search_size && !isspace(search[--search_size]))
125
+				search[search_size] = '\0';
126
+			choices_search(choices, search);
127
+		} else if (ch == KEY_CTRL('N')) { /* C-N */
128
+			choices_next(choices);
129
+		} else if (ch == KEY_CTRL('P')) { /* C-P */
130
+			choices_prev(choices);
131
+		} else if (ch == KEY_CTRL('I')) { /* TAB (C-I) */
132
+			strncpy(search, choices_get(choices, choices->selection), SEARCH_SIZE_MAX);
133
+			choices_search(choices, search);
134
+		} else if (ch == KEY_CTRL('C') || ch == KEY_CTRL('D')) { /* ^C || ^D */
135
+			clear(tty, options);
136
+			tty_close(tty);
137
+			exit(EXIT_FAILURE);
138
+		} else if (ch == KEY_CTRL('M')) { /* CR */
139
+			clear(tty, options);
140
+
141
+			/* ttyout should be flushed before outputting on stdout */
142
+			tty_close(tty);
143
+
144
+			emit(choices);
145
+
146
+			/* Return to eventually exit successfully */
147
+			return;
148
+		} else if (ch == KEY_ESC) { /* ESC */
149
+			ch = tty_getchar(tty);
150
+			if (ch == '[' || ch == 'O') {
151
+				ch = tty_getchar(tty);
152
+				if (ch == 'A') { /* UP ARROW */
153
+					choices_prev(choices);
154
+				} else if (ch == 'B') { /* DOWN ARROW */
155
+					choices_next(choices);
156
+				}
157
+			}
158
+		}
159
+	} while (1);
160
+}
0 161
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+#ifndef TTY_INTERFACE_H
2
+#define TTY_INTERFACE_H TTY_INTERFACE_H
3
+
4
+#include "choices.h"
5
+#include "options.h"
6
+#include "tty.h"
7
+
8
+#define SEARCH_SIZE_MAX 4096
9
+
10
+void tty_interface_run(tty_t *tty, choices_t *choices, options_t *options);
11
+
12
+#endif