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;
        }