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