Libecoli 0.11.1
Extensible COmmand LIne library
Loading...
Searching...
No Matches
simple-editline/main.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2025, Olivier MATZ <zer0@droids-corp.org>
3 */
4
25
26#include <errno.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31#include <ecoli.h>
32
33#define ID_NAME "id_name"
34#define ID_JOHN "id_john"
35#define ID_COUNT "id_count"
36
37/* stop program when true */
38static bool done;
39
40static int hello_cb(const struct ec_pnode *parse)
41{
42 const char *count;
43 const char *name;
44
45 name = ec_strvec_val(ec_pnode_get_strvec(ec_pnode_find(parse, ID_NAME)), 0);
46 count = ec_strvec_val(ec_pnode_get_strvec(ec_pnode_find(parse, ID_COUNT)), 0);
47
48 printf("you say hello to %s", name);
49 if (count)
50 printf(" %s times", count);
51 printf("\n");
52
53 return 0;
54}
55
56static int bye_cb(const struct ec_pnode *parse)
57{
58 const char *name;
59
60 name = ec_strvec_val(ec_pnode_get_strvec(ec_pnode_find(parse, ID_NAME)), 0);
61 printf("you say bye to %s\n", name);
62
63 return 0;
64}
65
66static int exit_cb(const struct ec_pnode *parse)
67{
68 (void)parse;
69
70 printf("Exit !\n");
71 done = true;
72
73 return 0;
74}
75
76static int check_exit(void *opaque)
77{
78 (void)opaque;
79 return done;
80}
81
82static struct ec_node *create_commands(void)
83{
84 struct ec_node *cmdlist = NULL, *cmd = NULL;
85 struct ec_node *names = NULL;
86 int ret;
87
88 /* the top node containing the list of commands */
89 cmdlist = ec_node("or", EC_NO_ID);
90 if (cmdlist == NULL)
91 goto fail;
92
93 /* a common subtree containing a list of names */
94 names = EC_NODE_OR(
95 ID_NAME,
96 ec_node_str(ID_JOHN, "john"),
97 ec_node_str(EC_NO_ID, "johnny"),
98 ec_node_str(EC_NO_ID, "mike")
99 );
100 if (names == NULL)
101 goto fail;
102
103 /* the hello command */
104 cmd = EC_NODE_SEQ(
105 EC_NO_ID,
106 ec_node_str(EC_NO_ID, "hello"),
107 ec_node_clone(names),
108 ec_node_option(EC_NO_ID, ec_node_int(ID_COUNT, 0, 10, 10))
109 );
110 if (cmd == NULL)
111 goto fail;
112 if (ec_interact_set_callback(cmd, hello_cb) < 0)
113 goto fail;
114 if (ec_interact_set_help(cmd, "say hello to someone several times") < 0)
115 goto fail;
116 if (ec_interact_set_help(ec_node_find(cmd, ID_JOHN), "specific help for john") < 0)
117 goto fail;
118 if (ec_interact_set_help(ec_node_find(cmd, ID_NAME), "the name of the person") < 0)
119 goto fail;
120 if (ec_interact_set_help(ec_node_find(cmd, ID_COUNT), "an integer (0-10)") < 0)
121 goto fail;
122 ret = ec_node_or_add(cmdlist, cmd);
123 cmd = NULL; /* already freed, even on error */
124 if (ret < 0)
125 goto fail;
126
127 /* the bye command */
128 cmd = EC_NODE_SEQ(EC_NO_ID, ec_node_str(EC_NO_ID, "bye"), ec_node_clone(names));
129 if (ec_interact_set_callback(cmd, bye_cb) < 0)
130 goto fail;
131 if (ec_interact_set_help(cmd, "say bye") < 0)
132 goto fail;
133 ret = ec_node_or_add(cmdlist, cmd);
134 cmd = NULL; /* already freed, even on error */
135 if (ret < 0)
136 goto fail;
137
138 /* the exit command */
139 cmd = ec_node_str(EC_NO_ID, "exit");
140 if (ec_interact_set_callback(cmd, exit_cb) < 0)
141 goto fail;
142 if (ec_interact_set_help(cmd, "exit program") < 0)
143 goto fail;
144 ret = ec_node_or_add(cmdlist, cmd);
145 cmd = NULL; /* already freed, even on error */
146 if (ret < 0)
147 goto fail;
148
149 /* the lexer, added above the command list */
150 cmdlist = ec_node_sh_lex(EC_NO_ID, cmdlist);
151 if (cmdlist == NULL)
152 goto fail;
153
154 ec_node_free(names);
155
156 return cmdlist;
157
158fail:
159 fprintf(stderr, "cannot initialize nodes\n");
160 ec_node_free(names);
161 ec_node_free(cmdlist);
162 ec_node_free(cmd);
163 return NULL;
164}
165
166int main(void)
167{
168 struct ec_editline *editline = NULL;
169 struct ec_node *node = NULL;
170
171 if (ec_init() < 0) {
172 fprintf(stderr, "cannot init ecoli: %s\n", strerror(errno));
173 return 1;
174 }
175
176 node = create_commands();
177 if (node == NULL) {
178 fprintf(stderr, "failed to create commands: %s\n", strerror(errno));
179 goto fail;
180 }
181
182 editline = ec_editline("simple-editline", stdin, stdout, stderr, 0);
183 if (editline == NULL) {
184 fprintf(stderr, "Failed to initialize editline\n");
185 goto fail;
186 }
187
188 if (ec_editline_set_prompt(editline, "simple> ") < 0) {
189 fprintf(stderr, "Failed to set prompt\n");
190 goto fail;
191 }
192 ec_editline_set_node(editline, node);
193
194 if (ec_editline_interact(editline, check_exit, NULL) < 0)
195 goto fail;
196
197 ec_editline_free(editline);
198 ec_node_free(node);
199 return 0;
200
201fail:
202 ec_editline_free(editline);
203 ec_node_free(node);
204 return 1;
205}
int ec_editline_set_prompt(struct ec_editline *editline, const char *prompt)
struct ec_editline * ec_editline(const char *prog, FILE *f_in, FILE *f_out, FILE *f_err, enum ec_editline_init_flags flags)
void ec_editline_free(struct ec_editline *editline)
int ec_editline_interact(struct ec_editline *editline, ec_editline_check_exit_cb_t check_exit_cb, void *opaque)
int ec_editline_set_node(struct ec_editline *editline, const struct ec_node *node)
int ec_init(void)
int ec_interact_set_help(struct ec_node *node, const char *help)
int ec_interact_set_callback(struct ec_node *node, ec_interact_command_cb_t cb)
struct ec_node * ec_node_int(const char *id, int64_t min, int64_t max, unsigned int base)
struct ec_node * ec_node_option(const char *id, struct ec_node *node)
int ec_node_or_add(struct ec_node *node, struct ec_node *child)
#define EC_NODE_OR(args...)
Definition node_or.h:23
#define EC_NODE_SEQ(args...)
Definition node_seq.h:29
struct ec_node * ec_node_sh_lex(const char *id, struct ec_node *child)
struct ec_node * ec_node_str(const char *id, const char *str)
struct ec_node * ec_node_clone(struct ec_node *node)
struct ec_node * ec_node(const char *typename, const char *id)
struct ec_node * ec_node_find(struct ec_node *node, const char *id)
#define EC_NO_ID
Definition node.h:64
void ec_node_free(struct ec_node *node)
const struct ec_strvec * ec_pnode_get_strvec(const struct ec_pnode *pnode)
const struct ec_pnode * ec_pnode_find(const struct ec_pnode *root, const char *id)
struct ec_pnode * ec_pnode(const struct ec_node *node)
const char * ec_strvec_val(const struct ec_strvec *strvec, size_t idx)