[njs] Fixed autocompletion for global objects.
Dmitry Volyntsev
xeioex at nginx.com
Mon Jul 2 13:32:17 UTC 2018
details: http://hg.nginx.org/njs/rev/f2a2c9674082
branches:
changeset: 546:f2a2c9674082
user: Dmitry Volyntsev <xeioex at 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;
More information about the nginx-devel
mailing list