nspace.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * nspace.c
  3. *
  4. * This file provides the implementation of the "nspace" class
  5. */
  6. #include "private.h"
  7. #include "lub/string.h"
  8. #include <assert.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. /*---------------------------------------------------------
  13. * PRIVATE METHODS
  14. *--------------------------------------------------------- */
  15. static void clish_nspace_init(clish_nspace_t * this, clish_view_t * view)
  16. {
  17. this->view = view;
  18. /* set up defaults */
  19. this->prefix = NULL;
  20. this->help = BOOL_FALSE;
  21. this->completion = BOOL_TRUE;
  22. this->context_help = BOOL_FALSE;
  23. this->inherit = BOOL_TRUE;
  24. /* initialise the tree of commands links for this nspace */
  25. lub_bintree_init(&this->tree,
  26. clish_command_bt_offset(),
  27. clish_command_bt_compare, clish_command_bt_getkey);
  28. }
  29. /*--------------------------------------------------------- */
  30. static void clish_nspace_fini(clish_nspace_t * this)
  31. {
  32. clish_command_t *cmd;
  33. /* deallocate the memory for this instance */
  34. lub_string_free(this->prefix);
  35. this->prefix = NULL;
  36. /* delete each command link held by this nspace */
  37. while ((cmd = lub_bintree_findfirst(&this->tree))) {
  38. /* remove the command from the tree */
  39. lub_bintree_remove(&this->tree, cmd);
  40. /* release the instance */
  41. clish_command_delete(cmd);
  42. }
  43. }
  44. /*--------------------------------------------------------- */
  45. static clish_command_t *clish_nspace_find_create_command(clish_nspace_t * this,
  46. const char *prefix,
  47. const clish_command_t *
  48. ref)
  49. {
  50. clish_command_t *cmd;
  51. char *name = NULL;
  52. assert(prefix);
  53. lub_string_catn(&name, prefix, strlen(prefix));
  54. lub_string_catn(&name, " ", 1);
  55. lub_string_catn(&name, clish_command__get_name(ref),
  56. strlen(clish_command__get_name(ref)));
  57. /* The command is cached already */
  58. if (cmd = lub_bintree_find(&this->tree, name)) {
  59. free(name);
  60. return cmd;
  61. }
  62. cmd = clish_command_new_link(name, ref);
  63. free(name);
  64. assert(cmd);
  65. /* Insert command link into the tree */
  66. if (-1 == lub_bintree_insert(&this->tree, cmd)) {
  67. clish_command_delete(cmd);
  68. cmd = NULL;
  69. }
  70. return cmd;
  71. }
  72. /*---------------------------------------------------------
  73. * PUBLIC META FUNCTIONS
  74. *--------------------------------------------------------- */
  75. clish_nspace_t *clish_nspace_new(clish_view_t * view)
  76. {
  77. clish_nspace_t *this = malloc(sizeof(clish_nspace_t));
  78. if (this) {
  79. clish_nspace_init(this, view);
  80. }
  81. return this;
  82. }
  83. /*---------------------------------------------------------
  84. * PUBLIC METHODS
  85. *--------------------------------------------------------- */
  86. void clish_nspace_delete(clish_nspace_t * this)
  87. {
  88. clish_nspace_fini(this);
  89. free(this);
  90. }
  91. /*--------------------------------------------------------- */
  92. static const char *clish_nspace_after_prefix(const char *prefix,
  93. const char *line)
  94. {
  95. const char *in_line = NULL;
  96. if (!line)
  97. return NULL;
  98. /* If entered line contain nspace prefix */
  99. if (lub_string_nocasestr(line, prefix) != line)
  100. return NULL;
  101. /* If entered line contain only the prefix */
  102. if (!lub_string_nocasecmp(line, prefix))
  103. return NULL;
  104. /* If prefix is not followed by space */
  105. in_line = line + strlen(prefix);
  106. if (in_line[0] != ' ')
  107. return NULL;
  108. return (in_line + 1);
  109. }
  110. /*--------------------------------------------------------- */
  111. clish_command_t *clish_nspace_find_command(clish_nspace_t * this, const char *name)
  112. {
  113. clish_command_t *cmd = NULL, *cmd_link = NULL;
  114. clish_view_t *view = clish_nspace__get_view(this);
  115. const char *prefix = clish_nspace__get_prefix(this);
  116. const char *in_line;
  117. if (!prefix)
  118. return clish_view_find_command(view, name, this->inherit);
  119. if (!(in_line = clish_nspace_after_prefix(prefix, name)))
  120. return NULL;
  121. cmd = clish_view_find_command(view, in_line, this->inherit);
  122. if (!cmd)
  123. return NULL;
  124. return clish_nspace_find_create_command(this, prefix, cmd);
  125. }
  126. /*--------------------------------------------------------- */
  127. const clish_command_t *clish_nspace_find_next_completion(clish_nspace_t * this,
  128. const char *iter_cmd, const char *line, clish_nspace_visibility_t field)
  129. {
  130. const clish_command_t *cmd = NULL, *cmd_link = NULL;
  131. clish_view_t *view = clish_nspace__get_view(this);
  132. const char *prefix = clish_nspace__get_prefix(this);
  133. const char *in_iter = "";
  134. const char *in_line;
  135. if (!prefix)
  136. return clish_view_find_next_completion(view, iter_cmd, line, field, this->inherit);
  137. if (!(in_line = clish_nspace_after_prefix(prefix, line)))
  138. return NULL;
  139. if (iter_cmd &&
  140. (lub_string_nocasestr(iter_cmd, prefix) == iter_cmd) &&
  141. (lub_string_nocasecmp(iter_cmd, prefix)))
  142. in_iter = iter_cmd + strlen(prefix) + 1;
  143. cmd = clish_view_find_next_completion(view, in_iter, in_line, field, this->inherit);
  144. if (!cmd)
  145. return NULL;
  146. return clish_nspace_find_create_command(this, prefix, cmd);
  147. }
  148. /*---------------------------------------------------------
  149. * PUBLIC ATTRIBUTES
  150. *--------------------------------------------------------- */
  151. clish_view_t *clish_nspace__get_view(const clish_nspace_t * this)
  152. {
  153. return this->view;
  154. }
  155. /*--------------------------------------------------------- */
  156. void clish_nspace__set_prefix(clish_nspace_t * this, const char *prefix)
  157. {
  158. assert(NULL == this->prefix);
  159. this->prefix = lub_string_dup(prefix);
  160. }
  161. /*--------------------------------------------------------- */
  162. const char *clish_nspace__get_prefix(const clish_nspace_t * this)
  163. {
  164. return this->prefix;
  165. }
  166. /*--------------------------------------------------------- */
  167. void clish_nspace__set_help(clish_nspace_t * this, bool_t help)
  168. {
  169. this->help = help;
  170. }
  171. /*--------------------------------------------------------- */
  172. bool_t clish_nspace__get_help(const clish_nspace_t * this)
  173. {
  174. return this->help;
  175. }
  176. /*--------------------------------------------------------- */
  177. void clish_nspace__set_completion(clish_nspace_t * this, bool_t completion)
  178. {
  179. this->completion = completion;
  180. }
  181. /*--------------------------------------------------------- */
  182. bool_t clish_nspace__get_completion(const clish_nspace_t * this)
  183. {
  184. return this->completion;
  185. }
  186. /*--------------------------------------------------------- */
  187. void clish_nspace__set_context_help(clish_nspace_t * this, bool_t context_help)
  188. {
  189. this->context_help = context_help;
  190. }
  191. /*--------------------------------------------------------- */
  192. bool_t clish_nspace__get_context_help(const clish_nspace_t * this)
  193. {
  194. return this->context_help;
  195. }
  196. /*--------------------------------------------------------- */
  197. void clish_nspace__set_inherit(clish_nspace_t * this, bool_t inherit)
  198. {
  199. this->inherit = inherit;
  200. }
  201. /*--------------------------------------------------------- */
  202. bool_t clish_nspace__get_inherit(const clish_nspace_t * this)
  203. {
  204. return this->inherit;
  205. }
  206. /*--------------------------------------------------------- */
  207. bool_t
  208. clish_nspace__get_visibility(const clish_nspace_t * instance,
  209. clish_nspace_visibility_t field)
  210. {
  211. bool_t result = BOOL_FALSE;
  212. switch (field) {
  213. case CLISH_NSPACE_HELP:
  214. result = clish_nspace__get_help(instance);
  215. break;
  216. case CLISH_NSPACE_COMPLETION:
  217. result = clish_nspace__get_completion(instance);
  218. break;
  219. case CLISH_NSPACE_CHELP:
  220. result = clish_nspace__get_context_help(instance);
  221. break;
  222. }
  223. return result;
  224. }
  225. /*--------------------------------------------------------- */