123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- * shell_word_generator.c
- */
- #include <string.h>
- #include "private.h"
- #include "lub/string.h"
- #include "lub/argv.h"
- /*-------------------------------------------------------- */
- void
- clish_shell_iterator_init(clish_shell_iterator_t * iter,
- clish_nspace_visibility_t field)
- {
- iter->last_cmd = NULL;
- iter->field = field;
- }
- /*-------------------------------------------------------- */
- const clish_command_t *clish_shell_find_next_completion(const clish_shell_t *
- this, const char *line,
- clish_shell_iterator_t *
- iter)
- {
- const clish_command_t *result, *cmd;
- clish_nspace_t *nspace;
- clish_view_t *view;
- unsigned view_cnt = clish_view__get_nspace_count(this->view);
- int i;
- /* ask the local view for next command */
- result = clish_view_find_next_completion(this->view,
- iter->last_cmd, line, iter->field, BOOL_TRUE);
- /* ask the global view for next command */
- cmd = clish_view_find_next_completion(this->global,
- iter->last_cmd, line, iter->field, BOOL_TRUE);
- if (clish_command_diff(result, cmd) > 0)
- result = cmd;
- if (!result)
- iter->last_cmd = NULL;
- else
- iter->last_cmd = clish_command__get_name(result);
- return result;
- }
- /*--------------------------------------------------------- */
- static char *clish_shell_param_generator(clish_shell_t * this,
- const clish_command_t * cmd,
- const char *line,
- unsigned offset,
- unsigned state)
- {
- char *result = NULL;
- const char *name = clish_command__get_name(cmd);
- char *text = lub_string_dup(&line[offset]);
- unsigned index;
- const clish_param_t *param = NULL;
- clish_ptype_t *ptype;
- unsigned idx;
- /* get the index of the current parameter */
- index = lub_argv_wordcount(line) - lub_argv_wordcount(name);
- if ((0 != index) || (line[offset - 1] == ' ')) {
- if (0 == state) {
- lub_argv_t *argv;
- clish_pargv_t *pargv;
- unsigned i;
-
- if ((0 != index) && (text[0] != '\0')) {
- /* if there is some text for the parameter then adjust the index */
- index--;
- }
- argv = lub_argv_new(line, 0);
- idx = lub_argv_wordcount(name);
- if (this->context.completion_pargv) {
- clish_pargv_delete(this->context.completion_pargv);
- this->context.completion_pargv = NULL;
- }
- this->context.completion_pargv = clish_pargv_create();
- pargv = clish_pargv_create();
- clish_pargv_parse(pargv, cmd, this->viewid, clish_command__get_paramv(cmd),
- argv, &idx, this->context.completion_pargv, index + idx);
- clish_pargv_delete(pargv);
- lub_argv_delete(argv);
- this->context.completion_index = 0;
- this->context.completion_pindex = 0;
- }
- while ((param = clish_pargv__get_param(this->context.completion_pargv,
- this->context.completion_index++))) {
- if (param == clish_command__get_args(cmd)) {
- /* The param is args so it has no format */
- result = lub_string_dup(text);
- } else if (CLISH_PARAM_SUBCOMMAND ==
- clish_param__get_mode(param)) {
- /* The subcommand is identified by it's value */
- result = lub_string_dup(clish_param__get_value(param));
- } else if (CLISH_PARAM_SWITCH ==
- clish_param__get_mode(param)) {
- /* The switch has no completion string */
- result = NULL;
- } else {
- /* The common param. Let ptype do the work */
- if (ptype = clish_param__get_ptype(param)) {
- result = clish_ptype_word_generator(ptype, text,
- this->context.completion_pindex++);
- if (!result)
- this->context.completion_pindex = 0;
- else
- this->context.completion_index--;
- } else {
- result = NULL;
- }
- }
- if (result)
- break;
- }
- } else if (0 == state) {
- /* simply return the command name */
- result = lub_string_dup(clish_command__get_suffix(cmd));
- }
- if (!result) {
- clish_pargv_delete(this->context.completion_pargv);
- this->context.completion_pargv = NULL;
- /* make sure we reset the line state */
- // tinyrl_crlf(this->tinyrl);
- // tinyrl_reset_line_state(this->tinyrl);
- // tinyrl_completion_error_over(this->tinyrl);
- }
- lub_string_free(text);
- return result;
- }
- /*--------------------------------------------------------- */
- static char *clish_shell_command_generator(clish_shell_t * this,
- const char *line,
- unsigned offset, unsigned state)
- {
- char *result = NULL;
- const clish_command_t *cmd = NULL;
- if (0 == state) {
- cmd =
- clish_shell_getfirst_command(this, line,
- CLISH_NSPACE_COMPLETION);
- } else {
- cmd = clish_shell_getnext_command(this, line);
- }
- if (NULL != cmd) {
- result = lub_string_dup(clish_command__get_suffix(cmd));
- }
- /* keep the compiler happy */
- offset = offset;
- return result;
- }
- /*--------------------------------------------------------- */
- char *clish_shell_word_generator(clish_shell_t * this,
- const char *line,
- unsigned offset, unsigned state)
- {
- char *result = NULL;
- const clish_command_t *cmd, *next = NULL;
- /* try and resolve a command which is a prefix of the line */
- cmd = clish_shell_resolve_command(this, line);
- if (NULL != cmd) {
- clish_shell_iterator_t iter;
- /* see whether there is an extended extension */
- clish_shell_iterator_init(&iter, CLISH_NSPACE_COMPLETION);
- next = clish_shell_find_next_completion(this, line, &iter);
- }
- if ((NULL != cmd) && (NULL == next)) {
- /* this needs to be completed as a parameter */
- result =
- clish_shell_param_generator(this, cmd, line, offset,
- state);
- } else {
- /* this needs to be completed as a command */
- result =
- clish_shell_command_generator(this, line, offset, state);
- }
- if (0 == state) {
- /* reset the state from a help perspective */
- this->state = SHELL_STATE_READY;
- }
- return result;
- }
- /*--------------------------------------------------------- */
|