typedef enum {
- NJS_COMPLETION_GLOBAL = 0,
+ NJS_COMPLETION_VAR = 0,
NJS_COMPLETION_SUFFIX,
+ NJS_COMPLETION_GLOBAL
} njs_completion_phase_t;
#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)
{
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 ( ;; ) {
- if (cmpl->index >= cmpl->completions->items) {
+ var = nxt_lvlhsh_each(&cmpl->vm->parser->scope->variables,
+ &cmpl->lhe);
+
+ if (var == NULL) {
break;
}
- suffix = njs_completion(cmpl->completions, cmpl->index++);
-
- if (suffix->start[0] == '.' || suffix->length < cmpl->length) {
+ if (var->name.length < cmpl->length) {
continue;
}
- if (strncmp(text, (char *) suffix->start,
- nxt_min(suffix->length, cmpl->length)) == 0)
- {
- return njs_editline(suffix);
+ if (strncmp(text, (char *) var->name.start, cmpl->length) == 0) {
+ return njs_editline(&var->name);
}
}
- 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);
- }
- }
- }
+ njs_next_phase(cmpl);
+ case NJS_COMPLETION_SUFFIX:
if (cmpl->length == 0) {
- return NULL;
+ njs_next_phase(cmpl);
}
- /* Getting the longest prefix before a '.' */
+ if (cmpl->suffix_completions == NULL) {
+ /* Getting the longest prefix before a '.' */
- p = &text[cmpl->length - 1];
- while (p > text && *p != '.') { p--; }
+ p = &text[cmpl->length - 1];
+ while (p > text && *p != '.') { p--; }
- if (*p != '.') {
- return NULL;
- }
+ if (*p != '.') {
+ njs_next_phase(cmpl);
+ }
- expression.start = (u_char *) text;
- expression.length = p - text;
+ 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->suffix_completions = njs_vm_completions(cmpl->vm,
+ &expression);
+ if (cmpl->suffix_completions == NULL) {
+ njs_next_phase(cmpl);
+ }
}
- cmpl->index = 0;
- cmpl->phase = NJS_COMPLETION_SUFFIX;
- }
+ /* Getting the right-most suffix after a '.' */
- /* Getting the right-most suffix after a '.' */
+ len = 0;
+ p = &text[cmpl->length - 1];
- len = 0;
- p = &text[cmpl->length - 1];
+ while (p > text && *p != '.') {
+ p--;
+ len++;
+ }
- while (p > text && *p != '.') {
- p--;
- len++;
- }
+ p++;
- p++;
+ for ( ;; ) {
+ if (cmpl->index >= cmpl->suffix_completions->items) {
+ njs_next_phase(cmpl);
+ }
- for ( ;; ) {
- if (cmpl->index >= cmpl->suffix_completions->items) {
- break;
- }
+ suffix = njs_completion(cmpl->suffix_completions, cmpl->index++);
- suffix = njs_completion(cmpl->suffix_completions, cmpl->index++);
+ if (len != 0 && strncmp((char *) suffix->start, p,
+ nxt_min(len, suffix->length)) != 0)
+ {
+ continue;
+ }
- 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;
}
- len = suffix->length + (p - text) + 1;
- completion = malloc(len);
- if (completion == NULL) {
- return NULL;
+ case NJS_COMPLETION_GLOBAL:
+ if (cmpl->suffix_completions != NULL) {
+ /* No global completions if suffixes were found. */
+ njs_next_phase(cmpl);
}
- snprintf(completion, len, "%.*s%.*s", (int) (p - text), text,
- (int) suffix->length, suffix->start);
- return completion;
+ for ( ;; ) {
+ if (cmpl->index >= cmpl->completions->items) {
+ break;
+ }
+
+ suffix = njs_completion(cmpl->completions, cmpl->index++);
+
+ if (suffix->start[0] == '.' || suffix->length < cmpl->length) {
+ continue;
+ }
+
+ if (strncmp(text, (char *) suffix->start, cmpl->length) == 0) {
+ return njs_editline(suffix);
+ }
+ }
}
return NULL;