/* * shell_help.c */ #include "private.h" #include "clish/types.h" #include "lub/string.h" #include #include #include /*--------------------------------------------------------- */ /* * 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)); } } /*--------------------------------------------------------- */ 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 = clish_command_help(cmd, &help, this->viewid, line, &width); if (width > max_width) max_width = width; /* Add if command is completed */ if (!status) { lub_argv_add(help.name, ""); 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); } /*--------------------------------------------------------- */