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
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include "Globals.h"
#include "Terminal.h"
#include "Draw.h"
#include "Input.h"
Options opts = {
.prompt = "",
.insensitive = 0
};
ItemList all_items = {0};
ItemList filtered = {0};
char *input = NULL;
size_t input_len = 0;
size_t input_capacity = 0;
int cursor = 0;
int scroll = 0;
int needs_redraw = 1;
static void ensure_item_capacity(ItemList *list) {
if (list->count >= list->capacity) {
size_t new_cap = list->capacity == 0 ? INITIAL_CAPACITY : list->capacity * 2;
list->items = realloc(list->items, new_cap * sizeof(char *));
list->capacity = new_cap;
}
}
void read_items(void) {
char *line = NULL;
size_t len = 0;
ssize_t n;
while ((n = getline(&line, &len, stdin)) != -1) {
if (n > 0 && line[n-1] == '\n') line[n-1] = '\0';
ensure_item_capacity(&all_items);
all_items.items[all_items.count++] = strdup(line);
}
free(line);
filter_items();
}
void version(void) {
puts("insel 1.0");
puts("'those who select their inputs'\n");
puts("GNU GPL version 2 <https://gnu.org/licenses/old-licenses/gpl-2.0.html>.\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.");
exit(0);
}
void help(void) {
puts("Usage: insel [-i] [-p prompt]"
"\n"
"Options:"
"\n"
" -i Case-insensitive matching"
"\n"
" -v Show version"
"\n"
" -p prompt Prompt to display"
"\n"
" --help Show this help message");
exit(0);
}
int main(int argc, char *argv[]) {
stdin_is_tty = isatty(STDIN_FILENO);
orig_stdout = dup(STDOUT_FILENO);
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-v") == 0) version();
else if (strcmp(argv[i], "--help") == 0) help();
else if (strcmp(argv[i], "-i") == 0) opts.insensitive = 1;
else if (strcmp(argv[i], "-b") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-p") == 0 && i + 1 < argc) {
if (opts.prompt[0] != '\0') free(opts.prompt);
opts.prompt = strdup(argv[++i]);
}
else if (strcmp(argv[i], "-nb") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-nf") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-sb") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-sf") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-fn") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-m") == 0 && i + 1 < argc) i++;
else if (strcmp(argv[i], "-w") == 0 && i + 1 < argc) i++;
}
read_items();
setup_terminal();
while (1) {
if (needs_redraw) {
draw();
needs_redraw = 0;
}
fd_set fds;
FD_ZERO(&fds);
FD_SET(tty_fd, &fds);
struct timeval tv = { .tv_sec = 0, .tv_usec = 10000 };
if (select(tty_fd + 1, &fds, NULL, NULL, &tv) > 0) {
handle_input();
}
}
return 0;
}
|