/* * shell_help.c */ #include "private.h" #include "lub/string.h" #include #include /*--------------------------------------------------------- */ /* * Provide a detailed list of the possible command completions */ static void available_commands(clish_shell_t * this, const char *line, bool_t full) { char *buf = NULL; size_t max_width = 0; const clish_command_t *cmd; if (NULL == clish_shell_getfirst_command(this, line, CLISH_NSPACE_HELP)) { /* * A totally wrong command has been inputed * Indicate the point of error and display * a list of possible commands */ char *prompt = clish_view__get_prompt(this->view, this->viewid); unsigned error_offset = strlen(prompt) + 1; lub_string_free(prompt); /* find the best match... */ cmd = clish_shell_resolve_prefix(this, line); if (NULL != cmd) { error_offset += strlen(clish_command__get_name(cmd)) + 1; /* take a copy for help purposes */ buf = lub_string_dup(clish_command__get_name(cmd)); } else { /* show all possible commands */ buf = lub_string_dup(""); } /* indicate the point of error */ fprintf(stderr, "%*s\n", error_offset, "^"); } else { /* take a copy */ buf = lub_string_dup(line); } /* iterate round to determine max_width */ for (cmd = clish_shell_getfirst_command(this, buf, CLISH_NSPACE_HELP); cmd; cmd = clish_shell_getnext_command(this, buf)) { size_t width; const char *name; if (full) { name = clish_command__get_name(cmd); } else { name = clish_command__get_suffix(cmd); } width = strlen(name); if (width > max_width) { max_width = width; } } /* now iterate round to print the help */ for (cmd = clish_shell_getfirst_command(this, buf, CLISH_NSPACE_HELP); cmd; cmd = clish_shell_getnext_command(this, buf)) { const char *name; if (full) { name = clish_command__get_name(cmd); } else { name = clish_command__get_suffix(cmd); } fprintf(stderr, " %-*s %s\n", (int)max_width, name, clish_command__get_text(cmd)); } /* cleanup */ lub_string_free(buf); } /*--------------------------------------------------------- */ void clish_shell_help(clish_shell_t * this, const char *line) { const clish_command_t *cmd, *next_cmd, *first_cmd; /* if there are further commands then we need to show them too */ cmd = clish_shell_resolve_prefix(this, line); if (NULL != cmd) { clish_shell_iterator_t iter; /* skip the command already known about */ clish_shell_iterator_init(&iter, CLISH_NSPACE_HELP); first_cmd = clish_shell_find_next_completion(this, line, &iter); next_cmd = clish_shell_find_next_completion(this, line, &iter); } else { first_cmd = next_cmd = NULL; } if ((NULL != cmd) && (NULL == next_cmd) && (!first_cmd || (first_cmd == cmd))) { /* we've resolved a particular command */ switch (this->state) { case SHELL_STATE_HELPING: { const char *detail = clish_command__get_detail(cmd); if (NULL != detail) fprintf(stderr, "%s\n", detail); else clish_command_help(cmd, this->viewid, line); break; } case SHELL_STATE_READY: case SHELL_STATE_SCRIPT_ERROR: case SHELL_STATE_SYNTAX_ERROR: /* get the command to provide help */ clish_command_help(cmd, this->viewid, line); break; default: /* do nothing */ break; } } else { /* dump the available commands */ available_commands(this, line, BOOL_FALSE); } /* update the state */ if (this->state == SHELL_STATE_HELPING) { this->state = SHELL_STATE_READY; } else { this->state = SHELL_STATE_HELPING; } } /*--------------------------------------------------------- */