| ... | ... |
@@ -2,13 +2,10 @@ |
| 2 | 2 |
#include <stdio.h> |
| 3 | 3 |
#include <string.h> |
| 4 | 4 |
#include <stdlib.h> |
| 5 |
-#include <termios.h> |
|
| 6 |
-#include <unistd.h> |
|
| 7 |
-#include <sys/stat.h> |
|
| 8 |
-#include <fcntl.h> |
|
| 9 | 5 |
#include <ctype.h> |
| 10 | 6 |
|
| 11 | 7 |
#include "fzy.h" |
| 8 |
+#include "tty.h" |
|
| 12 | 9 |
|
| 13 | 10 |
#define INITIAL_CAPACITY 1 |
| 14 | 11 |
int choices_capacity = 0; |
| ... | ... |
@@ -83,58 +80,22 @@ void run_search(char *needle){
|
| 83 | 80 |
} |
| 84 | 81 |
|
| 85 | 82 |
qsort(choices_sorted, choices_available, sizeof(size_t), cmpchoice); |
| 86 |
- |
|
| 87 |
-} |
|
| 88 |
- |
|
| 89 |
-int ttyin; |
|
| 90 |
-FILE *ttyout; |
|
| 91 |
-struct termios original_termios; |
|
| 92 |
- |
|
| 93 |
-void reset_tty(){
|
|
| 94 |
- tcsetattr(ttyin, TCSANOW, &original_termios); |
|
| 95 |
-} |
|
| 96 |
- |
|
| 97 |
-void init_tty(){
|
|
| 98 |
- ttyin = open("/dev/tty", O_RDONLY);
|
|
| 99 |
- ttyout = fopen("/dev/tty", "w");
|
|
| 100 |
- |
|
| 101 |
- tcgetattr(ttyin, &original_termios); |
|
| 102 |
- |
|
| 103 |
- struct termios new_termios = original_termios; |
|
| 104 |
- |
|
| 105 |
- new_termios.c_lflag &= ~(ICANON | ECHO); |
|
| 106 |
- |
|
| 107 |
- tcsetattr(ttyin, TCSANOW, &new_termios); |
|
| 108 |
-} |
|
| 109 |
- |
|
| 110 |
-char ttygetchar(){
|
|
| 111 |
- char ch; |
|
| 112 |
- int size = read(ttyin, &ch, 1); |
|
| 113 |
- if(size < 0){
|
|
| 114 |
- perror("error reading from tty");
|
|
| 115 |
- exit(EXIT_FAILURE); |
|
| 116 |
- }else if(size == 0){
|
|
| 117 |
- /* EOF */ |
|
| 118 |
- exit(EXIT_FAILURE); |
|
| 119 |
- }else{
|
|
| 120 |
- return ch; |
|
| 121 |
- } |
|
| 122 | 83 |
} |
| 123 | 84 |
|
| 124 | 85 |
int search_size; |
| 125 | 86 |
char search[4096] = {0};
|
| 126 | 87 |
|
| 127 |
-void clear(){
|
|
| 128 |
- fprintf(ttyout, "%c%c0G", 0x1b, '['); |
|
| 88 |
+void clear(tty_t *tty){
|
|
| 89 |
+ fprintf(tty->fout, "%c%c0G", 0x1b, '['); |
|
| 129 | 90 |
int line = 0; |
| 130 | 91 |
while(line++ < 10 + 1){
|
| 131 |
- fprintf(ttyout, "%c%cK\n", 0x1b, '['); |
|
| 92 |
+ fprintf(tty->fout, "%c%cK\n", 0x1b, '['); |
|
| 132 | 93 |
} |
| 133 |
- fprintf(ttyout, "%c%c%iA", 0x1b, '[', line-1); |
|
| 134 |
- fprintf(ttyout, "%c%c0G", 0x1b, '['); |
|
| 94 |
+ fprintf(tty->fout, "%c%c%iA", 0x1b, '[', line-1); |
|
| 95 |
+ fprintf(tty->fout, "%c%c0G", 0x1b, '['); |
|
| 135 | 96 |
} |
| 136 | 97 |
|
| 137 |
-void draw_match(const char *choice, int selected){
|
|
| 98 |
+void draw_match(tty_t *tty, const char *choice, int selected){
|
|
| 138 | 99 |
int n = strlen(search); |
| 139 | 100 |
size_t positions[n + 1]; |
| 140 | 101 |
for(int i = 0; i < n + 1; i++) |
| ... | ... |
@@ -144,36 +105,36 @@ void draw_match(const char *choice, int selected){
|
| 144 | 105 |
|
| 145 | 106 |
for(size_t i = 0, p = 0; choice[i] != '\0'; i++){
|
| 146 | 107 |
if(positions[p] == i){
|
| 147 |
- fprintf(ttyout, "%c%c33m", 0x1b, '['); |
|
| 108 |
+ fprintf(tty->fout, "%c%c33m", 0x1b, '['); |
|
| 148 | 109 |
p++; |
| 149 | 110 |
}else{
|
| 150 |
- fprintf(ttyout, "%c%c39;49m", 0x1b, '['); |
|
| 111 |
+ fprintf(tty->fout, "%c%c39;49m", 0x1b, '['); |
|
| 151 | 112 |
} |
| 152 |
- fprintf(ttyout, "%c", choice[i]); |
|
| 113 |
+ fprintf(tty->fout, "%c", choice[i]); |
|
| 153 | 114 |
} |
| 154 |
- fprintf(ttyout, "\n"); |
|
| 155 |
- fprintf(ttyout, "%c%c0m", 0x1b, '['); |
|
| 115 |
+ fprintf(tty->fout, "\n"); |
|
| 116 |
+ fprintf(tty->fout, "%c%c0m", 0x1b, '['); |
|
| 156 | 117 |
} |
| 157 | 118 |
|
| 158 |
-void draw(){
|
|
| 119 |
+void draw(tty_t *tty){
|
|
| 159 | 120 |
int line = 0; |
| 160 | 121 |
const char *prompt = "> "; |
| 161 |
- clear(); |
|
| 162 |
- fprintf(ttyout, "%s%s\n", prompt, search); |
|
| 122 |
+ clear(tty); |
|
| 123 |
+ fprintf(tty->fout, "%s%s\n", prompt, search); |
|
| 163 | 124 |
for(size_t i = 0; line < 10 && i < choices_available; i++){
|
| 164 | 125 |
if(i == current_selection) |
| 165 |
- fprintf(ttyout, "%c%c7m", 0x1b, '['); |
|
| 166 |
- draw_match(choices[choices_sorted[i]], i == current_selection); |
|
| 126 |
+ fprintf(tty->fout, "%c%c7m", 0x1b, '['); |
|
| 127 |
+ draw_match(tty, choices[choices_sorted[i]], i == current_selection); |
|
| 167 | 128 |
line++; |
| 168 | 129 |
} |
| 169 |
- fprintf(ttyout, "%c%c%iA", 0x1b, '[', line + 1); |
|
| 170 |
- fprintf(ttyout, "%c%c%ziG", 0x1b, '[', strlen(prompt) + strlen(search) + 1); |
|
| 171 |
- fflush(ttyout); |
|
| 130 |
+ fprintf(tty->fout, "%c%c%iA", 0x1b, '[', line + 1); |
|
| 131 |
+ fprintf(tty->fout, "%c%c%ziG", 0x1b, '[', strlen(prompt) + strlen(search) + 1); |
|
| 132 |
+ fflush(tty->fout); |
|
| 172 | 133 |
} |
| 173 | 134 |
|
| 174 |
-void emit(){
|
|
| 135 |
+void emit(tty_t *tty){
|
|
| 175 | 136 |
/* ttyout should be flushed before outputting on stdout */ |
| 176 |
- fclose(ttyout); |
|
| 137 |
+ fclose(tty->fout); |
|
| 177 | 138 |
|
| 178 | 139 |
if(choices_available){
|
| 179 | 140 |
/* output the selected result */ |
| ... | ... |
@@ -186,12 +147,12 @@ void emit(){
|
| 186 | 147 |
exit(EXIT_SUCCESS); |
| 187 | 148 |
} |
| 188 | 149 |
|
| 189 |
-void run(){
|
|
| 150 |
+void run(tty_t *tty){
|
|
| 190 | 151 |
run_search(search); |
| 191 | 152 |
char ch; |
| 192 | 153 |
do {
|
| 193 |
- draw(); |
|
| 194 |
- ch = ttygetchar(); |
|
| 154 |
+ draw(tty); |
|
| 155 |
+ ch = tty_getchar(tty); |
|
| 195 | 156 |
if(isprint(ch)){
|
| 196 | 157 |
/* FIXME: overflow */ |
| 197 | 158 |
search[search_size++] = ch; |
| ... | ... |
@@ -213,13 +174,11 @@ void run(){
|
| 213 | 174 |
run_search(search); |
| 214 | 175 |
}else if(ch == 14){ /* C-N */
|
| 215 | 176 |
current_selection = (current_selection + 1) % 10; |
| 216 |
- draw(); |
|
| 217 | 177 |
}else if(ch == 16){ /* C-P */
|
| 218 | 178 |
current_selection = (current_selection + 9) % 10; |
| 219 |
- draw(); |
|
| 220 | 179 |
}else if(ch == 10){ /* Enter */
|
| 221 |
- clear(); |
|
| 222 |
- emit(); |
|
| 180 |
+ clear(tty); |
|
| 181 |
+ emit(tty); |
|
| 223 | 182 |
} |
| 224 | 183 |
}while(1); |
| 225 | 184 |
} |
| ... | ... |
@@ -236,14 +195,14 @@ int main(int argc, char *argv[]){
|
| 236 | 195 |
}else if(argc != 1){
|
| 237 | 196 |
usage(argv[0]); |
| 238 | 197 |
} |
| 239 |
- atexit(reset_tty); |
|
| 240 |
- init_tty(reset_tty); |
|
| 198 |
+ tty_t tty; |
|
| 199 |
+ tty_init(&tty); |
|
| 241 | 200 |
|
| 242 | 201 |
resize_choices(INITIAL_CAPACITY); |
| 243 | 202 |
read_choices(); |
| 244 | 203 |
|
| 245 |
- clear(); |
|
| 246 |
- run(); |
|
| 204 |
+ clear(&tty); |
|
| 205 |
+ run(&tty); |
|
| 247 | 206 |
|
| 248 | 207 |
return 0; |
| 249 | 208 |
} |
| 250 | 209 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,38 @@ |
| 1 |
+#include <stdio.h> |
|
| 2 |
+#include <unistd.h> |
|
| 3 |
+#include <fcntl.h> |
|
| 4 |
+#include <stdlib.h> |
|
| 5 |
+ |
|
| 6 |
+#include "tty.h" |
|
| 7 |
+ |
|
| 8 |
+void tty_reset(tty_t *tty){
|
|
| 9 |
+ tcsetattr(tty->fdin, TCSANOW, &tty->original_termios); |
|
| 10 |
+} |
|
| 11 |
+ |
|
| 12 |
+void tty_init(tty_t *tty){
|
|
| 13 |
+ tty->fdin = open("/dev/tty", O_RDONLY);
|
|
| 14 |
+ tty->fout = fopen("/dev/tty", "w");
|
|
| 15 |
+ |
|
| 16 |
+ tcgetattr(tty->fdin, &tty->original_termios); |
|
| 17 |
+ |
|
| 18 |
+ struct termios new_termios = tty->original_termios; |
|
| 19 |
+ |
|
| 20 |
+ new_termios.c_lflag &= ~(ICANON | ECHO); |
|
| 21 |
+ |
|
| 22 |
+ tcsetattr(tty->fdin, TCSANOW, &new_termios); |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+char tty_getchar(tty_t *tty){
|
|
| 26 |
+ char ch; |
|
| 27 |
+ int size = read(tty->fdin, &ch, 1); |
|
| 28 |
+ if(size < 0){
|
|
| 29 |
+ perror("error reading from tty");
|
|
| 30 |
+ exit(EXIT_FAILURE); |
|
| 31 |
+ }else if(size == 0){
|
|
| 32 |
+ /* EOF */ |
|
| 33 |
+ exit(EXIT_FAILURE); |
|
| 34 |
+ }else{
|
|
| 35 |
+ return ch; |
|
| 36 |
+ } |
|
| 37 |
+} |
|
| 38 |
+ |
| 0 | 39 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 1 |
+#ifndef TTY_H |
|
| 2 |
+#define TTY_H TTY_H |
|
| 3 |
+ |
|
| 4 |
+#include <termios.h> |
|
| 5 |
+ |
|
| 6 |
+typedef struct{
|
|
| 7 |
+ int fdin; |
|
| 8 |
+ FILE *fout; |
|
| 9 |
+ struct termios original_termios; |
|
| 10 |
+} tty_t; |
|
| 11 |
+ |
|
| 12 |
+void tty_reset(tty_t *tty); |
|
| 13 |
+void tty_init(tty_t *tty); |
|
| 14 |
+char tty_getchar(tty_t *tty); |
|
| 15 |
+ |
|
| 16 |
+#endif |