even less lines - iomenu - interactive terminal-based selection menu
(HTM) git clone git://bitreich.org/iomenu git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/iomenu
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Tags
(DIR) README
(DIR) LICENSE
---
(DIR) commit d3fb1d64c2c59436bbf19b18713bb82a0c987760
(DIR) parent 13035ab96ecce34b052d703bebe4bc995ecc3920
(HTM) Author: Josuah Demangeonā ā µ <mail@josuah.net>
Date: Fri, 17 Mar 2017 18:42:57 +0100
even less lines
Diffstat:
M iomenu.c | 168 ++++++++++++++++----------------
1 file changed, 84 insertions(+), 84 deletions(-)
---
(DIR) diff --git a/iomenu.c b/iomenu.c
@@ -17,17 +17,29 @@
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
-typedef struct Line {
+struct line {
char *text; /* sent as output and matched by input */
- int match; /* whether it matches buffer's input */
-} Line;
+ int match; /* whether it matches linev's input */
+};
-Line **buffer;
-size_t current = 0, matching = 0, total = 0;
-char *input = "";
-int opt_lines = 30;
-char *opt_prompt = "";
+char input[BUFSIZ];
+size_t current = 0, matching = 0, linec = 0;
+struct line **linev = NULL;
+int opt_lines = 30;
+char *opt_prompt = ">";
+
+
+void
+free_linev(struct line **linev)
+{
+ for (; linec > 0; linec--) {
+ free(linev[linec - 1]->text);
+ free(linev[linec - 1]);
+ }
+
+ free(linev);
+}
void
@@ -45,17 +57,12 @@ set_terminal(int tty_fd)
struct termios termio_old;
struct termios termio_new;
- /* set the terminal to send one key at a time. */
-
- /* get the terminal's state */
if (tcgetattr(tty_fd, &termio_old) < 0)
die("Can not get terminal attributes with tcgetattr().");
- /* create a new modified state by switching the binary flags */
termio_new = termio_old;
termio_new.c_lflag &= ~(ICANON | ECHO | IGNBRK);
- /* apply this state to buffer[current] terminal now (TCSANOW) */
tcsetattr(tty_fd, TCSANOW, &termio_new);
return termio_old;
@@ -63,45 +70,43 @@ set_terminal(int tty_fd)
void
-fill_buffer(void)
+fill_linev(void)
{
- extern Line **buffer;
-
- char s[BUFSIZ];
- size_t size = 2 << 4;
+ extern struct line **linev;
- buffer = malloc(sizeof(Line) * size);
+ char s[BUFSIZ];
+ size_t size = 1 << 4;
+ linev = malloc(sizeof(*linev) * size);
input[0] = '\0';
- total = matching = 1;
+ linec = matching = 0;
/* read the file into an array of lines */
- for (; fgets(s, BUFSIZ, stdin); total++, matching++) {
- if (total > size) {
+ for (; fgets(s, BUFSIZ, stdin); linec++, matching++) {
+
+ size_t len = strlen(s);
+ if (len > 0 && s[len - 1] == '\n')
+ s[len - 1] = '\0';
+
+ if (linec >= size) {
size *= 2;
- if (!realloc(buffer, sizeof(Line) * size))
+ linev = realloc(linev, sizeof(*linev) * size);
+
+ if (linev == NULL)
die("realloc");
}
- /* empty input match everything */
- buffer[total]->matches = 1;
- buffer[total]->text[strlen(s) - 1] = '\0';
+ linev[linec] = malloc(sizeof(struct line));
+ linev[linec]->match = 1;
+ linev[linec]->text = s;
}
-}
-
-
-void
-free_buffer(Line **buffer)
-{
- for (; total > 0; total--)
- free(buffer[total - 1]->text);
- free(buffer);
+ linev[linec] = NULL;
}
int
-line_matches(Line *line, char **tokv, size_t tokc)
+line_matches(struct line *line, char **tokv, size_t tokc)
{
for (size_t i = 0; i < tokc; i++)
if (strstr(line->text, tokv[i]) != 0)
@@ -124,23 +129,28 @@ filter_lines(int inc)
/* tokenize input from space characters, this comes from dmenu */
strcpy(buf, input);
- for (s = strtok(buf, " "); s; s = strtok(NULL, " ")) {
- if (++tokc > n && !(tokv = realloc(tokv, ++n * sizeof(*tokv))))
- die("realloc");
+ for (s = strtok(buf, " "); s; s = strtok(NULL, " "), tokc++) {
- tokv[tokc - 1] = s;
+ if (tokc >= n) {
+ tokv = realloc(tokv, ++n * sizeof(*tokv));
+
+ if (tokv == NULL)
+ die("realloc");
+ }
+
+ tokv[tokc] = s;
}
/* match lines */
matching = 0;
- for (size_t i = 0; i < total; i++) {
+ for (size_t i = 0; i < linec; i++) {
- if (input[0] && strcmp(input, buffer[i]->text) == 0) {
- buffer[i]->match = 1;
+ if (input[0] && strcmp(input, linev[i]->text) == 0) {
+ linev[i]->match = 1;
- } else if ((inc && buffer[i]->match) || (!inc && !buffer[i]->match)) {
- buffer[i]->match = line_matches(buffer[i], tokv, tokc);
- matching += buffer[i]->match;
+ } else if (!(inc ^ linev[i]->match)) {
+ linev[i]->match = line_matches(linev[i], tokv, tokc);
+ matching += linev[i]->match;
}
}
}
@@ -149,8 +159,8 @@ filter_lines(int inc)
int
matching_prev(int pos)
{
- for (size_t i = pos; i > 0; i--)
- if (buffer[i]->match)
+ for (size_t i = pos - 1; i > 0; i--)
+ if (linev[i]->match)
return i;
return pos;
}
@@ -159,52 +169,42 @@ matching_prev(int pos)
int
matching_next(size_t pos)
{
- for (size_t i = pos; i < total; i++)
- if (buffer[i]->match)
+ for (size_t i = pos + 1; i < linec; i++)
+ if (linev[i]->match)
return i;
return pos;
}
-int
-matching_close(size_t pos)
-{
- if (buffer[pos]->match)
- return pos;
-
- for (size_t i = 0; i + pos < total && i <= pos; i++) {
- if (buffer[pos - i]->match)
- return pos - i;
-
- if (buffer[pos + i]->match)
- return pos + i;
- }
-
- return pos;
-}
-
-
void
draw_line(size_t pos, const size_t cols)
{
- fprintf(stderr, pos == current ? "\033[1;31m%s" : "%s", buffer[pos]->text);
+ fprintf(stderr,
+ pos == current ? "\033[7m%s\033[m\n" : "%s\n",
+ linev[pos]->text
+ );
}
void
draw_lines(size_t count, size_t cols)
{
- size_t i;
- for (i = MAX(current, 0); i < total && i < count;) {
- if (buffer[i]->match) {
+ size_t i = current, printed = 0;
+
+ /* find `count / 3` matching lines above */
+ for (size_t c = 0; c < 2 * count / 3 && i > 0; i--)
+ if (linev[i] && linev[i]->match)
+ c++;
+
+ while (i < linec && printed < count) {
+ if (linev[i]->match) {
draw_line(i, cols);
- i++;
+ i++; printed++;
}
}
- /* continue up to the end of the screen clearing it */
- for (; i < count; i++)
+ for (; printed < count; printed++)
fputs("\n\033[K", stderr);
}
@@ -212,12 +212,12 @@ draw_lines(size_t count, size_t cols)
void
draw_prompt(int cols)
{
- fprintf(stderr, "\r\033[K\033[1m%7s %s", opt_prompt, input);
+ fprintf(stderr, "\r\033[K\033[1m%7s %s\033[m", opt_prompt, input);
}
void
-draw_screen( int tty_fd)
+draw_screen(int tty_fd)
{
struct winsize w;
int count;
@@ -272,7 +272,7 @@ add_character(char key)
}
filter_lines(1);
- current = matching_close(current);
+ current = matching_next(0);
}
@@ -288,7 +288,7 @@ print_selection(int return_input)
puts(input);
} else if (matching > 0) {
- puts(buffer[current]->text);
+ puts(linev[current]->text);
}
}
@@ -299,7 +299,7 @@ print_selection(int return_input)
int
input_key(FILE *tty_fp)
{
- extern char *input;
+ extern char input[];
char key = fgetc(tty_fp);
@@ -329,7 +329,7 @@ input_key(FILE *tty_fp)
case CONTROL('H'): /* backspace */
input[strlen(input) - 1] = '\0';
filter_lines(0);
- current = matching_close(current);
+ current = matching_next(0);
break;
case CONTROL('N'):
@@ -341,7 +341,7 @@ input_key(FILE *tty_fp)
break;
case CONTROL('I'): /* tab */
- strcpy(input, buffer[current]->text);
+ strcpy(input, linev[current]->text);
filter_lines(1);
break;
@@ -418,7 +418,7 @@ main(int argc, char *argv[])
}
/* command line arguments */
- fill_buffer();
+ fill_linev();
/* set the interface */
draw_screen(tty_fd);
@@ -430,7 +430,7 @@ main(int argc, char *argv[])
/* close files descriptors and pointers, and free memory */
close(tty_fd);
- free_buffer(buffer);
+ free_linev(linev);
return exit_code;
}