/* * shell_word_generator.c */ #include #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_resolve_command(const clish_shell_t * this, const char *line) { clish_command_t *cmd, *result; /* Search the current view */ result = clish_view_resolve_command(clish_shell__get_view(this), line, BOOL_TRUE); /* Search the global view */ cmd = clish_view_resolve_command(this->global, line, BOOL_TRUE); result = clish_command_choose_longest(result, cmd); return result; } /*--------------------------------------------------------- */ const clish_command_t *clish_shell_resolve_prefix(const clish_shell_t * this, const char *line) { clish_command_t *cmd, *result; /* Search the current view */ result = clish_view_resolve_prefix(clish_shell__get_view(this), line, BOOL_TRUE); /* Search the global view */ cmd = clish_view_resolve_prefix(this->global, line, BOOL_TRUE); result = clish_command_choose_longest(result, cmd); return result; } /*-------------------------------------------------------- */ 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; /* ask the local view for next command */ result = clish_view_find_next_completion(clish_shell__get_view(this), 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; } /*--------------------------------------------------------- */ void clish_shell_param_generator(clish_shell_t *this, lub_argv_t *matches, const clish_command_t *cmd, const char *line, unsigned offset) { const char *name = clish_command__get_name(cmd); char *text = lub_string_dup(&line[offset]); clish_ptype_t *ptype; unsigned idx = lub_argv_wordcount(name); /* get the index of the current parameter */ unsigned index = lub_argv_wordcount(line) - idx; clish_context_t context; if ((0 != index) || (offset && line[offset - 1] == ' ')) { lub_argv_t *argv = lub_argv_new(line, 0); clish_pargv_t *pargv = clish_pargv_new(); clish_pargv_t *completion = clish_pargv_new(); unsigned completion_index = 0; const clish_param_t *param = NULL; /* if there is some text for the parameter then adjust the index */ if ((0 != index) && (text[0] != '\0')) index--; /* Parse command line to get completion pargv's */ context.shell = this; context.cmd = cmd; context.pargv = pargv; clish_shell_parse_pargv(pargv, cmd, &context, clish_command__get_paramv(cmd), argv, &idx, completion, index + idx); lub_argv_delete(argv); while ((param = clish_pargv__get_param(completion, completion_index++))) { char *result; /* The param is args so it has no completion */ if (param == clish_command__get_args(cmd)) continue; /* The switch has no completion string */ if (CLISH_PARAM_SWITCH == clish_param__get_mode(param)) continue; /* The subcommand is identified by it's value */ if (CLISH_PARAM_SUBCOMMAND == clish_param__get_mode(param)) { result = clish_param__get_value(param); if (result) lub_argv_add(matches, result); } /* The 'completion' field of PARAM */ if (clish_param__get_completion(param)) { char *str, *q; char *saveptr; str = clish_shell_expand( clish_param__get_completion(param), SHELL_VAR_ACTION, &context); if (str) { for (q = strtok_r(str, " \n", &saveptr); q; q = strtok_r(NULL, " \n", &saveptr)) { if (q == strstr(q, text)) lub_argv_add(matches, q); } lub_string_free(str); } } /* The common PARAM. Let ptype do the work */ if ((ptype = clish_param__get_ptype(param))) clish_ptype_word_generator(ptype, matches, text); } clish_pargv_delete(completion); clish_pargv_delete(pargv); } lub_string_free(text); } /*--------------------------------------------------------- */