iomenu

interactive text selection menu
Log | Files | Refs | README | LICENSE

commit 9786d2c290cdd4b3a37979155ced24f86f8358f5
parent 6a1d1b6950adc20996a8bf22441762e08f1dabb8
Author: Josuah Demangeonā  ā µ <mail@josuah.net>
Date:   Wed, 15 Mar 2017 23:02:10 +0100

converted buffer.c from linked list to array

Diffstat:
MMakefile | 8+++-----
Mbuffer.c | 136++++++++++++++++++++++++-------------------------------------------------------
Miomenu.h | 80++++++++++++++++++++++++++++++++++++++-----------------------------------------
3 files changed, 82 insertions(+), 142 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,8 +1,6 @@ -CFLAGS = -std=c89 -pedantic -Wall -Wextra -g -static +CFLAGS = -std=c99 -pedantic -Wall -Wextra -g -static OBJ = ${SRC:.c=.o} -MANPREFIX = $(PREFIX) - all: clean iomenu iomenu: buffer.c draw.c input.c @@ -11,6 +9,6 @@ clean: rm -f iomenu ${OBJ} install: iomenu - mkdir -p $(PREFIX)/bin $(MANPREFIX)/man/man1 - cp *.1 $(MANPREFIX)/man/man1/ + mkdir -p $(PREFIX)/bin $(PREFIX)/man/man1 + cp *.1 $(PREFIX)/man/man1/ cp iomenu $(PREFIX)/bin/ diff --git a/buffer.c b/buffer.c @@ -9,129 +9,76 @@ /* * Fill the buffer apropriately with the lines */ -Buffer * +void fill_buffer(void) { - /* fill buffer with string */ - char s[LINE_SIZE]; - Line **buffer = malloc(sizeof(Line)); - FILE *fp = stdin; - int l; + extern Line **buffer; + + char s[LINE_SIZE]; + size_t size = 1; - if (!fp) - die("Can not open file for reading."); + buffer = malloc(sizeof(Line) * 2 << 4); input[0] = '\0'; total = matching = 1; - /* empty line in case no line come from stdin */ - first = buffer[current] = malloc(sizeof(Line)); - first->next = first->prev = NULL; - last = NULL; - - /* read the file into a doubly linked list of lines */ - for (l = 1; fgets(s, LINE_SIZE, fp); total++, l++) - last = add_line(l, s, last); - - return buffer; -} - + /* read the file into an array of lines */ + for (; fgets(s, LINE_SIZE, stdin); total++, matching++) { + if (total > size) { + size *= 2; + if (!realloc(buffer, size * sizeof(Line))) + die("realloc"); + } -/* - * Add a line to the end of the buffer[current] buffer. - */ -Line * -add_line( int number, Line *prev) -{ - /* allocate new line */ - last = new_line(s); - last->number = number; - last->matches = 1; /* matches by default */ - matching++; - - /* interlink with previous line if exists */ - if (prev) { - prev->next = last; - last->prev = prev; - } else { - first = last; + buffer[total]->text[strlen(s) - 1] = '\0'; + buffer[total]->match = 1; /* empty input match everything */ } - - return last; } -Line * -new_line(char *s) -{ - Line *line = malloc(sizeof(Line)); - - /* strip trailing newline */ - s[strlen(s) - 1] = '\0'; - - /* fill line->content */ - line->content = s; - - return line; -} - - -/* - * Free the also recursing the doubly linked list. - */ void -free_buffer(Buffer *buffer) +free_buffer(Line **buffer) { Line *next = NULL; - while (first) { - next = first->next; - - free(first); - - first = next; - } + for (; total > 0; total--) + free(buffer[total - 1]->text); free(buffer); } /* - * Set the line->matching state according to the return value of match_line, - * and matching to number of matching candidates. - * - * The incremental parameter sets whether check already matching or - * non-matching lines only. This is for performance concerns. + * If inc is 1, it will only check already matching lines. + * If inc is 0, it will only check non-matching lines. */ void -filter_lines( int inc) +filter_lines(int inc) { - Line *line = first; char **tokv = NULL; - char *s, buf[sizeof input]; + char *s, buf[sizeof(input)]; size_t n = 0, tokc = 0; /* 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("cannot realloc memory for tokv\n"); + die("realloc"); tokv[tokc - 1] = s; } /* match lines */ matching = 0; - while (line) { - if (input[0] && !strcmp(input, line->content)) { - line->matches = 1; - buffer[current] = line; - } else if ((inc && line->matches) || (!inc && !line->matches)) { - line->matches = match_line(line, tokv, tokc); - matching += line->matches; - } + for (int i = 0; i < total; i++) { - line = line->next; + if (input[0] && strcmp(input, buffer[i]->text) == 0) { + buffer[i]->match = 1; + + } else if ((inc && buffer[i]->match) || (!inc && !buffer[i]->match)) { + buffer[i]->match = match_line(buffer[i], tokv, tokc); + matching += buffer[i]->match; + } } } @@ -142,12 +89,11 @@ filter_lines( int inc) int match_line(Line *line, char **tokv, size_t tokc) { - size_t i, match = 1, offset = 0; - - for (i = 0; i < tokc && match; i++) - match = !!strstr(line->content + offset, tokv[i]); + for (int i = 0; i < tokc; i++) + if (!!strstr(buffer[i]->text, tokv[i])) + return 0; - return match; + return 1; } @@ -155,10 +101,10 @@ match_line(Line *line, char **tokv, size_t tokc) * Seek the previous matching line, or NULL if none matches. */ Line * -matching_prev(Line *line) +matching_prev(int pos) { - while ((line = line->prev) && !line->matches); - return line; + for (; pos > 0 && !buffer[pos]->match; pos--); + return buffer[pos]; } @@ -166,8 +112,8 @@ matching_prev(Line *line) * Seek the next matching line, or NULL if none matches. */ Line * -matching_next(Line *line) +matching_next(int pos) { - while ((line = line->next) && !line->matches); - return line; + for (; pos < total && !buffer[pos]->match; pos++); + return buffer[pos]; } diff --git a/iomenu.h b/iomenu.h @@ -1,65 +1,61 @@ +/*--- constants --------------------------------------------------------------*/ + #define LINE_SIZE 1024 #define OFFSET 5 #define CONTINUE 2 /* as opposed to EXIT_SUCCESS and EXIT_FAILURE */ + +/*--- macros -----------------------------------------------------------------*/ + #define CONTROL(char) (char ^ 0x40) #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) -/* - * Line coming from stdin - */ +/*--- structures -------------------------------------------------------------*/ + typedef struct Line { - char *content; /* sent as output and matched by input */ - int matches; /* whether it matches buffer's input */ + char *text; /* sent as output and matched by input */ + int match; /* whether it matches buffer's input */ } Line; -/* buffer */ -Line *buffer[]; -int current, matching, total; -Line *first, *last; - -/* flags */ -int opt_line_numbers; -int opt_lines; -char *opt_prompt, *input; +/*--- variables --------------------------------------------------------------*/ +Line **buffer; +int current, matching, total; +int opt_lines; +char *opt_prompt, *input; -/* iomenu */ -void die(const char *); -struct termios set_terminal(int); -void usage(void); +/*--- functions --------------------------------------------------------------*/ +/* iomenu */ +void die(const char *); +struct termios set_terminal(int); +void usage(void); /* buffer */ - -Line ** fill_buffer(char *); -void free_buffer(); -Line * add_line(int, char *, char *, Line *); -Line * new_line(char *, char *); -Line * matching_next(Line *); -Line * matching_prev(Line *); -int match_line(Line *, char **, size_t); -void filter_lines(int); - +void fill_buffer(void); +void free_buffer(); +Line * add_line(int, char *, char *, Line *); +Line * new_line(char *, char *); +Line * matching_next(int); +Line * matching_prev(int); +int match_line(Line *, char **, size_t); +void filter_lines(int); /* draw */ - -void draw_screen(int); -void draw_clear(int); -void draw_line(Line *, int); -void draw_lines(int, int); -void draw_prompt(int); - +void draw_screen(int); +void draw_clear(int); +void draw_line(Line *, int); +void draw_lines(int, int); +void draw_prompt(int); /* input */ - -int input_get(int); -int input_key(FILE *); -void action_jump(int); -void action_print_selection(int); -void action_remove_word_input(); -void action_add_character(char); +int input_get(int); +int input_key(FILE *); +void action_jump(int); +void action_print_selection(int); +void action_remove_word_input(); +void action_add_character(char);