cont
[protos/libecoli.git] / lib / main-readline.c
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #define _GNU_SOURCE /* for asprintf */
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <assert.h>
32
33 #include <readline/readline.h>
34 #include <readline/history.h>
35
36 #include <ecoli_tk_str.h>
37 #include <ecoli_tk_seq.h>
38 #include <ecoli_tk_space.h>
39 #include <ecoli_tk_or.h>
40 #include <ecoli_tk_shlex.h>
41 #include <ecoli_tk_int.h>
42
43 static struct ec_tk *commands;
44
45 static char *my_completion_entry(const char *s, int state)
46 {
47         static struct ec_completed_tk *c;
48         static struct ec_completed_tk_iter *iter;
49         static const struct ec_completed_tk_elt *elt;
50         char *out_string;
51
52
53         if (state == 0) {
54                 char *line;
55
56                 ec_completed_tk_free(c);
57
58                 line = strdup(rl_line_buffer);
59                 if (line == NULL)
60                         return NULL;
61                 line[rl_point] = '\0';
62
63                 c = ec_tk_complete(commands, line);
64                 free(line);
65                 if (c == NULL)
66                         return NULL;
67
68                 ec_completed_tk_iter_free(iter);
69                 iter = ec_completed_tk_iter_new(c, ITER_MATCH);
70                 if (iter == NULL)
71                         return NULL;
72         }
73
74         elt = ec_completed_tk_iter_next(iter);
75         if (elt == NULL)
76                 return NULL;
77
78         if (asprintf(&out_string, "%s%s", s, elt->add) < 0)
79                 return NULL;
80
81         return out_string;
82 }
83
84 static char **my_attempted_completion(const char *text, int start, int end)
85 {
86         (void)start;
87         (void)end;
88
89         /* remove default file completion */
90         rl_attempted_completion_over = 1;
91
92         return rl_completion_matches(text, my_completion_entry);
93 }
94
95
96 static int show_help(int ignore, int invoking_key)
97 {
98         struct ec_completed_tk *c;
99         char *line;
100
101         (void)ignore;
102         (void)invoking_key;
103
104         printf("\nhelp:\n");
105         line = strdup(rl_line_buffer);
106         if (line == NULL)
107                 return 1;
108         line[rl_point] = '\0';
109
110         c = ec_tk_complete(commands, line);
111         free(line);
112         if (c == NULL)
113                 return 1;
114         ec_completed_tk_dump(stdout, c);
115         ec_completed_tk_free(c);
116
117         rl_forced_update_display();
118
119         return 0;
120 }
121
122 int main(void)
123 {
124         struct ec_parsed_tk *p;
125 //      const char *name;
126         char *line;
127
128         rl_bind_key('?', show_help);
129
130         commands = ec_tk_shlex_new(NULL,
131                 ec_tk_seq_new_list(NULL,
132                         ec_tk_str_new(NULL, "hello"),
133                         ec_tk_or_new_list("name",
134                                 ec_tk_str_new(NULL, "john"),
135                                 ec_tk_str_new(NULL, "johnny"),
136                                 ec_tk_str_new(NULL, "mike"),
137                                 ec_tk_int_new(NULL, 0, 10, 10),
138                                 EC_TK_ENDLIST
139                         ),
140                         EC_TK_ENDLIST
141                 )
142         );
143         if (commands == NULL) {
144                 printf("cannot create token\n");
145                 return 1;
146         }
147
148         rl_attempted_completion_function = my_attempted_completion;
149
150         while (1) {
151                 line = readline("> ");
152                 if (line == NULL)
153                         break;
154
155                 p = ec_tk_parse(commands, line);
156                 ec_parsed_tk_dump(stdout, p);
157                 add_history(line);
158                 ec_parsed_tk_free(p);
159         }
160
161
162         ec_tk_free(commands);
163         return 0;
164 }