From: Olivier Matz Date: Sun, 8 May 2011 16:00:54 +0000 (+0200) Subject: genconf: basic support of completion for nodes starting with "//" X-Git-Url: http://git.droids-corp.org/?p=libcmdline.git;a=commitdiff_plain;h=09addaa3b831267407b6f4a51dfaa4597d5da0a6 genconf: basic support of completion for nodes starting with "//" Signed-off-by: Olivier Matz --- diff --git a/src/genconf/parse_confnode.c b/src/genconf/parse_confnode.c index 382bfde..562e688 100644 --- a/src/genconf/parse_confnode.c +++ b/src/genconf/parse_confnode.c @@ -118,6 +118,8 @@ parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, tkd->mask, 1); else { n = conf_htable_lookup(token + 2); + if (n == NULL) + return -1; if ((n->flags & tkd->mask) != tkd->flags) return -1; TAILQ_INSERT_TAIL(&l, n, user_next); @@ -139,15 +141,17 @@ parse_conf_node(cmdline_parse_token_hdr_t *tk, const char *buf, void *res, struct confnode_complete_callback { struct confnode *start; struct confnode *cur; + int xpath; }; static struct confnode *get_next_node(struct confnode *start, struct confnode *cur, unsigned flags, - unsigned mask) + unsigned mask, int xpath) { struct confnode *prev; struct confnode *parent = start; + int descend = 1; while (1) { prev = cur; @@ -159,14 +163,22 @@ static struct confnode *get_next_node(struct confnode *start, /* first iteration */ if (cur == NULL) cur = TAILQ_FIRST(&parent->children); + /* directory in xpath mode */ + else if (xpath && descend && + (cur->flags & CONFNODE_F_IS_DIR) && + (cur->flags & CONFNODE_F_INVISIBLE) == 0) + cur = TAILQ_FIRST(&cur->children); + /* other cases */ else cur = TAILQ_NEXT(cur, next); + descend = 1; /* no next, return to upper level */ if (cur == NULL) { if (prev == NULL) return NULL; /* no node */ cur = prev->parent; + descend = 0; continue; } @@ -177,6 +189,10 @@ static struct confnode *get_next_node(struct confnode *start, continue; } + /* skip other nodes with no name */ + if (cur->flags & CONFNODE_F_NO_NAME) + continue; + /* check that flags match what we want */ if ((cur->flags & mask) != flags) continue; @@ -194,7 +210,7 @@ complete_conf_node_start(cmdline_parse_token_hdr_t *tk, struct token_conf_node *tk2 = (struct token_conf_node *)tk; struct token_conf_node_data *tkd = &tk2->conf_node_data; struct confnode_complete_callback *cb; - struct confnode *n; + struct confnode *n, *start; unsigned flags = tkd->flags; unsigned mask = tkd->mask; @@ -204,11 +220,23 @@ complete_conf_node_start(cmdline_parse_token_hdr_t *tk, return -1; *opaque = cb; - n = get_next_node(*tkd->cur, NULL, flags, mask); - if (n == NULL) - return -1; /* no completion */ + if (strlen(tokstr) >= 2 && tokstr[0] == '/' && tokstr[1] == '/') { + start = *tkd->root; + cb->xpath = 1; + } + else { + start = *tkd->cur; + cb->xpath = 0; + } + + n = get_next_node(start, NULL, flags, mask, cb->xpath); + if (n == NULL) { + /* no completion. + * cb is freed in complete_conf_node_end()*/ + return -1; + } - cb->start = *tkd->cur; + cb->start = start; cb->cur = n; return 0; } @@ -221,21 +249,22 @@ complete_conf_node_iterate(cmdline_parse_token_hdr_t *tk, void **opaque, struct token_conf_node_data *tkd = &tk2->conf_node_data; struct confnode_complete_callback *cb; struct confnode *n; - unsigned len; unsigned flags = tkd->flags; unsigned mask = tkd->mask; + int len; cb = *opaque; n = cb->cur; if (n == NULL) return -1; - cb->cur = get_next_node(cb->start, n, flags, mask); + cb->cur = get_next_node(cb->start, n, flags, mask, cb->xpath); - len = strlen(n->name) + 1; - if (len > size) + len = snprintf(dstbuf, size, "%s%s", + cb->xpath ? "//" : "", + n->name); + if (len < 0 || len >= size) return -1; - strcpy(dstbuf, n->name); return 0; }