X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fecoli_completed.c;h=bdada2adcb194a9a366f661e1bee2b22600d69e7;hb=9ea36377cc6557fd9d40d02f45fd02a0c7dec877;hp=68209712b4f4db01fb20404cb630d34ef8bffb72;hpb=450515ddeece572a2d58509a01f3e27c0fb75bb2;p=protos%2Flibecoli.git diff --git a/lib/ecoli_completed.c b/lib/ecoli_completed.c index 6820971..bdada2a 100644 --- a/lib/ecoli_completed.c +++ b/lib/ecoli_completed.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -44,12 +45,14 @@ struct ec_completed_item { enum ec_completed_type type; const struct ec_node *node; struct ec_completed_group *grp; - char *str; - char *display; + char *start; /* the initial token */ + char *full; /* the full token after completion */ + char *completion; /* chars that are added, NULL if not applicable */ + char *display; /* what should be displayed by help/completers */ struct ec_keyval *attrs; }; -struct ec_completed *ec_completed(void) +struct ec_completed *ec_completed(struct ec_parsed *state) { struct ec_completed *completed = NULL; @@ -57,13 +60,13 @@ struct ec_completed *ec_completed(void) if (completed == NULL) goto fail; - TAILQ_INIT(&completed->groups); - completed->attrs = ec_keyval(); if (completed->attrs == NULL) goto fail; - completed->cur_state = NULL; + TAILQ_INIT(&completed->groups); + + completed->cur_state = state; return completed; @@ -75,46 +78,36 @@ struct ec_completed *ec_completed(void) return NULL; } -struct ec_parsed *ec_completed_cur_parse_state(struct ec_completed *completed) +struct ec_parsed *ec_completed_get_state(struct ec_completed *completed) { return completed->cur_state; } int -ec_node_complete_child(struct ec_node *node, struct ec_completed *completed, - const struct ec_strvec *strvec) +ec_node_complete_child(const struct ec_node *node, + struct ec_completed *completed, + const struct ec_strvec *strvec) { struct ec_parsed *child_state, *cur_state; struct ec_completed_group *cur_group; int ret; - /* build the node if required */ - if (node->type->build != NULL) { - if ((node->flags & EC_NODE_F_BUILT) == 0) { - ret = node->type->build(node); - if (ret < 0) - return ret; - } - } - node->flags |= EC_NODE_F_BUILT; - if (node->type->complete == NULL) return -ENOTSUP; /* save previous parse state, prepare child state */ cur_state = completed->cur_state; - child_state = ec_parsed(); + child_state = ec_parsed(node); if (child_state == NULL) return -ENOMEM; if (cur_state != NULL) ec_parsed_add_child(cur_state, child_state); - ec_parsed_set_node(child_state, node); completed->cur_state = child_state; cur_group = completed->cur_group; completed->cur_group = NULL; - /* complete */ + /* fill the completed struct with items */ ret = node->type->complete(node, completed, strvec); /* restore parent parse state */ @@ -129,23 +122,16 @@ ec_node_complete_child(struct ec_node *node, struct ec_completed *completed, if (ret < 0) return ret; -#if 0 // XXX dump - printf("----------------------------------------------------------\n"); - ec_node_dump(stdout, node); - ec_strvec_dump(stdout, strvec); - ec_completed_dump(stdout, completed); -#endif - return 0; } -struct ec_completed *ec_node_complete_strvec(struct ec_node *node, +struct ec_completed *ec_node_complete_strvec(const struct ec_node *node, const struct ec_strvec *strvec) { struct ec_completed *completed = NULL; int ret; - completed = ec_completed(); + completed = ec_completed(NULL); if (completed == NULL) goto fail; @@ -160,7 +146,7 @@ fail: return NULL; } -struct ec_completed *ec_node_complete(struct ec_node *node, +struct ec_completed *ec_node_complete(const struct ec_node *node, const char *str) { struct ec_strvec *strvec = NULL; @@ -195,6 +181,10 @@ ec_completed_group(const struct ec_node *node, struct ec_parsed *parsed) if (grp == NULL) return NULL; + grp->attrs = ec_keyval(); + if (grp->attrs == NULL) + goto fail; + grp->state = ec_parsed_dup(parsed); if (grp->state == NULL) goto fail; @@ -205,116 +195,158 @@ ec_completed_group(const struct ec_node *node, struct ec_parsed *parsed) return grp; fail: - if (grp != NULL) + if (grp != NULL) { ec_parsed_free(grp->state); + ec_keyval_free(grp->attrs); + } ec_free(grp); return NULL; } -struct ec_completed_item * -ec_completed_item(const struct ec_node *node) +static struct ec_completed_item * +ec_completed_item(const struct ec_node *node, enum ec_completed_type type, + const char *start, const char *full) { struct ec_completed_item *item = NULL; + struct ec_keyval *attrs = NULL; + char *comp_cp = NULL, *start_cp = NULL; + char *full_cp = NULL, *display_cp = NULL; + + if (type == EC_COMP_UNKNOWN && full != NULL) { + errno = EINVAL; + return NULL; + } + if (type != EC_COMP_UNKNOWN && full == NULL) { + errno = EINVAL; + return NULL; + } item = ec_calloc(1, sizeof(*item)); if (item == NULL) goto fail; - item->attrs = ec_keyval(); - if (item->attrs == NULL) + attrs = ec_keyval(); + if (attrs == NULL) goto fail; - item->type = EC_COMP_UNKNOWN; + if (start != NULL) { + start_cp = ec_strdup(start); + if (start_cp == NULL) + goto fail; + + if (ec_str_startswith(full, start)) { + comp_cp = ec_strdup(&full[strlen(start)]); + if (comp_cp == NULL) + goto fail; + } + } + if (full != NULL) { + full_cp = ec_strdup(full); + if (full_cp == NULL) + goto fail; + display_cp = ec_strdup(full); + if (display_cp == NULL) + goto fail; + } + item->node = node; + item->type = type; + item->start = start_cp; + item->full = full_cp; + item->completion = comp_cp; + item->display = display_cp; + item->attrs = attrs; return item; fail: - if (item != NULL) { - ec_free(item->str); - ec_free(item->display); - ec_keyval_free(item->attrs); - } + ec_keyval_free(attrs); + ec_free(comp_cp); + ec_free(start_cp); + ec_free(full_cp); + ec_free(display_cp); ec_free(item); return NULL; } -int -ec_completed_item_set(struct ec_completed_item *item, - enum ec_completed_type type, const char *str) +int ec_completed_item_set_display(struct ec_completed_item *item, + const char *display) { - char *str_copy = NULL; char *display_copy = NULL; int ret = 0; - if (item == NULL) - return -EINVAL; - if (item->str != NULL) - return -EEXIST; - - switch (type) { - case EC_COMP_UNKNOWN: - if (str != NULL) - return -EINVAL; - break; - case EC_COMP_FULL: - case EC_PARTIAL_MATCH: - if (str == NULL) - return -EINVAL; - break; - default: + if (item == NULL || display == NULL || + item->type == EC_COMP_UNKNOWN) return -EINVAL; - } - if (str != NULL) { - ret = -ENOMEM; - str_copy = ec_strdup(str); - if (str_copy == NULL) - goto fail; - display_copy = ec_strdup(str); - if (display_copy == NULL) - goto fail; - } + display_copy = ec_strdup(display); + if (display_copy == NULL) + goto fail; - item->type = type; - item->str = str_copy; + ec_free(item->display); item->display = display_copy; + return 0; fail: - ec_free(str_copy); ec_free(display_copy); return ret; } -int ec_completed_item_set_display(struct ec_completed_item *item, - const char *display) +int +ec_completed_item_set_completion(struct ec_completed_item *item, + const char *completion) { - char *display_copy = NULL; + char *completion_copy = NULL; int ret = 0; - if (item == NULL || display == NULL || - item->type == EC_COMP_UNKNOWN || item->str == NULL) + if (item == NULL || completion == NULL || + item->type == EC_COMP_UNKNOWN) return -EINVAL; ret = -ENOMEM; - display_copy = ec_strdup(display); - if (display_copy == NULL) + completion_copy = ec_strdup(completion); + if (completion_copy == NULL) goto fail; - ec_free(item->display); - item->display = display_copy; + ec_free(item->completion); + item->completion = completion_copy; return 0; fail: - ec_free(display_copy); + ec_free(completion_copy); return ret; } -// XXX refactor ec_completed_item(), ec_completed_item_add(), ec_completed_item_set* int +ec_completed_item_set_str(struct ec_completed_item *item, + const char *str) +{ + char *str_copy = NULL; + int ret = 0; + + if (item == NULL || str == NULL || + item->type == EC_COMP_UNKNOWN) + return -EINVAL; + + ret = -ENOMEM; + str_copy = ec_strdup(str); + if (str_copy == NULL) + goto fail; + + ec_free(item->full); + item->full = str_copy; + + return 0; + +fail: + ec_free(str_copy); + return ret; +} + +static int ec_completed_item_add(struct ec_completed *completed, struct ec_completed_item *item) { @@ -323,10 +355,13 @@ ec_completed_item_add(struct ec_completed *completed, switch (item->type) { case EC_COMP_UNKNOWN: + completed->count_unknown++; break; case EC_COMP_FULL: - case EC_PARTIAL_MATCH: - completed->count_match++; //XXX + completed->count_full++; + break; + case EC_COMP_PARTIAL: + completed->count_partial++; break; default: return -EINVAL; @@ -352,7 +387,7 @@ ec_completed_item_add(struct ec_completed *completed, const char * ec_completed_item_get_str(const struct ec_completed_item *item) { - return item->str; + return item->full; } const char * @@ -361,6 +396,12 @@ ec_completed_item_get_display(const struct ec_completed_item *item) return item->display; } +const char * +ec_completed_item_get_completion(const struct ec_completed_item *item) +{ + return item->completion; +} + enum ec_completed_type ec_completed_item_get_type(const struct ec_completed_item *item) { @@ -379,42 +420,63 @@ ec_completed_item_get_grp(const struct ec_completed_item *item) return item->grp; } -void ec_completed_item_free(struct ec_completed_item *item) +static void +ec_completed_item_free(struct ec_completed_item *item) { if (item == NULL) return; - ec_free(item->str); + ec_free(item->full); + ec_free(item->start); + ec_free(item->completion); ec_free(item->display); ec_keyval_free(item->attrs); ec_free(item); } +int ec_completed_add_item(struct ec_completed *completed, + const struct ec_node *node, + struct ec_completed_item **p_item, + enum ec_completed_type type, + const char *start, const char *full) +{ + struct ec_completed_item *item = NULL; + int ret; + + item = ec_completed_item(node, type, start, full); + if (item == NULL) + return -1; + + ret = ec_completed_item_add(completed, item); + if (ret < 0) + goto fail; + + if (p_item != NULL) + *p_item = item; + + return 0; + +fail: + ec_completed_item_free(item); + + return -1; +} + /* default completion function: return a no-match element */ int ec_node_default_complete(const struct ec_node *gen_node, // XXX rename in nomatch struct ec_completed *completed, const struct ec_strvec *strvec) { - struct ec_completed_item *item = NULL; int ret; if (ec_strvec_len(strvec) != 1) return 0; - item = ec_completed_item(gen_node); - if (item == NULL) - return -ENOMEM; - ret = ec_completed_item_set(item, EC_COMP_UNKNOWN, NULL); - if (ret < 0) { - ec_completed_item_free(item); - return ret; - } - ret = ec_completed_item_add(completed, item); - if (ret < 0) { - ec_completed_item_free(item); + ret = ec_completed_add_item(completed, gen_node, NULL, + EC_COMP_UNKNOWN, NULL, NULL); + if (ret < 0) return ret; - } return 0; } @@ -432,6 +494,7 @@ static void ec_completed_group_free(struct ec_completed_group *grp) ec_completed_item_free(item); } ec_parsed_free(ec_parsed_get_root(grp->state)); + ec_keyval_free(grp->attrs); ec_free(grp); } @@ -461,8 +524,9 @@ void ec_completed_dump(FILE *out, const struct ec_completed *completed) return; } - fprintf(out, "completion: count=%u match=%u\n", - completed->count, completed->count_match); + fprintf(out, "completion: count=%u full=%u partial=%u unknown=%u\n", + completed->count, completed->count_full, + completed->count_partial, completed->count_unknown); TAILQ_FOREACH(grp, &completed->groups, next) { fprintf(out, "node=%p, node_type=%s\n", @@ -471,18 +535,38 @@ void ec_completed_dump(FILE *out, const struct ec_completed *completed) const char *typestr; switch (item->type) { - case EC_COMP_UNKNOWN: typestr = "no-match"; break; - case EC_COMP_FULL: typestr = "match"; break; - case EC_PARTIAL_MATCH: typestr = "partial-match"; break; + case EC_COMP_UNKNOWN: typestr = "unknown"; break; + case EC_COMP_FULL: typestr = "full"; break; + case EC_COMP_PARTIAL: typestr = "partial"; break; default: typestr = "unknown"; break; } - fprintf(out, " type=%s str=<%s> disp=<%s>\n", - typestr, item->str, item->display); + fprintf(out, " type=%s str=<%s> comp=<%s> disp=<%s>\n", + typestr, item->full, item->completion, + item->display); } } } +int ec_completed_merge(struct ec_completed *to, + struct ec_completed *from) +{ + struct ec_completed_group *grp; + + while (!TAILQ_EMPTY(&from->groups)) { + grp = TAILQ_FIRST(&from->groups); + TAILQ_REMOVE(&from->groups, grp, next); + TAILQ_INSERT_TAIL(&to->groups, grp, next); + } + to->count += from->count; + to->count_full += from->count_full; + to->count_partial += from->count_partial; + to->count_unknown += from->count_unknown; + + ec_completed_free(from); + return 0; +} + unsigned int ec_completed_count( const struct ec_completed *completed, enum ec_completed_type type) @@ -493,9 +577,11 @@ unsigned int ec_completed_count( return count; if (type & EC_COMP_FULL) - count += completed->count_match; + count += completed->count_full; + if (type & EC_COMP_PARTIAL) + count += completed->count_partial; if (type & EC_COMP_UNKNOWN) - count += (completed->count - completed->count_match); //XXX + count += completed->count_unknown; return count; } @@ -518,13 +604,16 @@ ec_completed_iter(struct ec_completed *completed, return iter; } -const struct ec_completed_item *ec_completed_iter_next( +struct ec_completed_item *ec_completed_iter_next( struct ec_completed_iter *iter) { - const struct ec_completed *completed = iter->completed; - const struct ec_completed_group *cur_node; - const struct ec_completed_item *cur_match; + struct ec_completed *completed; + struct ec_completed_group *cur_node; + struct ec_completed_item *cur_match; + if (iter == NULL) + return NULL; + completed = iter->completed; if (completed == NULL) return NULL;