ion my way for cleaning this up - 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 13035ab96ecce34b052d703bebe4bc995ecc3920 /scm/iomenu/commit/13035ab96ecce34b052d703bebe4bc995ecc3920.gph bitreich.org 70 1parent 35d50bc1a88b26d1f57219a9f3f7b1a907c57498 /scm/iomenu/commit/35d50bc1a88b26d1f57219a9f3f7b1a907c57498.gph bitreich.org 70 hAuthor: Josuah Demangeon⠠⠵ URL:mailto:mail@josuah.net bitreich.org 70 iDate: Thu, 16 Mar 2017 22:26:25 +0100 Err bitreich.org 70 i Err bitreich.org 70 ion my way for cleaning this up Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i A .gitignore | 1 + Err bitreich.org 70 i M LICENSE | 30 ++++++++++++------------------ Err bitreich.org 70 i M Makefile | 2 +- Err bitreich.org 70 i M iomenu.c | 479 ++++++++++--------------------- Err bitreich.org 70 i Err bitreich.org 70 i4 files changed, 159 insertions(+), 353 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/.gitignore b/.gitignore /scm/iomenu/file/.gitignore.gph bitreich.org 70 i@@ -0,0 +1 @@ Err bitreich.org 70 i+iomenu Err bitreich.org 70 1diff --git a/LICENSE b/LICENSE /scm/iomenu/file/LICENSE.gph bitreich.org 70 i@@ -1,21 +1,15 @@ Err bitreich.org 70 i-MIT License Err bitreich.org 70 i+ISC Licence Err bitreich.org 70 i Err bitreich.org 70 i-Copyright (c) 2016 Josuah Demangeon⠠⠵ Err bitreich.org 70 i+Copyright (c) 2017 by Josuah Demangeon Err bitreich.org 70 i Err bitreich.org 70 i-Permission is hereby granted, free of charge, to any person obtaining a copy Err bitreich.org 70 i-of this software and associated documentation files (the "Software"), to deal Err bitreich.org 70 i-in the Software without restriction, including without limitation the rights Err bitreich.org 70 i-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell Err bitreich.org 70 i-copies of the Software, and to permit persons to whom the Software is Err bitreich.org 70 i-furnished to do so, subject to the following conditions: Err bitreich.org 70 i+Permission to use, copy, modify, and/or distribute this software for any Err bitreich.org 70 i+purpose with or without fee is hereby granted, provided that the above Err bitreich.org 70 i+copyright notice and this permission notice appear in all copies. Err bitreich.org 70 i Err bitreich.org 70 i-The above copyright notice and this permission notice shall be included in all Err bitreich.org 70 i-copies or substantial portions of the Software. Err bitreich.org 70 i- Err bitreich.org 70 i-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR Err bitreich.org 70 i-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, Err bitreich.org 70 i-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE Err bitreich.org 70 i-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER Err bitreich.org 70 i-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, Err bitreich.org 70 i-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE Err bitreich.org 70 i-SOFTWARE. Err bitreich.org 70 i+THE SOFTWARE IS PROVIDED “AS IS” AND ISC DISCLAIMS ALL WARRANTIES Err bitreich.org 70 i+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF Err bitreich.org 70 i+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY Err bitreich.org 70 i+SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES Err bitreich.org 70 i+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN Err bitreich.org 70 i+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF Err bitreich.org 70 i+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. Err bitreich.org 70 1diff --git a/Makefile b/Makefile /scm/iomenu/file/Makefile.gph bitreich.org 70 i@@ -1,4 +1,4 @@ Err bitreich.org 70 i-CFLAGS = -std=c99 -pedantic -Wall -Wextra -g -static Err bitreich.org 70 i+CFLAGS = -std=c99 -Wpedantic -Wall -Wextra -g -static Err bitreich.org 70 i OBJ = ${SRC:.c=.o} Err bitreich.org 70 i Err bitreich.org 70 i all: clean iomenu Err bitreich.org 70 1diff --git a/iomenu.c b/iomenu.c /scm/iomenu/file/iomenu.c.gph bitreich.org 70 i@@ -9,64 +9,83 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i-/*--- constants --------------------------------------------------------------*/ Err bitreich.org 70 i- Err bitreich.org 70 i-#define LINE_SIZE 1024 Err bitreich.org 70 i #define OFFSET 5 Err bitreich.org 70 i #define CONTINUE 2 /* as opposed to EXIT_SUCCESS and EXIT_FAILURE */ Err bitreich.org 70 i Err bitreich.org 70 i- Err bitreich.org 70 i-/*--- macros -----------------------------------------------------------------*/ Err bitreich.org 70 i- Err bitreich.org 70 i #define CONTROL(char) (char ^ 0x40) Err bitreich.org 70 i #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) 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-/*--- structures -------------------------------------------------------------*/ Err bitreich.org 70 i- Err bitreich.org 70 i typedef 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 Err bitreich.org 70 i Err bitreich.org 70 i-/*--- variables --------------------------------------------------------------*/ Err bitreich.org 70 i- Err bitreich.org 70 i Line **buffer; Err bitreich.org 70 i-int current, matching, total; Err bitreich.org 70 i-int opt_lines; Err bitreich.org 70 i-char *opt_prompt, *input; 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+ Err bitreich.org 70 i Err bitreich.org 70 i+void Err bitreich.org 70 i+die(const char *s) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ /* tcsetattr(STDIN_FILENO, TCSANOW, &termio_old); */ Err bitreich.org 70 i+ fprintf(stderr, "%s\n", s); Err bitreich.org 70 i+ exit(EXIT_FAILURE); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+ Err bitreich.org 70 i+struct termios Err bitreich.org 70 i+set_terminal(int tty_fd) Err bitreich.org 70 i+{ 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+} Err bitreich.org 70 i Err bitreich.org 70 i-/*--- functions --------------------------------------------------------------*/ Err bitreich.org 70 i Err bitreich.org 70 i-/* Err bitreich.org 70 i- * Fill the buffer apropriately with the lines Err bitreich.org 70 i- */ Err bitreich.org 70 i void Err bitreich.org 70 i fill_buffer(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[LINE_SIZE]; Err bitreich.org 70 i- size_t size = 1; Err bitreich.org 70 i+ char s[BUFSIZ]; Err bitreich.org 70 i+ size_t size = 2 << 4; Err bitreich.org 70 i Err bitreich.org 70 i- buffer = malloc(sizeof(Line) * 2 << 4); Err bitreich.org 70 i+ buffer = malloc(sizeof(Line) * size); Err bitreich.org 70 i Err bitreich.org 70 i input[0] = '\0'; Err bitreich.org 70 i total = matching = 1; 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, LINE_SIZE, stdin); total++, matching++) { 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 size *= 2; Err bitreich.org 70 i- if (!realloc(buffer, size * sizeof(Line))) Err bitreich.org 70 i+ if (!realloc(buffer, sizeof(Line) * size)) 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- buffer[total]->match = 1; /* empty input match everything */ Err bitreich.org 70 i } Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -74,8 +93,6 @@ fill_buffer(void) 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- Line *next = NULL; 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@@ -83,6 +100,17 @@ free_buffer(Line **buffer) 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+{ 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+ return 0; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 1; 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 * If inc is 1, it will only check already matching lines. Err bitreich.org 70 i * If inc is 0, it will only check non-matching lines. Err bitreich.org 70 i@@ -105,131 +133,89 @@ filter_lines(int inc) 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 (int i = 0; i < total; i++) { Err bitreich.org 70 i+ for (size_t i = 0; i < total; 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 Err bitreich.org 70 i } else if ((inc && buffer[i]->match) || (!inc && !buffer[i]->match)) { Err bitreich.org 70 i- buffer[i]->match = match_line(buffer[i], tokv, tokc); 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 } 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-/* Err bitreich.org 70 i- * Return whecher the line matches every string from tokv. Err bitreich.org 70 i- */ Err bitreich.org 70 i int Err bitreich.org 70 i-match_line(Line *line, char **tokv, size_t tokc) Err bitreich.org 70 i-{ Err bitreich.org 70 i- for (int i = 0; i < tokc; i++) Err bitreich.org 70 i- if (!!strstr(buffer[i]->text, tokv[i])) Err bitreich.org 70 i- return 0; Err bitreich.org 70 i- Err bitreich.org 70 i- return 1; 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- * Seek the previous matching line, or NULL if none matches. Err bitreich.org 70 i- */ Err bitreich.org 70 i-Line * Err bitreich.org 70 i matching_prev(int pos) Err bitreich.org 70 i { Err bitreich.org 70 i- for (; pos > 0 && !buffer[pos]->match; pos--); Err bitreich.org 70 i- return buffer[pos]; 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+ return 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-/* Err bitreich.org 70 i- * Seek the next matching line, or NULL if none matches. Err bitreich.org 70 i- */ Err bitreich.org 70 i-Line * Err bitreich.org 70 i-matching_next(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 (; pos < total && !buffer[pos]->match; pos++); Err bitreich.org 70 i- return buffer[pos]; 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+ 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-/* Err bitreich.org 70 i- * Print a line to stderr. Err bitreich.org 70 i- */ Err bitreich.org 70 i-void Err bitreich.org 70 i-draw_line(Line *line, const int cols) 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- char output[LINE_SIZE] = "\033[K"; Err bitreich.org 70 i- int n = 0; Err bitreich.org 70 i- Err bitreich.org 70 i- if (opt_line_numbers) { Err bitreich.org 70 i- strcat(output, buffer[current] ? "\033[1;37m" : "\033[1;30m"); Err bitreich.org 70 i- sprintf(output + strlen(output), "%7d\033[m ", line->number); Err bitreich.org 70 i- } else { Err bitreich.org 70 i- strcat(output, buffer[current] ? "\033[1;31m > " : " "); Err bitreich.org 70 i- } Err bitreich.org 70 i- n += 8; 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- /* highlight buffer[current] line */ Err bitreich.org 70 i- if (buffer[current]) Err bitreich.org 70 i- strcat(output, "\033[1;33m"); 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- /* content */ Err bitreich.org 70 i- strncat(output, line->content, cols - n); Err bitreich.org 70 i- n += strlen(line->content); 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- /* MAX with '1' as \033[0C still move 1 to the right */ Err bitreich.org 70 i- sprintf(output + strlen(output), "\033[%dC", Err bitreich.org 70 i- MAX(1, 40 - n)); Err bitreich.org 70 i- n += MAX(1, 40 - n); Err bitreich.org 70 i- strcat(output, "\033[m\n"); Err bitreich.org 70 i+ return pos; Err bitreich.org 70 i+} Err bitreich.org 70 i Err bitreich.org 70 i- fputs(output, stderr); 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 } Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i-/* Err bitreich.org 70 i- * Print all the lines from an array of pointer to lines. Err bitreich.org 70 i- * Err bitreich.org 70 i- * The total number oflines printed shall not excess 'count'. Err bitreich.org 70 i- */ Err bitreich.org 70 i void Err bitreich.org 70 i-draw_lines( int count, int cols) Err bitreich.org 70 i+draw_lines(size_t count, size_t cols) Err bitreich.org 70 i { Err bitreich.org 70 i- Line *line = buffer[current]; Err bitreich.org 70 i- int i = 0; Err bitreich.org 70 i- int j = 0; Err bitreich.org 70 i- Err bitreich.org 70 i- /* seek back from buffer[current] line to the first line to print */ Err bitreich.org 70 i- while (line && i < count - OFFSET) { Err bitreich.org 70 i- i = line->matches ? i + 1 : i; Err bitreich.org 70 i- line = line->prev; Err bitreich.org 70 i- } Err bitreich.org 70 i- line = line ? line : first; Err bitreich.org 70 i- Err bitreich.org 70 i- /* print up to count lines that match the input */ Err bitreich.org 70 i- while (line && j < count) { Err bitreich.org 70 i- if (line->matches) { Err bitreich.org 70 i- draw_line(line, line == buffer[current], cols); Err bitreich.org 70 i- j++; 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+ draw_line(i, cols); Err bitreich.org 70 i+ i++; Err bitreich.org 70 i } Err bitreich.org 70 i- Err bitreich.org 70 i- line = line->next; 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 (; j < count; j++) Err bitreich.org 70 i- fputs("\r\033[K\n", stderr); Err bitreich.org 70 i+ for (; i < count; i++) 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+ 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 } Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i-/* Err bitreich.org 70 i- * Update the screen interface and print all candidates. Err bitreich.org 70 i- * Err bitreich.org 70 i- * This also has to clear the previous lines. 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 { Err bitreich.org 70 i@@ -261,72 +247,49 @@ draw_clear(int lines) 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- * Print the prompt, before the input, with the number of candidates that Err bitreich.org 70 i- * match. Err bitreich.org 70 i- */ Err bitreich.org 70 i void Err bitreich.org 70 i-draw_prompt(int cols) Err bitreich.org 70 i+remove_word_input() Err bitreich.org 70 i { Err bitreich.org 70 i- size_t i; Err bitreich.org 70 i- int matching = matching; Err bitreich.org 70 i- int total = total; Err bitreich.org 70 i- Err bitreich.org 70 i- /* for the '/' separator between the numbers */ Err bitreich.org 70 i- cols--; Err bitreich.org 70 i- Err bitreich.org 70 i- /* number of digits */ Err bitreich.org 70 i- for (i = matching; i; i /= 10, cols--); Err bitreich.org 70 i- for (i = total; i; i /= 10, cols--); Err bitreich.org 70 i- cols -= !matching ? 1 : 0; /* 0 also has one digit*/ Err bitreich.org 70 i- Err bitreich.org 70 i- /* actual prompt */ Err bitreich.org 70 i- fprintf(stderr, "\r%-6s\033[K\033[1m>\033[m ", opt_prompt); Err bitreich.org 70 i- cols -= 2 + MAX(strlen(opt_prompt), 6); Err bitreich.org 70 i- Err bitreich.org 70 i- /* input without overflowing terminal width */ Err bitreich.org 70 i- for (i = 0; i < strlen(input) && cols > 0; cols--, i++) Err bitreich.org 70 i- fputc(input[i], stderr); Err bitreich.org 70 i+ size_t len = strlen(input) - 1; Err bitreich.org 70 i Err bitreich.org 70 i- /* save the cursor position at the end of the input */ Err bitreich.org 70 i- fputs("\033[s", stderr); Err bitreich.org 70 i+ for (int i = len; i >= 0 && isspace(input[i]); i--) Err bitreich.org 70 i+ input[i] = '\0'; Err bitreich.org 70 i Err bitreich.org 70 i- /* grey */ Err bitreich.org 70 i- fputs("\033[1;30m", stderr); Err bitreich.org 70 i+ len = strlen(input) - 1; Err bitreich.org 70 i+ for (int i = len; i >= 0 && !isspace(input[i]); i--) Err bitreich.org 70 i+ input[i] = '\0'; Err bitreich.org 70 i+} Err bitreich.org 70 i Err bitreich.org 70 i- /* go to the end of the line */ Err bitreich.org 70 i- fprintf(stderr, "\033[%dC", cols); Err bitreich.org 70 i Err bitreich.org 70 i- /* total match and line count at the end of the line */ Err bitreich.org 70 i- fprintf(stderr, "%d/%d", matching, total); Err bitreich.org 70 i+void Err bitreich.org 70 i+add_character(char key) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t len = strlen(input); Err bitreich.org 70 i Err bitreich.org 70 i- /* restore cursor position at the end of the input */ Err bitreich.org 70 i- fputs("\033[m\033[u", stderr); Err bitreich.org 70 i+ if (isprint(key)) { Err bitreich.org 70 i+ input[len] = key; Err bitreich.org 70 i+ input[len + 1] = '\0'; 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 } Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i /* Err bitreich.org 70 i- * Listen for the user input and call the appropriate functions. Err bitreich.org 70 i+ * Send the selection to stdout. Err bitreich.org 70 i */ Err bitreich.org 70 i-int Err bitreich.org 70 i-input_get(int tty_fd) Err bitreich.org 70 i+void Err bitreich.org 70 i+print_selection(int return_input) Err bitreich.org 70 i { Err bitreich.org 70 i- FILE *tty_fp = fopen("/dev/tty", "r"); Err bitreich.org 70 i- int exit_code; Err bitreich.org 70 i- Err bitreich.org 70 i- /* receive one character at a time from the terminal */ Err bitreich.org 70 i- struct termios termio_old = set_terminal(tty_fd); Err bitreich.org 70 i- Err bitreich.org 70 i- while ((exit_code = input_key(tty_fp)) == CONTINUE) Err bitreich.org 70 i- draw_screen(tty_fd); Err bitreich.org 70 i- Err bitreich.org 70 i- /* resets the terminal to the previous state. */ Err bitreich.org 70 i- tcsetattr(tty_fd, TCSANOW, &termio_old); Err bitreich.org 70 i+ fputs("\r\033[K", stderr); Err bitreich.org 70 i Err bitreich.org 70 i- fclose(tty_fp); Err bitreich.org 70 i+ if (return_input || !matching) { Err bitreich.org 70 i+ puts(input); Err bitreich.org 70 i Err bitreich.org 70 i- return exit_code; Err bitreich.org 70 i+ } else if (matching > 0) { Err bitreich.org 70 i+ puts(buffer[current]->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@@ -341,7 +304,7 @@ input_key(FILE *tty_fp) Err bitreich.org 70 i char key = fgetc(tty_fp); Err bitreich.org 70 i Err bitreich.org 70 i if (key == '\n') { Err bitreich.org 70 i- action_print_selection(0); Err bitreich.org 70 i+ print_selection(0); Err bitreich.org 70 i return EXIT_SUCCESS; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -355,12 +318,10 @@ input_key(FILE *tty_fp) Err bitreich.org 70 i input[0] = '\0'; Err bitreich.org 70 i current = 0; Err bitreich.org 70 i filter_lines(0); Err bitreich.org 70 i- action_jump(1); Err bitreich.org 70 i- action_jump(-1); Err bitreich.org 70 i break; Err bitreich.org 70 i Err bitreich.org 70 i case CONTROL('W'): Err bitreich.org 70 i- action_remove_word_input(); Err bitreich.org 70 i+ remove_word_input(); Err bitreich.org 70 i filter_lines(0); Err bitreich.org 70 i break; Err bitreich.org 70 i Err bitreich.org 70 i@@ -368,15 +329,15 @@ 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- action_jump(0); Err bitreich.org 70 i+ current = matching_close(current); Err bitreich.org 70 i break; Err bitreich.org 70 i Err bitreich.org 70 i case CONTROL('N'): Err bitreich.org 70 i- action_jump(1); Err bitreich.org 70 i+ current = matching_next(current); Err bitreich.org 70 i break; Err bitreich.org 70 i Err bitreich.org 70 i case CONTROL('P'): Err bitreich.org 70 i- action_jump(-1); Err bitreich.org 70 i+ matching_prev(current); 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@@ -386,52 +347,11 @@ input_key(FILE *tty_fp) Err bitreich.org 70 i Err bitreich.org 70 i case CONTROL('J'): Err bitreich.org 70 i case CONTROL('M'): /* enter */ Err bitreich.org 70 i- action_print_selection(0); Err bitreich.org 70 i- return EXIT_SUCCESS; Err bitreich.org 70 i- Err bitreich.org 70 i- case CONTROL('@'): /* ctrl + space */ Err bitreich.org 70 i- action_print_selection(1); Err bitreich.org 70 i+ print_selection(0); Err bitreich.org 70 i return EXIT_SUCCESS; Err bitreich.org 70 i Err bitreich.org 70 i- case CONTROL('['): /* escape */ Err bitreich.org 70 i- switch (fgetc(tty_fp)) { Err bitreich.org 70 i- Err bitreich.org 70 i- case 'O': /* arrow keys */ Err bitreich.org 70 i- switch (fgetc(tty_fp)) { Err bitreich.org 70 i- Err bitreich.org 70 i- case 'A': /* up */ Err bitreich.org 70 i- action_jump(-1); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case 'B': /* Down */ Err bitreich.org 70 i- action_jump(1); Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case '[': /* page control */ Err bitreich.org 70 i- key = fgetc(tty_fp); Err bitreich.org 70 i- switch(fgetc(tty_fp)) { Err bitreich.org 70 i- Err bitreich.org 70 i- case '~': Err bitreich.org 70 i- switch (key) { Err bitreich.org 70 i- Err bitreich.org 70 i- case '5': /* page up */ Err bitreich.org 70 i- action_jump(-10); Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i- case '6': /* page down */ Err bitreich.org 70 i- action_jump(10); Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i- break; Err bitreich.org 70 i- } Err bitreich.org 70 i- break; Err bitreich.org 70 i- Err bitreich.org 70 i default: Err bitreich.org 70 i- action_add_character(key); Err bitreich.org 70 i+ add_character(key); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i return CONTINUE; Err bitreich.org 70 i@@ -439,129 +359,26 @@ input_key(FILE *tty_fp) Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i /* Err bitreich.org 70 i- * Set the buffer[current] line to next/previous/any matching line. Err bitreich.org 70 i- */ Err bitreich.org 70 i-void Err bitreich.org 70 i-action_jump(int direction) Err bitreich.org 70 i-{ Err bitreich.org 70 i- Line * line = buffer[current]; Err bitreich.org 70 i- Line * result = line; Err bitreich.org 70 i- Err bitreich.org 70 i- if (direction == 0 && !buffer[current]->match) { Err bitreich.org 70 i- line = matching_next(current); Err bitreich.org 70 i- line = line ? line : matching_prev(current); Err bitreich.org 70 i- result = line ? line : result; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- for (; direction < 0 && line; direction++) { Err bitreich.org 70 i- line = matching_prev(line); Err bitreich.org 70 i- result = line ? line : result; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- for (; direction > 0 && line; direction--) { Err bitreich.org 70 i- line = matching_next(line); Err bitreich.org 70 i- result = line ? line : result; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- buffer[current] = result; 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- * Remove the last word from the buffer's input Err bitreich.org 70 i- */ Err bitreich.org 70 i-void Err bitreich.org 70 i-action_remove_word_input() Err bitreich.org 70 i-{ Err bitreich.org 70 i- size_t len = strlen(input) - 1; Err bitreich.org 70 i- Err bitreich.org 70 i- for (int i = len; i >= 0 && isspace(input[i]); i--) Err bitreich.org 70 i- input[i] = '\0'; Err bitreich.org 70 i- Err bitreich.org 70 i- len = strlen(input) - 1; Err bitreich.org 70 i- for (int i = len; i >= 0 && !isspace(input[i]); i--) Err bitreich.org 70 i- input[i] = '\0'; 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- * Add a character to the buffer input and filter lines again. Err bitreich.org 70 i- */ Err bitreich.org 70 i-void Err bitreich.org 70 i-action_add_character(char key) Err bitreich.org 70 i-{ Err bitreich.org 70 i- size_t len = strlen(input); Err bitreich.org 70 i- Err bitreich.org 70 i- if (isprint(key)) { Err bitreich.org 70 i- input[len] = key; Err bitreich.org 70 i- input[len + 1] = '\0'; Err bitreich.org 70 i- } Err bitreich.org 70 i- Err bitreich.org 70 i- filter_lines(1); Err bitreich.org 70 i- Err bitreich.org 70 i- action_jump(0); 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- * Send the selection to stdout. Err bitreich.org 70 i- */ Err bitreich.org 70 i-void Err bitreich.org 70 i-action_print_selection(int return_input) Err bitreich.org 70 i-{ Err bitreich.org 70 i- fputs("\r\033[K", stderr); Err bitreich.org 70 i- Err bitreich.org 70 i- if (return_input || !matching) { 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- } Err bitreich.org 70 i-} Err bitreich.org 70 i- Err bitreich.org 70 i- Err bitreich.org 70 i-opt_line_numbers = 0; Err bitreich.org 70 i-opt_print_number = 0; Err bitreich.org 70 i-opt_lines = 30; Err bitreich.org 70 i-opt_prompt = ""; Err bitreich.org 70 i- Err bitreich.org 70 i- Err bitreich.org 70 i-/* Err bitreich.org 70 i- * Reset the terminal state and exit with error. Err bitreich.org 70 i- */ Err bitreich.org 70 i-void Err bitreich.org 70 i-die(const char *s) Err bitreich.org 70 i-{ Err bitreich.org 70 i- /* tcsetattr(STDIN_FILENO, TCSANOW, &termio_old); */ Err bitreich.org 70 i- fprintf(stderr, "%s\n", s); Err bitreich.org 70 i- exit(EXIT_FAILURE); 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- * Set terminal to send one char at a time for interactive mode, and return the Err bitreich.org 70 i- * last terminal state. Err bitreich.org 70 i+ * Listen for the user input and call the appropriate functions. Err bitreich.org 70 i */ Err bitreich.org 70 i-struct termios Err bitreich.org 70 i-set_terminal(int tty_fd) Err bitreich.org 70 i+int Err bitreich.org 70 i+input_get(int tty_fd) Err bitreich.org 70 i { Err bitreich.org 70 i- struct termios termio_old; Err bitreich.org 70 i- struct termios termio_new; Err bitreich.org 70 i+ FILE *tty_fp = fopen("/dev/tty", "r"); Err bitreich.org 70 i+ int exit_code; 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+ /* receive one character at a time from the terminal */ Err bitreich.org 70 i+ struct termios termio_old = set_terminal(tty_fd); 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+ while ((exit_code = input_key(tty_fp)) == CONTINUE) Err bitreich.org 70 i+ draw_screen(tty_fd); 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+ /* resets the terminal to the previous state. */ Err bitreich.org 70 i+ tcsetattr(tty_fd, TCSANOW, &termio_old); 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+ fclose(tty_fp); Err bitreich.org 70 i Err bitreich.org 70 i- return termio_old; Err bitreich.org 70 i+ return exit_code; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i@@ -578,8 +395,6 @@ int Err bitreich.org 70 i main(int argc, char *argv[]) Err bitreich.org 70 i { Err bitreich.org 70 i int i, exit_code, tty_fd = open("/dev/tty", O_RDWR); Err bitreich.org 70 i- Buffer *buffer = NULL; Err bitreich.org 70 i- Opt *opt = malloc(sizeof(Opt)); Err bitreich.org 70 i Err bitreich.org 70 i Err bitreich.org 70 i /* command line arguments */ Err bitreich.org 70 i@@ -588,9 +403,6 @@ main(int argc, char *argv[]) Err bitreich.org 70 i usage(); Err bitreich.org 70 i Err bitreich.org 70 i switch (argv[i][1]) { Err bitreich.org 70 i- case 'n': Err bitreich.org 70 i- opt_line_numbers = 1; Err bitreich.org 70 i- break; Err bitreich.org 70 i case 'l': Err bitreich.org 70 i if (sscanf(argv[++i], "%d", &opt_lines) <= 0) Err bitreich.org 70 i die("wrong number format after -l"); Err bitreich.org 70 i@@ -606,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- buffer = fill_buffer(); Err bitreich.org 70 i+ fill_buffer(); 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@@ -618,7 +430,6 @@ 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(opt); Err bitreich.org 70 i free_buffer(buffer); Err bitreich.org 70 i Err bitreich.org 70 i return exit_code; Err bitreich.org 70 .