Handle tab at the begining
[iomenu.git] / input.c
blob5c28d256617a90413116e86e30aed6fd1e8d87fc
1 #include <ctype.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <termios.h>
7 #include "input.h"
8 #include "util.h"
9 #include "draw.h"
10 #include "buffer.h"
13 * Listen for the user input and call the appropriate functions.
15 void
16 input_get(Buffer *buffer, int offset, int tty_fd, Opt *opt)
18 FILE *tty_fp = fopen("/dev/tty", "r");
20 /* receive one character at a time from the terminal */
21 struct termios termio_old = set_terminal(tty_fd);
23 /* get input char by char from the keyboard. */
24 while (input_key(fgetc(tty_fp), buffer, opt)) {
25 draw_screen(buffer, offset, tty_fd, opt);
28 /* resets the terminal to the previous state. */
29 tcsetattr(tty_fd, TCSANOW, &termio_old);
31 fclose(tty_fp);
35 * Perform action associated with key
37 int
38 input_key(char key, Buffer *buffer, Opt *opt)
40 if (key == opt->validate_key) {
41 action_print_selection(buffer, opt);
42 return FALSE;
45 switch (key) {
47 case CONTROL('C'):
48 draw_clear(opt->lines);
49 exit(EXIT_FAILURE);
50 break; /* never reached */
52 case CONTROL('U'):
53 buffer->input[0] = '\0';
54 buffer->current = buffer->first;
55 filter_lines(buffer, opt);
56 action_jump(buffer, BOTH, opt);
57 break;
59 case CONTROL('W'):
60 action_remove_word_input(buffer);
61 filter_lines(buffer, opt);
62 break;
64 case 127:
65 case CONTROL('H'): /* backspace */
66 buffer->input[strlen(buffer->input) - 1] = '\0';
67 filter_lines(buffer, opt);
69 if (!buffer->current->matches) {
70 action_jump(buffer, BOTH, opt);
72 break;
74 case CONTROL('N'):
75 action_jump(buffer, NEXT, opt);
76 break;
78 case CONTROL('P'):
79 action_jump(buffer, PREV, opt);
80 break;
82 case CONTROL('I'): /* tab */
83 strcpy(buffer->input, buffer->current->content);
84 filter_lines(buffer, opt);
85 break;
87 case CONTROL('M'):
88 case CONTROL('J'): /* enter */
89 action_print_selection(buffer, opt);
90 return FALSE;
92 default:
93 action_add_character(buffer, key, opt);
96 return TRUE;
100 * Set the current line to the next/previous/closest matching line.
102 void
103 action_jump(Buffer *buffer, int direction, Opt *opt)
105 Line * line = buffer->current;
107 if (direction == BOTH) {
108 line = matching_next(buffer->current);
109 line = (line) ? line : matching_prev(buffer->current);
110 } else if (direction == NEXT) {
111 line = matching_next(line);
112 } else if (direction == PREV) {
113 line = matching_prev(line);
116 buffer->current = (line) ? line : buffer->current;
118 if (opt->print_numbers)
119 action_print_selection(buffer, opt);
123 * Send the selection to stdout.
125 void
126 action_print_selection(Buffer *buffer, Opt *opt)
128 fputs("\r\033[K", stderr);
130 if (opt->print_numbers) {
131 printf("%d\n", buffer->current->number);
132 } else {
133 if (opt->complete) {
134 puts(buffer->input);
135 } else {
136 puts(buffer->current->content);
142 * Remove the last word from the buffer's input
144 void
145 action_remove_word_input(Buffer *buffer)
147 size_t length = strlen(buffer->input) - 1;
148 int i;
150 for (i = length; i >= 0 && isspace(buffer->input[i]); i--) {
151 buffer->input[i] = '\0';
154 length = strlen(buffer->input) - 1;
155 for (i = length; i >= 0 && !isspace(buffer->input[i]); i--) {
156 buffer->input[i] = '\0';
161 * Add a character to the buffer input and filter lines again.
163 void
164 action_add_character(Buffer *buffer, char key, Opt *opt)
166 size_t length = strlen(buffer->input);
168 if (isprint(key)) {
169 buffer->input[length] = key;
170 buffer->input[length + 1] = '\0';
173 filter_lines(buffer, opt);
175 if (!buffer->current->matches) {
176 action_jump(buffer, BOTH, opt);
179 if (!buffer->current->matches) {
180 buffer->current = buffer->empty;