iomenu

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

commit 6a1d1b6950adc20996a8bf22441762e08f1dabb8
parent 0a259537342b214215afbeb7625ba86142ba7e8f
Author: Josuah Demangeonā  ā µ <mail@josuah.net>
Date:   Mon, 13 Mar 2017 23:22:53 +0100

(broken) removing further code

Diffstat:
Mbuffer.c | 66+++++++++++++++++++++++++++++++++---------------------------------
Mdraw.c | 46+++++++++++++++++++++++-----------------------
Minput.c | 109++++++++++++++++++++++++++++++++++++++-----------------------------------------
Miomenu.c | 43+++++++++++++++----------------------------
Miomenu.h | 52+++++++++++++++++++++++++---------------------------
5 files changed, 149 insertions(+), 167 deletions(-)

diff --git a/buffer.c b/buffer.c @@ -10,7 +10,7 @@ * Fill the buffer apropriately with the lines */ Buffer * -fill_buffer(char *separator) +fill_buffer(void) { /* fill buffer with string */ char s[LINE_SIZE]; @@ -21,48 +21,48 @@ fill_buffer(char *separator) if (!fp) die("Can not open file for reading."); - buffer->input[0] = '\0'; - buffer->total = buffer->matching = 1; + input[0] = '\0'; + total = matching = 1; /* empty line in case no line come from stdin */ - buffer->first = buffer->current = malloc(sizeof(Line)); - buffer->first->next = buffer->first->prev = NULL; - buffer->last = NULL; + 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); buffer->total++, l++) - buffer->last = add_line(buffer, l, s, separator, buffer->last); + for (l = 1; fgets(s, LINE_SIZE, fp); total++, l++) + last = add_line(l, s, last); return buffer; } /* - * Add a line to the end of the current buffer. + * Add a line to the end of the buffer[current] buffer. */ Line * -add_line(Buffer *buffer, int number, char *s, char *separator, Line *prev) +add_line( int number, Line *prev) { /* allocate new line */ - buffer->last = new_line(s, separator); - buffer->last->number = number; - buffer->last->matches = 1; /* matches by default */ - buffer->matching++; + last = new_line(s); + last->number = number; + last->matches = 1; /* matches by default */ + matching++; /* interlink with previous line if exists */ if (prev) { - prev->next = buffer->last; - buffer->last->prev = prev; + prev->next = last; + last->prev = prev; } else { - buffer->first = buffer->last; + first = last; } - return buffer->last; + return last; } Line * -new_line(char *s, char *separator) +new_line(char *s) { Line *line = malloc(sizeof(Line)); @@ -77,19 +77,19 @@ new_line(char *s, char *separator) /* - * Free the buffer, also recursing the doubly linked list. + * Free the also recursing the doubly linked list. */ void free_buffer(Buffer *buffer) { Line *next = NULL; - while (buffer->first) { - next = buffer->first->next; + while (first) { + next = first->next; - free(buffer->first); + free(first); - buffer->first = next; + first = next; } free(buffer); @@ -98,21 +98,21 @@ free_buffer(Buffer *buffer) /* * Set the line->matching state according to the return value of match_line, - * and buffer->matching to number of matching candidates. + * 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. */ void -filter_lines(Buffer *buffer, int inc) +filter_lines( int inc) { - Line *line = buffer->first; + Line *line = first; char **tokv = NULL; - char *s, buf[sizeof buffer->input]; + char *s, buf[sizeof input]; size_t n = 0, tokc = 0; /* tokenize input from space characters, this comes from dmenu */ - strcpy(buf, buffer->input); + 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"); @@ -121,14 +121,14 @@ filter_lines(Buffer *buffer, int inc) } /* match lines */ - buffer->matching = 0; + matching = 0; while (line) { - if (buffer->input[0] && !strcmp(buffer->input, line->content)) { + if (input[0] && !strcmp(input, line->content)) { line->matches = 1; - buffer->current = line; + buffer[current] = line; } else if ((inc && line->matches) || (!inc && !line->matches)) { line->matches = match_line(line, tokv, tokc); - buffer->matching += line->matches; + matching += line->matches; } line = line->next; diff --git a/draw.c b/draw.c @@ -10,21 +10,21 @@ * Print a line to stderr. */ void -draw_line(Line *line, int current, const int cols, Opt *opt) +draw_line(Line *line, const int cols) { - char output[LINE_SIZE * sizeof(char)] = "\033[K"; + char output[LINE_SIZE] = "\033[K"; int n = 0; - if (opt->line_numbers) { - strcat(output, current ? "\033[1;37m" : "\033[1;30m"); + if (opt_line_numbers) { + strcat(output, buffer[current] ? "\033[1;37m" : "\033[1;30m"); sprintf(output + strlen(output), "%7d\033[m ", line->number); } else { - strcat(output, current ? "\033[1;31m > " : " "); + strcat(output, buffer[current] ? "\033[1;31m > " : " "); } n += 8; - /* highlight current line */ - if (current) + /* highlight buffer[current] line */ + if (buffer[current]) strcat(output, "\033[1;33m"); /* content */ @@ -48,23 +48,23 @@ draw_line(Line *line, int current, const int cols, Opt *opt) * The total number oflines printed shall not excess 'count'. */ void -draw_lines(Buffer *buffer, int count, int cols, Opt *opt) +draw_lines( int count, int cols) { - Line *line = buffer->current; + Line *line = buffer[current]; int i = 0; int j = 0; - /* seek back from current line to the first line to print */ + /* seek back from buffer[current] line to the first line to print */ while (line && i < count - OFFSET) { i = line->matches ? i + 1 : i; line = line->prev; } - line = line ? line : buffer->first; + line = line ? line : first; /* print up to count lines that match the input */ while (line && j < count) { if (line->matches) { - draw_line(line, line == buffer->current, cols, opt); + draw_line(line, line == buffer[current], cols); j++; } @@ -83,7 +83,7 @@ draw_lines(Buffer *buffer, int count, int cols, Opt *opt) * This also has to clear the previous lines. */ void -draw_screen(Buffer *buffer, int tty_fd, Opt *opt) +draw_screen( int tty_fd) { struct winsize w; int count; @@ -91,14 +91,14 @@ draw_screen(Buffer *buffer, int tty_fd, Opt *opt) if (ioctl(tty_fd, TIOCGWINSZ, &w) < 0) die("could not get terminal size"); - count = MIN(opt->lines, w.ws_row - 2); + count = MIN(opt_lines, w.ws_row - 2); fputs("\n", stderr); - draw_lines(buffer, count, w.ws_col, opt); + draw_lines(count, w.ws_col); /* go up to the prompt position and update it */ fprintf(stderr, "\033[%dA", count + 1); - draw_prompt(buffer, w.ws_col, opt); + draw_prompt(w.ws_col); } @@ -118,11 +118,11 @@ draw_clear(int lines) * match. */ void -draw_prompt(Buffer *buffer, int cols, Opt *opt) +draw_prompt(int cols) { size_t i; - int matching = buffer->matching; - int total = buffer->total; + int matching = matching; + int total = total; /* for the '/' separator between the numbers */ cols--; @@ -133,12 +133,12 @@ draw_prompt(Buffer *buffer, int cols, Opt *opt) cols -= !matching ? 1 : 0; /* 0 also has one digit*/ /* actual prompt */ - fprintf(stderr, "\r%-6s\033[K\033[1m>\033[m ", opt->prompt); - cols -= 2 + MAX(strlen(opt->prompt), 6); + fprintf(stderr, "\r%-6s\033[K\033[1m>\033[m ", opt_prompt); + cols -= 2 + MAX(strlen(opt_prompt), 6); /* input without overflowing terminal width */ - for (i = 0; i < strlen(buffer->input) && cols > 0; cols--, i++) - fputc(buffer->input[i], stderr); + for (i = 0; i < strlen(input) && cols > 0; cols--, i++) + fputc(input[i], stderr); /* save the cursor position at the end of the input */ fputs("\033[s", stderr); diff --git a/input.c b/input.c @@ -11,7 +11,7 @@ * Listen for the user input and call the appropriate functions. */ int -input_get(Buffer *buffer, int tty_fd, Opt *opt) +input_get(int tty_fd) { FILE *tty_fp = fopen("/dev/tty", "r"); int exit_code; @@ -20,8 +20,8 @@ input_get(Buffer *buffer, int tty_fd, Opt *opt) struct termios termio_old = set_terminal(tty_fd); /* get input char by char from the keyboard. */ - while ((exit_code = input_key(tty_fp, buffer, opt)) == CONTINUE) - draw_screen(buffer, tty_fd, opt); + while ((exit_code = input_key(tty_fp)) == CONTINUE) + draw_screen(tty_fd); /* resets the terminal to the previous state. */ tcsetattr(tty_fd, TCSANOW, &termio_old); @@ -36,61 +36,62 @@ input_get(Buffer *buffer, int tty_fd, Opt *opt) * Perform action associated with key */ int -input_key(FILE *tty_fp, Buffer *buffer, Opt *opt) +input_key(FILE *tty_fp) { char key = fgetc(tty_fp); - if (key == opt->validate_key) { - action_print_selection(buffer, 0, opt); + if (key == '\n') { + action_print_selection(0); return EXIT_SUCCESS; } switch (key) { case CONTROL('C'): - draw_clear(opt->lines); + draw_clear(opt_lines); return EXIT_FAILURE; case CONTROL('U'): - buffer->input[0] = '\0'; - buffer->current = buffer->first; - filter_lines(buffer, 0); - action_jump(buffer, 1); - action_jump(buffer, -1); + input[0] = '\0'; + buffer[current] = first; + filter_lines(0); + action_jump(1); + action_jump(-1); break; case CONTROL('W'): action_remove_word_input(buffer); - filter_lines(buffer, 0); + filter_lines(0); break; case 127: case CONTROL('H'): /* backspace */ - buffer->input[strlen(buffer->input) - 1] = '\0'; - filter_lines(buffer, 0); - action_jump(buffer, 0); + input[strlen(input) - 1] = '\0'; + filter_lines(0); + action_jump(0); break; case CONTROL('N'): - action_jump(buffer, 1); + action_jump(1); + extern char *input; break; case CONTROL('P'): - action_jump(buffer, -1); + action_jump(-1); break; case CONTROL('I'): /* tab */ - strcpy(buffer->input, buffer->current->content); - filter_lines(buffer, 1); + strcpy(input, buffer[current]->content); + filter_lines(1); break; case CONTROL('J'): case CONTROL('M'): /* enter */ - action_print_selection(buffer, 0, opt); + action_print_selection(0); return EXIT_SUCCESS; case CONTROL('@'): /* ctrl + space */ - action_print_selection(buffer, 1, opt); + action_print_selection(1); return EXIT_SUCCESS; case CONTROL('['): /* escape */ @@ -100,11 +101,11 @@ input_key(FILE *tty_fp, Buffer *buffer, Opt *opt) switch (fgetc(tty_fp)) { case 'A': /* up */ - action_jump(buffer, -1); + action_jump(-1); break; case 'B': /* Down */ - action_jump(buffer, 1); + action_jump(1); break; } break; @@ -117,11 +118,11 @@ input_key(FILE *tty_fp, Buffer *buffer, Opt *opt) switch (key) { case '5': /* page up */ - action_jump(buffer, -10); + action_jump(-10); break; case '6': /* page down */ - action_jump(buffer, 10); + action_jump(10); break; } break; @@ -131,7 +132,7 @@ input_key(FILE *tty_fp, Buffer *buffer, Opt *opt) break; default: - action_add_character(buffer, key); + action_add_character(key); } return CONTINUE; @@ -139,17 +140,17 @@ input_key(FILE *tty_fp, Buffer *buffer, Opt *opt) /* - * Set the current line to next/previous/any matching line. + * Set the buffer[current] line to next/previous/any matching line. */ void -action_jump(Buffer *buffer, int direction) +action_jump(int direction) { - Line * line = buffer->current; + Line * line = buffer[current]; Line * result = line; - if (direction == 0 && !buffer->current->matches) { - line = matching_next(buffer->current); - line = line ? line : matching_prev(buffer->current); + if (direction == 0 && !buffer[current]->matches) { + line = matching_next(buffer[current]); + line = line ? line : matching_prev(buffer[current]); result = line ? line : result; } @@ -163,7 +164,7 @@ action_jump(Buffer *buffer, int direction) result = line ? line : result; } - buffer->current = result; + buffer[current] = result; } @@ -171,17 +172,17 @@ action_jump(Buffer *buffer, int direction) * Remove the last word from the buffer's input */ void -action_remove_word_input(Buffer *buffer) +action_remove_word_input() { - size_t length = strlen(buffer->input) - 1; + size_t length = strlen(input) - 1; int i; - for (i = length; i >= 0 && isspace(buffer->input[i]); i--) - buffer->input[i] = '\0'; + for (i = length; i >= 0 && isspace(input[i]); i--) + input[i] = '\0'; - length = strlen(buffer->input) - 1; - for (i = length; i >= 0 && !isspace(buffer->input[i]); i--) - buffer->input[i] = '\0'; + length = strlen(input) - 1; + for (i = length; i >= 0 && !isspace(input[i]); i--) + input[i] = '\0'; } @@ -189,18 +190,18 @@ action_remove_word_input(Buffer *buffer) * Add a character to the buffer input and filter lines again. */ void -action_add_character(Buffer *buffer, char key) +action_add_character(char key) { - size_t length = strlen(buffer->input); + size_t length = strlen(input); if (isprint(key)) { - buffer->input[length] = key; - buffer->input[length + 1] = '\0'; + input[length] = key; + input[length + 1] = '\0'; } - filter_lines(buffer, 1); + filter_lines(1); - action_jump(buffer, 0); + action_jump(0); } @@ -208,20 +209,16 @@ action_add_character(Buffer *buffer, char key) * Send the selection to stdout. */ void -action_print_selection(Buffer *buffer, int return_input, Opt *opt) +action_print_selection(int return_input) { Line *line = NULL; fputs("\r\033[K", stderr); - if (opt->print_number) { - if (buffer->matching > 0) - printf("%d\n", buffer->current->number); + if (return_input || !matching) { + puts(input); - } else if (return_input || !buffer->matching) { - puts(buffer->input); - - } else if (buffer->matching > 0) { - puts(buffer->current->content); + } else if (matching > 0) { + puts(buffer[current]->content); } } diff --git a/iomenu.c b/iomenu.c @@ -1,3 +1,8 @@ +opt_line_numbers = 0; +opt_print_number = 0; +opt_lines = 30; +opt_prompt = ""; + #include <ctype.h> #include <fcntl.h> #include <stdio.h> @@ -43,7 +48,7 @@ set_terminal(int tty_fd) termio_new = termio_old; termio_new.c_lflag &= ~(ICANON | ECHO | IGNBRK); - /* apply this state to current terminal now (TCSANOW) */ + /* apply this state to buffer[current] terminal now (TCSANOW) */ tcsetattr(tty_fd, TCSANOW, &termio_new); return termio_old; @@ -53,8 +58,7 @@ set_terminal(int tty_fd) void usage(void) { - fputs("usage: iomenu [-n] [-N] [-k key] [-s separator] ", stderr); - fputs("[-p prompt] [-l lines]\n", stderr); + fputs("usage: iomenu [-n] [-p prompt] [-l lines]\n", stderr); exit(EXIT_FAILURE); } @@ -67,12 +71,6 @@ main(int argc, char *argv[]) Buffer *buffer = NULL; Opt *opt = malloc(sizeof(Opt)); - opt->line_numbers = 0; - opt->print_number = 0; - opt->validate_key = CONTROL('M'); - opt->separator = NULL; - opt->lines = 30; - opt->prompt = ""; /* command line arguments */ for (i = 1; i < argc; i++) { @@ -81,27 +79,16 @@ main(int argc, char *argv[]) switch (argv[i][1]) { case 'n': - opt->line_numbers = 1; - break; - case 'N': - opt->print_number = 1; - opt->line_numbers = 1; - break; - case 'k': - opt->validate_key = (argv[++i][0] == '^') ? - CONTROL(toupper(argv[i][1])): argv[i][0]; - break; - case 's': - opt->separator = argv[++i]; + opt_line_numbers = 1; break; case 'l': - if (sscanf(argv[++i], "%d", &opt->lines) <= 0) + if (sscanf(argv[++i], "%d", &opt_lines) <= 0) die("wrong number format after -l"); break; case 'p': if (++i >= argc) - die("wrong string format after -p"); - opt->prompt = argv[i]; + die("missing string after -p"); + opt_prompt = argv[i]; break; default: usage(); @@ -109,15 +96,15 @@ main(int argc, char *argv[]) } /* command line arguments */ - buffer = fill_buffer(opt->separator); + buffer = fill_buffer(); /* set the interface */ - draw_screen(buffer, tty_fd, opt); + draw_screen(tty_fd); /* listen and interact to input */ - exit_code = input_get(buffer, tty_fd, opt); + exit_code = input_get(tty_fd); - draw_clear(opt->lines); + draw_clear(opt_lines); /* close files descriptors and pointers, and free memory */ close(tty_fd); diff --git a/iomenu.h b/iomenu.h @@ -8,19 +8,6 @@ /* - * Options from the command line, to pass to each function that need some - */ -typedef struct Opt { - int line_numbers; - int print_number; - char validate_key; - char *separator; - int lines; - char *prompt; -} Opt; - - -/* * Line coming from stdin */ typedef struct Line { @@ -29,6 +16,17 @@ typedef struct Line { } Line; +/* buffer */ +Line *buffer[]; +int current, matching, total; +Line *first, *last; + +/* flags */ +int opt_line_numbers; +int opt_lines; +char *opt_prompt, *input; + + /* iomenu */ void die(const char *); @@ -38,30 +36,30 @@ void usage(void); /* buffer */ -Buffer * fill_buffer(char *); -void free_buffer(Buffer *); -Line * add_line(Buffer *, int, char *, char *, Line *); +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(Buffer *, int); +void filter_lines(int); /* draw */ -void draw_screen(Buffer *, int, Opt *); +void draw_screen(int); void draw_clear(int); -void draw_line(Line *, int, int, Opt *); -void draw_lines(Buffer *, int, int, Opt *); -void draw_prompt(Buffer *, int, Opt *); +void draw_line(Line *, int); +void draw_lines(int, int); +void draw_prompt(int); /* input */ -int input_get(Buffer *, int, Opt *); -int input_key(FILE *, Buffer *, Opt *); -void action_jump(Buffer *, int); -void action_print_selection(Buffer *,int, Opt *); -void action_remove_word_input(Buffer *); -void action_add_character(Buffer *, 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);