source: cmd.c @ a5a9572

release-1.7release-1.8release-1.9
Last change on this file since a5a9572 was 385fda9, checked in by David Benjamin <davidben@mit.edu>, 11 years ago
A fairly hacky job of porting sepbar to owl_window We now use the new framework, but the sepbar isn't being marked dirty at the appropriate times. It'll want to be redone later to take advantage of the new signals. The 'in' parameter was also dropped. It was being unused. At best it provided a strange bug when resizing with appendtosepbar set. Also revert the attempt at cleaning up the cursor. We still have a hack, but using owl_window. The cursor probably needs integration with the context stack or some such.
  • Property mode set to 100644
File size: 8.9 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include "owl.h"
6
7extern const owl_cmd commands_to_init[];
8
9/**************************************************************************/
10/***************************** COMMAND DICT *******************************/
11/**************************************************************************/
12
13int owl_cmddict_setup(owl_cmddict *cd) {
14  if (0 != owl_cmddict_init(cd)) return(-1);
15  if (0 != owl_cmddict_add_from_list(cd, commands_to_init)) return(-1);
16  return(0);
17}
18
19int owl_cmddict_init(owl_cmddict *cd) {
20  if (owl_dict_create(cd)) return(-1);
21  return(0);
22}
23
24/* for bulk initialization at startup */
25int owl_cmddict_add_from_list(owl_cmddict *cd, const owl_cmd *cmds) {
26  const owl_cmd *cur;
27  int ret = 0;
28  for (cur = cmds; cur->name != NULL; cur++) {
29    ret = owl_cmddict_add_cmd(cd, cur);
30    if (ret < 0) break;
31  }
32  return ret;
33}
34
35/* free the list with owl_cmddict_namelist_cleanup */
36void owl_cmddict_get_names(const owl_cmddict *d, owl_list *l) {
37  owl_dict_get_keys(d, l);
38}
39
40const owl_cmd *owl_cmddict_find(const owl_cmddict *d, const char *name) {
41  return owl_dict_find_element(d, name);
42}
43
44void owl_cmddict_namelist_cleanup(owl_list *l)
45{
46  owl_list_cleanup(l, owl_free);
47}
48
49/* creates a new command alias */
50int owl_cmddict_add_alias(owl_cmddict *cd, const char *alias_from, const char *alias_to) {
51  owl_cmd *cmd;
52  cmd = owl_malloc(sizeof(owl_cmd));
53  owl_cmd_create_alias(cmd, alias_from, alias_to);
54  owl_dict_insert_element(cd, cmd->name, cmd, (void (*)(void *))owl_cmd_delete);
55  return(0);
56}
57
58int owl_cmddict_add_cmd(owl_cmddict *cd, const owl_cmd * cmd) {
59  owl_cmd * newcmd = owl_malloc(sizeof(owl_cmd));
60  if(owl_cmd_create_from_template(newcmd, cmd) < 0) {
61    owl_free(newcmd);
62    return -1;
63  }
64  owl_perlconfig_new_command(cmd->name);
65  return owl_dict_insert_element(cd, newcmd->name, newcmd, (void (*)(void *))owl_cmd_delete);
66}
67
68char *_owl_cmddict_execute(const owl_cmddict *cd, const owl_context *ctx, const char *const *argv, int argc, const char *buff) {
69  char *retval = NULL;
70  const owl_cmd *cmd;
71
72  if (!strcmp(argv[0], "")) {
73  } else if (NULL != (cmd = owl_dict_find_element(cd, argv[0]))) {
74    retval = owl_cmd_execute(cmd, cd, ctx, argc, argv, buff);
75  } else {
76    owl_function_makemsg("Unknown command '%s'.", buff);
77  }
78  return retval;
79}
80
81char *owl_cmddict_execute(const owl_cmddict *cd, const owl_context *ctx, const char *cmdbuff) {
82  char **argv;
83  int argc;
84  char *tmpbuff;
85  char *retval = NULL;
86
87  tmpbuff=owl_strdup(cmdbuff);
88  argv=owl_parseline(tmpbuff, &argc);
89  if (argc < 0) {
90    owl_free(tmpbuff);
91    sepbar_dirty();
92    owl_function_makemsg("Unbalanced quotes");
93    return NULL;
94  } 
95 
96  if (argc < 1) {
97    owl_parse_delete(argv, argc);
98    owl_free(tmpbuff);
99    return NULL;
100  }
101
102  retval = _owl_cmddict_execute(cd, ctx, strs(argv), argc, cmdbuff);
103
104  owl_parse_delete(argv, argc);
105  owl_free(tmpbuff);
106  sepbar_dirty();
107  return retval;
108}
109
110char *owl_cmddict_execute_argv(const owl_cmddict *cd, const owl_context *ctx, const char *const *argv, int argc) {
111  char *buff, *ptr;
112  int len = 0, i;
113  char *retval = NULL;
114
115  for(i = 0; i < argc; i++) {
116    len += strlen(argv[i]) + 1;
117  }
118
119  ptr = buff = owl_malloc(len);
120
121  for(i = 0; i < argc; i++) {
122    strcpy(ptr, argv[i]);
123    ptr += strlen(argv[i]);
124    *(ptr++) = ' ';
125  }
126  *(ptr - 1) = 0;
127
128  retval = _owl_cmddict_execute(cd, ctx, argv, argc, buff);
129
130  owl_free(buff);
131  return retval;
132}
133
134/*********************************************************************/
135/***************************** COMMAND *******************************/
136/*********************************************************************/
137
138/* sets up a new command based on a template, copying strings */
139int owl_cmd_create_from_template(owl_cmd *cmd, const owl_cmd *templ) {
140  *cmd = *templ;
141  if (!templ->name) return(-1);
142  cmd->name = owl_strdup(templ->name);
143  if (templ->summary)     cmd->summary     = owl_strdup(templ->summary);
144  if (templ->usage)       cmd->usage       = owl_strdup(templ->usage);
145  if (templ->description) cmd->description = owl_strdup(templ->description);
146  if (templ->cmd_aliased_to) cmd->cmd_aliased_to = owl_strdup(templ->cmd_aliased_to);
147  return(0);
148}
149
150int owl_cmd_create_alias(owl_cmd *cmd, const char *name, const char *aliased_to) {
151  memset(cmd, 0, sizeof(owl_cmd));
152  cmd->name = owl_strdup(name);
153  cmd->cmd_aliased_to = owl_strdup(aliased_to);
154  cmd->summary = owl_sprintf("%s%s", OWL_CMD_ALIAS_SUMMARY_PREFIX, aliased_to);
155  return(0);
156}
157
158void owl_cmd_cleanup(owl_cmd *cmd)
159{
160  if (cmd->name) owl_free(cmd->name);
161  if (cmd->summary) owl_free(cmd->summary);
162  if (cmd->usage) owl_free(cmd->usage);
163  if (cmd->description) owl_free(cmd->description);
164  if (cmd->cmd_aliased_to) owl_free(cmd->cmd_aliased_to);
165  if (cmd->cmd_perl) owl_perlconfig_cmd_cleanup(cmd);
166}
167
168void owl_cmd_delete(owl_cmd *cmd)
169{
170  owl_cmd_cleanup(cmd);
171  owl_free(cmd);
172}
173
174int owl_cmd_is_context_valid(const owl_cmd *cmd, const owl_context *ctx) { 
175  if (owl_context_matches(ctx, cmd->validctx)) return 1;
176  else return 0;
177}
178
179char *owl_cmd_execute(const owl_cmd *cmd, const owl_cmddict *cd, const owl_context *ctx, int argc, const char *const *argv, const char *cmdbuff) {
180  static int alias_recurse_depth = 0;
181  int ival=0;
182  const char *cmdbuffargs;
183  char *newcmd, *rv=NULL;
184
185  if (argc < 1) return(NULL);
186
187  /* Recurse if this is an alias */
188  if (cmd->cmd_aliased_to) {
189    if (alias_recurse_depth++ > 50) {
190      owl_function_makemsg("Alias loop detected for '%s'.", cmdbuff);
191    } else {
192      cmdbuffargs = skiptokens(cmdbuff, 1);
193      newcmd = owl_sprintf("%s %s", cmd->cmd_aliased_to, cmdbuffargs);
194      rv = owl_function_command(newcmd);
195      owl_free(newcmd);
196    } 
197    alias_recurse_depth--;
198    return rv;
199  }
200
201  /* Do validation and conversions */
202  if (cmd->cmd_ctxargs_fn || cmd->cmd_ctxv_fn || cmd->cmd_ctxi_fn) {
203    if (!owl_cmd_is_context_valid(cmd, ctx)) {
204      owl_function_makemsg("Invalid context for command '%s'.", cmdbuff);
205      return NULL;
206    }
207  }
208
209  if ((argc != 1) && (cmd->cmd_v_fn || cmd->cmd_ctxv_fn)) {
210    owl_function_makemsg("Wrong number of arguments for %s command.", argv[0]);
211    return NULL;
212  }
213
214  if (cmd->cmd_i_fn || cmd->cmd_ctxi_fn) {
215      char *ep;
216      if (argc != 2) {
217        owl_function_makemsg("Wrong number of arguments for %s command.", argv[0]);
218        return NULL;
219      }
220      ival = strtol(argv[1], &ep, 10);
221      if (*ep || ep==argv[1]) {
222        owl_function_makemsg("Invalid argument '%s' for %s command.", argv[1], argv[0]);
223        return(NULL);
224      }
225  }
226
227  if (cmd->cmd_args_fn) {
228    return cmd->cmd_args_fn(argc, argv, cmdbuff);
229  } else if (cmd->cmd_v_fn) {   
230    cmd->cmd_v_fn();
231  } else if (cmd->cmd_i_fn) {
232    cmd->cmd_i_fn(ival);
233  } else if (cmd->cmd_ctxargs_fn) {
234    return cmd->cmd_ctxargs_fn(owl_context_get_data(ctx), argc, argv, cmdbuff);
235  } else if (cmd->cmd_ctxv_fn) {   
236    cmd->cmd_ctxv_fn(owl_context_get_data(ctx));
237  } else if (cmd->cmd_ctxi_fn) {
238    cmd->cmd_ctxi_fn(owl_context_get_data(ctx), ival);
239  } else if (cmd->cmd_perl) {
240    return owl_perlconfig_perlcmd(cmd, argc, argv);
241  }
242
243  return NULL;
244}
245
246/* returns a reference */
247const char *owl_cmd_get_summary(const owl_cmd *cmd) {
248  return cmd->summary;
249}
250
251/* returns a summary line describing this keymap.  the caller must free. */
252char *owl_cmd_describe(const owl_cmd *cmd) {
253  if (!cmd || !cmd->name || !cmd->summary) return NULL;
254  return owl_sprintf("%-25s - %s", cmd->name, cmd->summary);
255}
256
257
258
259void owl_cmd_get_help(const owl_cmddict *d, const char *name, owl_fmtext *fm) {
260  const char *s;
261  char *indent;
262  owl_cmd *cmd;
263
264  if (!name || (cmd = owl_dict_find_element(d, name)) == NULL) {
265    owl_fmtext_append_bold(fm, "OWL HELP\n\n");
266    owl_fmtext_append_normal(fm, "No such command...\n");
267    return;
268  }
269
270  owl_fmtext_append_bold(fm, "OWL HELP\n\n");
271  owl_fmtext_append_bold(fm, "NAME\n\n");
272  owl_fmtext_append_normal(fm, OWL_TABSTR);
273  owl_fmtext_append_normal(fm, cmd->name);
274
275  if (cmd->summary && *cmd->summary) {
276    owl_fmtext_append_normal(fm, " - ");
277    owl_fmtext_append_normal(fm, cmd->summary);
278  }
279  owl_fmtext_append_normal(fm, "\n");
280
281  if (cmd->usage && *cmd->usage) {
282    s = cmd->usage;
283    indent = owl_malloc(strlen(s)+(owl_text_num_lines(s)+3)*OWL_TAB+1);
284    owl_text_indent(indent, s, OWL_TAB);
285    owl_fmtext_append_bold(fm, "\nSYNOPSIS\n");
286    owl_fmtext_append_normal(fm, indent);
287    owl_fmtext_append_normal(fm, "\n");
288    owl_free(indent);
289  } else {
290    owl_fmtext_append_bold(fm, "\nSYNOPSIS\n");
291    owl_fmtext_append_normal(fm, OWL_TABSTR);
292    owl_fmtext_append_normal(fm, cmd->name);
293    owl_fmtext_append_normal(fm, "\n");
294  }
295
296  if (cmd->description && *cmd->description) {
297    s = cmd->description;
298    indent = owl_malloc(strlen(s)+(owl_text_num_lines(s)+3)*OWL_TAB+1);
299    owl_text_indent(indent, s, OWL_TAB);
300    owl_fmtext_append_bold(fm, "\nDESCRIPTION\n");
301    owl_fmtext_append_normal(fm, indent);
302    owl_fmtext_append_normal(fm, "\n");
303    owl_free(indent);
304  }
305
306  owl_fmtext_append_normal(fm, "\n\n"); 
307}
Note: See TracBrowser for help on using the repository browser.