details: http://hg.nginx.org/njs/rev/f2a2c9674082 branches: changeset: 546:f2a2c9674082 user: Dmitry Volyntsev <xei...@nginx.com> date: Mon Jul 02 16:10:52 2018 +0300 description: Fixed autocompletion for global objects.
This fixes #23 issue on GitHub. diffstat: njs/njs_shell.c | 186 +++++++++++++++++++++++++++++++------------------------ 1 files changed, 104 insertions(+), 82 deletions(-) diffs (227 lines): diff -r e210675daceb -r f2a2c9674082 njs/njs_shell.c --- a/njs/njs_shell.c Sun Jul 01 10:01:53 2018 +0300 +++ b/njs/njs_shell.c Mon Jul 02 16:10:52 2018 +0300 @@ -20,8 +20,9 @@ typedef enum { - NJS_COMPLETION_GLOBAL = 0, + NJS_COMPLETION_VAR = 0, NJS_COMPLETION_SUFFIX, + NJS_COMPLETION_GLOBAL } njs_completion_phase_t; @@ -476,6 +477,11 @@ njs_completion_handler(const char *text, #define njs_completion(c, i) &(((nxt_str_t *) (c)->start)[i]) +#define njs_next_phase(c) \ + (c)->index = 0; \ + (c)->phase++; \ + goto next; + static char * njs_completion_generator(const char *text, int state) { @@ -489,14 +495,108 @@ njs_completion_generator(const char *tex cmpl = &njs_completion; if (state == 0) { + cmpl->phase = 0; cmpl->index = 0; cmpl->length = strlen(text); - cmpl->phase = NJS_COMPLETION_GLOBAL; + cmpl->suffix_completions = NULL; nxt_lvlhsh_each_init(&cmpl->lhe, &njs_variables_hash_proto); } - if (cmpl->phase == NJS_COMPLETION_GLOBAL) { +next: + + switch (cmpl->phase) { + case NJS_COMPLETION_VAR: + if (cmpl->vm->parser == NULL) { + njs_next_phase(cmpl); + } + + for ( ;; ) { + var = nxt_lvlhsh_each(&cmpl->vm->parser->scope->variables, + &cmpl->lhe); + + if (var == NULL) { + break; + } + + if (var->name.length < cmpl->length) { + continue; + } + + if (strncmp(text, (char *) var->name.start, cmpl->length) == 0) { + return njs_editline(&var->name); + } + } + + njs_next_phase(cmpl); + + case NJS_COMPLETION_SUFFIX: + if (cmpl->length == 0) { + njs_next_phase(cmpl); + } + + if (cmpl->suffix_completions == NULL) { + /* Getting the longest prefix before a '.' */ + + p = &text[cmpl->length - 1]; + while (p > text && *p != '.') { p--; } + + if (*p != '.') { + njs_next_phase(cmpl); + } + + expression.start = (u_char *) text; + expression.length = p - text; + + cmpl->suffix_completions = njs_vm_completions(cmpl->vm, + &expression); + if (cmpl->suffix_completions == NULL) { + njs_next_phase(cmpl); + } + } + + /* Getting the right-most suffix after a '.' */ + + len = 0; + p = &text[cmpl->length - 1]; + + while (p > text && *p != '.') { + p--; + len++; + } + + p++; + + for ( ;; ) { + if (cmpl->index >= cmpl->suffix_completions->items) { + njs_next_phase(cmpl); + } + + suffix = njs_completion(cmpl->suffix_completions, cmpl->index++); + + if (len != 0 && strncmp((char *) suffix->start, p, + nxt_min(len, suffix->length)) != 0) + { + continue; + } + + len = suffix->length + (p - text) + 1; + completion = malloc(len); + if (completion == NULL) { + return NULL; + } + + snprintf(completion, len, "%.*s%.*s", (int) (p - text), text, + (int) suffix->length, suffix->start); + return completion; + } + + case NJS_COMPLETION_GLOBAL: + if (cmpl->suffix_completions != NULL) { + /* No global completions if suffixes were found. */ + njs_next_phase(cmpl); + } + for ( ;; ) { if (cmpl->index >= cmpl->completions->items) { break; @@ -508,88 +608,10 @@ njs_completion_generator(const char *tex continue; } - if (strncmp(text, (char *) suffix->start, - nxt_min(suffix->length, cmpl->length)) == 0) - { + if (strncmp(text, (char *) suffix->start, cmpl->length) == 0) { return njs_editline(suffix); } } - - if (cmpl->vm->parser != NULL) { - for ( ;; ) { - var = nxt_lvlhsh_each(&cmpl->vm->parser->scope->variables, - &cmpl->lhe); - if (var == NULL || var->name.length < cmpl->length) { - break; - } - - if (strncmp(text, (char *) var->name.start, - nxt_min(var->name.length, cmpl->length)) == 0) - { - return njs_editline(&var->name); - } - } - } - - if (cmpl->length == 0) { - return NULL; - } - - /* Getting the longest prefix before a '.' */ - - p = &text[cmpl->length - 1]; - while (p > text && *p != '.') { p--; } - - if (*p != '.') { - return NULL; - } - - expression.start = (u_char *) text; - expression.length = p - text; - - cmpl->suffix_completions = njs_vm_completions(cmpl->vm, &expression); - if (cmpl->suffix_completions == NULL) { - return NULL; - } - - cmpl->index = 0; - cmpl->phase = NJS_COMPLETION_SUFFIX; - } - - /* Getting the right-most suffix after a '.' */ - - len = 0; - p = &text[cmpl->length - 1]; - - while (p > text && *p != '.') { - p--; - len++; - } - - p++; - - for ( ;; ) { - if (cmpl->index >= cmpl->suffix_completions->items) { - break; - } - - suffix = njs_completion(cmpl->suffix_completions, cmpl->index++); - - if (len != 0 && strncmp((char *) suffix->start, p, - nxt_min(len, suffix->length)) != 0) - { - continue; - } - - len = suffix->length + (p - text) + 1; - completion = malloc(len); - if (completion == NULL) { - return NULL; - } - - snprintf(completion, len, "%.*s%.*s", (int) (p - text), text, - (int) suffix->length, suffix->start); - return completion; } return NULL; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel