shell_command.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /*
  2. * shell_word_generator.c
  3. */
  4. #include <string.h>
  5. #include "private.h"
  6. #include "lub/string.h"
  7. #include "lub/argv.h"
  8. /*-------------------------------------------------------- */
  9. void clish_shell_iterator_init(clish_shell_iterator_t * iter,
  10. clish_nspace_visibility_e field)
  11. {
  12. iter->last_cmd = NULL;
  13. iter->field = field;
  14. }
  15. /*--------------------------------------------------------- */
  16. const clish_command_t *clish_shell_resolve_command(const clish_shell_t * this,
  17. const char *line)
  18. {
  19. clish_command_t *cmd, *result;
  20. /* Search the current view */
  21. result = clish_view_resolve_command(clish_shell__get_view(this), line);
  22. /* Search the global view */
  23. cmd = clish_view_resolve_command(this->global, line);
  24. result = clish_command_choose_longest(result, cmd);
  25. return result;
  26. }
  27. /*-------------------------------------------------------- */
  28. const clish_command_t *clish_shell_find_next_completion(const clish_shell_t *
  29. this, const char *line, clish_shell_iterator_t * iter)
  30. {
  31. const clish_command_t *result, *cmd;
  32. /* ask the local view for next command */
  33. result = clish_view_find_next_completion(clish_shell__get_view(this),
  34. iter->last_cmd, line, iter->field, BOOL_TRUE);
  35. /* ask the global view for next command */
  36. cmd = clish_view_find_next_completion(this->global,
  37. iter->last_cmd, line, iter->field, BOOL_TRUE);
  38. if (clish_command_diff(result, cmd) > 0)
  39. result = cmd;
  40. if (!result)
  41. iter->last_cmd = NULL;
  42. else
  43. iter->last_cmd = clish_command__get_name(result);
  44. return result;
  45. }
  46. /*--------------------------------------------------------- */
  47. void clish_shell_param_generator(clish_shell_t *this, lub_argv_t *matches,
  48. const clish_command_t *cmd, const char *line, unsigned offset)
  49. {
  50. const char *name = clish_command__get_name(cmd);
  51. char *text = lub_string_dup(&line[offset]);
  52. clish_ptype_t *ptype;
  53. unsigned idx = lub_string_wordcount(name);
  54. /* get the index of the current parameter */
  55. unsigned index = lub_string_wordcount(line) - idx;
  56. clish_context_t context;
  57. if ((0 != index) || (offset && line[offset - 1] == ' ')) {
  58. lub_argv_t *argv = lub_argv_new(line, 0);
  59. clish_pargv_t *pargv = clish_pargv_new();
  60. clish_pargv_t *completion = clish_pargv_new();
  61. unsigned completion_index = 0;
  62. const clish_param_t *param = NULL;
  63. /* if there is some text for the parameter then adjust the index */
  64. if ((0 != index) && (text[0] != '\0'))
  65. index--;
  66. /* Parse command line to get completion pargv's */
  67. /* Prepare context */
  68. clish_context_init(&context, this);
  69. clish_context__set_cmd(&context, cmd);
  70. clish_context__set_pargv(&context, pargv);
  71. clish_shell_parse_pargv(pargv, cmd, &context,
  72. clish_command__get_paramv(cmd),
  73. argv, &idx, completion, index + idx);
  74. lub_argv_delete(argv);
  75. while ((param = clish_pargv__get_param(completion,
  76. completion_index++))) {
  77. const char *result;
  78. /* The param is args so it has no completion */
  79. if (param == clish_command__get_args(cmd))
  80. continue;
  81. /* The switch has no completion string */
  82. if (CLISH_PARAM_SWITCH == clish_param__get_mode(param))
  83. continue;
  84. /* The subcommand is identified by it's value */
  85. if (CLISH_PARAM_SUBCOMMAND ==
  86. clish_param__get_mode(param)) {
  87. result = clish_param__get_value(param);
  88. if (result)
  89. lub_argv_add(matches, result);
  90. }
  91. /* The 'completion' field of PARAM */
  92. if (clish_param__get_completion(param)) {
  93. char *str, *q;
  94. char *saveptr = NULL;
  95. str = clish_shell_expand(
  96. clish_param__get_completion(param), SHELL_VAR_ACTION, &context);
  97. if (str) {
  98. for (q = strtok_r(str, " \n", &saveptr);
  99. q; q = strtok_r(NULL, " \n", &saveptr)) {
  100. if (q == strstr(q, text))
  101. lub_argv_add(matches, q);
  102. }
  103. lub_string_free(str);
  104. }
  105. }
  106. /* The common PARAM. Let ptype do the work */
  107. if ((ptype = clish_param__get_ptype(param)))
  108. clish_ptype_word_generator(ptype, matches, text);
  109. }
  110. clish_pargv_delete(completion);
  111. clish_pargv_delete(pargv);
  112. }
  113. lub_string_free(text);
  114. }
  115. /*--------------------------------------------------------- */