123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- * shell_help.c
- */
- #include "private.h"
- #include "clish/types.h"
- #include "lub/string.h"
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- /*--------------------------------------------------------- */
- /*
- * Provide a detailed list of the possible command completions
- */
- static void available_commands(clish_shell_t *this,
- clish_help_t *help, const char *line, size_t *max_width)
- {
- const clish_command_t *cmd;
- clish_shell_iterator_t iter;
- if (max_width)
- *max_width = 0;
- /* Search for COMMAND completions */
- clish_shell_iterator_init(&iter, CLISH_NSPACE_HELP);
- while ((cmd = clish_shell_find_next_completion(this, line, &iter))) {
- size_t width;
- const char *name = clish_command__get_suffix(cmd);
- if (max_width) {
- width = strlen(name);
- if (width > *max_width)
- *max_width = width;
- }
- lub_argv_add(help->name, name);
- lub_argv_add(help->help, clish_command__get_text(cmd));
- lub_argv_add(help->detail, clish_command__get_detail(cmd));
- }
- }
- /*--------------------------------------------------------- */
- static int available_params(clish_shell_t *this,
- clish_help_t *help, const clish_command_t *cmd,
- const char *line, size_t *max_width)
- {
- unsigned index = lub_argv_wordcount(line);
- unsigned idx = lub_argv_wordcount(clish_command__get_name(cmd));
- lub_argv_t *argv;
- clish_pargv_t *completion, *pargv;
- unsigned i;
- unsigned cnt = 0;
- clish_pargv_status_t status = CLISH_LINE_OK;
- clish_context_t context;
- /* Empty line */
- if (0 == index)
- return -1;
- if (line[strlen(line) - 1] != ' ')
- index--;
- argv = lub_argv_new(line, 0);
- /* get the parameter definition */
- completion = clish_pargv_new();
- pargv = clish_pargv_new();
- /* Prepare context */
- context.shell = this;
- context.cmd = cmd;
- context.action = NULL;
- context.pargv = pargv;
- status = clish_shell_parse_pargv(pargv, cmd, &context,
- clish_command__get_paramv(cmd),
- argv, &idx, completion, index);
- clish_pargv_delete(pargv);
- cnt = clish_pargv__get_count(completion);
- /* Calculate the longest name */
- for (i = 0; i < cnt; i++) {
- const clish_param_t *param;
- const char *name;
- unsigned clen = 0;
- param = clish_pargv__get_param(completion, i);
- if (CLISH_PARAM_SUBCOMMAND == clish_param__get_mode(param))
- name = clish_param__get_value(param);
- else
- name = clish_ptype__get_text(clish_param__get_ptype(param));
- if (name)
- clen = strlen(name);
- if (max_width && (clen > *max_width))
- *max_width = clen;
- clish_param_help(param, help);
- }
- clish_pargv_delete(completion);
- lub_argv_delete(argv);
- /* It's a completed command */
- if (CLISH_LINE_OK == status)
- return 0;
- /* Incompleted command */
- return -1;
- }
- /*--------------------------------------------------------- */
- void clish_shell_help(clish_shell_t *this, const char *line)
- {
- clish_help_t help;
- size_t max_width = 0;
- const clish_command_t *cmd;
- int i;
- help.name = lub_argv_new(NULL, 0);
- help.help = lub_argv_new(NULL, 0);
- help.detail = lub_argv_new(NULL, 0);
- /* Get COMMAND completions */
- available_commands(this, &help, line, &max_width);
- /* Resolve a command */
- cmd = clish_shell_resolve_command(this, line);
- /* Search for PARAM completion */
- if (cmd) {
- size_t width = 0;
- int status;
- status = available_params(this, &help, cmd, line, &width);
- if (width > max_width)
- max_width = width;
- /* Add <cr> if command is completed */
- if (!status) {
- lub_argv_add(help.name, "<cr>");
- lub_argv_add(help.help, NULL);
- lub_argv_add(help.detail, NULL);
- }
- }
- if (lub_argv__get_count(help.name) == 0)
- goto end;
- /* Print help messages */
- for (i = 0; i < lub_argv__get_count(help.name); i++) {
- fprintf(stderr, " %-*s %s\n", (int)max_width,
- lub_argv__get_arg(help.name, i),
- lub_argv__get_arg(help.help, i) ?
- lub_argv__get_arg(help.help, i) : "");
- }
- /* Print details */
- if ((lub_argv__get_count(help.name) == 1) &&
- (SHELL_STATE_HELPING == this->state)) {
- const char *detail = lub_argv__get_arg(help.detail, 0);
- if (detail)
- fprintf(stderr, "%s\n", detail);
- }
- /* update the state */
- if (this->state == SHELL_STATE_HELPING)
- this->state = SHELL_STATE_OK;
- else
- this->state = SHELL_STATE_HELPING;
- end:
- lub_argv_delete(help.name);
- lub_argv_delete(help.help);
- lub_argv_delete(help.detail);
- }
- /*--------------------------------------------------------- */
|