fix bracket evaluation
[calc.git] / readline.c
1 #include <malloc.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include <readline/readline.h>
6 #include <readline/history.h>
7
8 #include "alloc.h"
9 #include "debug.h"
10 #include "element.h"
11
12 #include "readline.h"
13
14 /* constants */
15
16 #define HISTORY_LEN 10
17
18 /* macros */
19
20 /* gobal variables */
21
22 char **completion_list = NULL;
23
24 /* completion function */
25
26 char *generator (const char *text, int state)
27 {
28 static int index, len;
29 char *name;
30
31 if (!state) {
32 index = 0;
33 len = strlen(text);
34 }
35
36 while ((name = completion_list[index++])) {
37 if (strncmp (name, text, len) == 0) {
38 return strdup (name);
39 }
40 }
41
42 return NULL;
43 }
44
45 char **completion (const char *text, __attribute__((unused)) int start, __attribute__((unused)) int end)
46 {
47 rl_attempted_completion_over = 1;
48 return rl_completion_matches (text, generator);
49 }
50
51 /* edit line */
52 char *edit_line = NULL;
53 int edit_hook ()
54 {
55 static int state = 0;
56 if (edit_line) {
57 if (state == 0) {
58 state = 1;
59 } else {
60 state = 0;
61 free (edit_line);
62 edit_line = NULL;
63 }
64 }
65 return rl_insert_text (edit_line);
66 }
67
68 /* history management */
69
70 void history ()
71 {
72 HIST_ENTRY **entries = history_list ();
73 if (entries == NULL) {
74 VERBOSE (WARNING, fprintf (stdout, "no history\n"));
75 } else {
76 int i = 0;
77 while (entries[i] != NULL) {
78 printf ("%d: %s\n", history_length - i, entries[i]->line);
79 i++;
80 }
81 }
82 }
83
84 /* init readline */
85
86 void init_read_line ()
87 {
88 /* completion list*/
89 completion_list = generate_completion_list ();
90 rl_attempted_completion_function = completion;
91
92 /* edit program */
93 rl_startup_hook = edit_hook;
94
95 /* readline parameters */
96 rl_variable_bind ("blink-matching-paren", "On");
97 //rl_set_screen_size (50, 40);
98 }
99
100 /* read line */
101
102 int read_line (char **buffer, char *prompt)
103 {
104 if ((*buffer = readline (prompt)) == NULL) {
105 return 1;
106 }
107
108 /* check empty line */
109 if (strlen (*buffer) == 0) {
110 free (*buffer);
111 *buffer = NULL;
112 }
113
114 return 0;
115 }
116
117 /* manage history */
118
119 void manage_history (char *buffer)
120 {
121 /* add line into history */
122 add_history (buffer);
123 VERBOSE (INFO, fprintf (stdout, "line (%d/%d): '%s'\n",
124 where_history (), history_length, buffer));
125 if (history_length > HISTORY_LEN) {
126 HIST_ENTRY *last = remove_history (0);
127 if (last) {
128 free_history_entry (last);
129 }
130 }
131 }
132
133 /* clean readline */
134
135 void clean_read_line (char *buffer)
136 {
137 free_completion_list (completion_list);
138 if (buffer) {
139 free (buffer);
140 }
141 }
142
143 /* generate completion list */
144
145 char **generate_completion_list ()
146 {
147 int i, j, l = 0;
148 char **list = (char **) callocordie (NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1, sizeof (char *));
149
150 for (i = 0; i < NB_OPERATORS; i++) {
151 list[l] = strdup ((operators + i)->keyword);
152 for (j = 0; j < (int)strlen (list[l]); j++) {
153 if (list[i][j] == '\t') {
154 list[i][j] = '\0';
155 }
156 }
157 if (list[l] != NULL) {
158 l++;
159 }
160 }
161
162 for (i = 0; i < NB_FUNCTIONS; i++) {
163 list[l] = strdup ((functions + i)->keyword);
164 if (list[l] != NULL) {
165 l++;
166 }
167 }
168
169 for (i = 0; i < NB_CONSTANTS; i++) {
170 list[l] = strdup ((constants + i)->keyword);
171 if (list[l] != NULL) {
172 l++;
173 }
174 }
175
176 for (i = 0; i < NB_SYMBOLS; i++) {
177 list[l] = strdup (symbols[i]);
178 if (list[l] != NULL) {
179 l++;
180 }
181 }
182
183 return (list);
184 }
185
186 /* free completion list */
187
188 void free_completion_list (char **list)
189 {
190 int i;
191
192 if (list) {
193 for (i = 0; i < NB_OPERATORS + NB_FUNCTIONS + NB_CONSTANTS + NB_SYMBOLS + 1; i++) {
194 if (list[i] != NULL) {
195 free (list[i]);
196 }
197 }
198 free (list);
199 }
200 }
201
202 /* vim: set ts=4 sw=4 et: */