mirror of https://github.com/sipwise/klish.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.3 KiB
169 lines
4.3 KiB
/*
|
|
* 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_string_wordcount(line);
|
|
unsigned idx = lub_string_wordcount(clish_command__get_name(cmd));
|
|
lub_argv_t *argv;
|
|
clish_pargv_t *completion, *pargv;
|
|
unsigned i;
|
|
unsigned cnt = 0;
|
|
clish_pargv_status_e 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 */
|
|
clish_context_init(&context, this);
|
|
clish_context__set_cmd(&context, cmd);
|
|
clish_context__set_pargv(&context, 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;
|
|
unsigned 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);
|
|
}
|
|
|
|
/*--------------------------------------------------------- */
|