From: Olivier Matz Date: Thu, 8 Mar 2018 21:25:46 +0000 (+0100) Subject: fix file node X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=48e94706856e269b21f5748a28f226fa846b0c4b;p=protos%2Flibecoli.git fix file node --- diff --git a/lib/ecoli_completed.c b/lib/ecoli_completed.c index e44ba9e..4113ef3 100644 --- a/lib/ecoli_completed.c +++ b/lib/ecoli_completed.c @@ -355,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: + completed->count_full++; + break; case EC_COMP_PARTIAL: - completed->count_match++; //XXX + completed->count_partial++; break; default: return -EINVAL; @@ -521,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 full=%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", @@ -555,7 +559,9 @@ int ec_completed_merge(struct ec_completed *to, TAILQ_INSERT_TAIL(&to->groups, grp, next); } to->count += from->count; - to->count_match += from->count_match; + to->count_full += from->count_full; + to->count_partial += from->count_partial; + to->count_unknown += from->count_unknown; ec_completed_free(from); return 0; @@ -571,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; } diff --git a/lib/ecoli_completed.h b/lib/ecoli_completed.h index 9eed0cb..c7a6a62 100644 --- a/lib/ecoli_completed.h +++ b/lib/ecoli_completed.h @@ -66,7 +66,9 @@ TAILQ_HEAD(ec_completed_group_list, ec_completed_group); struct ec_completed { unsigned count; - unsigned count_match; + unsigned count_full; + unsigned count_partial; + unsigned count_unknown; struct ec_parsed *cur_state; struct ec_completed_group *cur_group; struct ec_completed_group_list groups; diff --git a/lib/ecoli_node_cmd.c b/lib/ecoli_node_cmd.c index ba1469b..9653c0e 100644 --- a/lib/ecoli_node_cmd.c +++ b/lib/ecoli_node_cmd.c @@ -85,7 +85,6 @@ ec_node_cmd_eval_var(void **result, void *userctx, for (i = 0; i < node->len; i++) { id = ec_node_id(node->table[i]); - //printf("i=%d id=%s\n", i, id); if (id == NULL) continue; if (strcmp(str, id)) @@ -104,7 +103,6 @@ ec_node_cmd_eval_var(void **result, void *userctx, return -ENOMEM; } - //printf("eval var %s %p\n", str, eval); //XXX *result = eval; return 0; diff --git a/lib/ecoli_node_file.c b/lib/ecoli_node_file.c index fbba156..8af484b 100644 --- a/lib/ecoli_node_file.c +++ b/lib/ecoli_node_file.c @@ -120,7 +120,7 @@ ec_node_file_complete(const struct ec_node *gen_node, char *dname = NULL, *bname = NULL, *effective_dir; struct ec_completed_item *item = NULL; enum ec_completed_type type; - struct stat st; + struct stat st, st2; const char *input; size_t bname_len; struct dirent *de = NULL; @@ -194,7 +194,19 @@ ec_node_file_complete(const struct ec_node *gen_node, /* add '/' if it's a dir */ if (de->d_type == DT_DIR) { is_dir = 1; - } else if (de->d_type == DT_UNKNOWN) { // XXX todo + } else if (de->d_type == DT_UNKNOWN) { + int dir_fd = dirfd(dir); + + if (dir_fd < 0) + goto out; + ret = fstatat(dir_fd, de->d_name, &st2, 0); + if (ret != 0) { + ret = -errno; + goto out; + } + if (!S_ISDIR(st2.st_mode)) + goto out; + is_dir = 1; } else { is_dir = 0; } @@ -278,26 +290,22 @@ static int ec_node_file_testcase(void) ret |= EC_TEST_CHECK_PARSE(node, -1); /* test completion */ -#if 0 // XXX how to properly test file completion? ret |= EC_TEST_CHECK_COMPLETE(node, EC_NODE_ENDLIST, EC_NODE_ENDLIST); ret |= EC_TEST_CHECK_COMPLETE(node, - "", EC_NODE_ENDLIST, + "/tmp/toto/t", EC_NODE_ENDLIST, EC_NODE_ENDLIST); + ret |= EC_TEST_CHECK_COMPLETE_PARTIAL(node, + "/tmp/toto/t", EC_NODE_ENDLIST, + "/tmp/toto/titi/", EC_NODE_ENDLIST); ret |= EC_TEST_CHECK_COMPLETE(node, - "/", EC_NODE_ENDLIST, - EC_NODE_ENDLIST); - ret |= EC_TEST_CHECK_COMPLETE(node, - "/tmp", EC_NODE_ENDLIST, - EC_NODE_ENDLIST); + "/tmp/toto/f", EC_NODE_ENDLIST, + "/tmp/toto/foo", EC_NODE_ENDLIST); ret |= EC_TEST_CHECK_COMPLETE(node, - "/tmp/", EC_NODE_ENDLIST, - EC_NODE_ENDLIST); - ret |= EC_TEST_CHECK_COMPLETE(node, - "/tmp/.", EC_NODE_ENDLIST, - EC_NODE_ENDLIST); -#endif + "/tmp/toto/b", EC_NODE_ENDLIST, + "/tmp/toto/bar", "/tmp/toto/bar2", EC_NODE_ENDLIST); + ec_node_free(node); return ret; diff --git a/lib/ecoli_test.c b/lib/ecoli_test.c index 6b168d6..4a915f1 100644 --- a/lib/ecoli_test.c +++ b/lib/ecoli_test.c @@ -99,7 +99,7 @@ out: return ret; } -int ec_test_check_complete(struct ec_node *tk, ...) +int ec_test_check_complete(struct ec_node *tk, enum ec_completed_type type, ...) { struct ec_completed *c = NULL; struct ec_strvec *vec = NULL; @@ -108,7 +108,7 @@ int ec_test_check_complete(struct ec_node *tk, ...) unsigned int count = 0; va_list ap; - va_start(ap, tk); + va_start(ap, type); /* build a string vector */ vec = ec_strvec(); @@ -146,7 +146,7 @@ int ec_test_check_complete(struct ec_node *tk, ...) count++; /* only check matching completions */ - iter = ec_completed_iter(c, EC_COMP_FULL); + iter = ec_completed_iter(c, type); while ((item = ec_completed_iter_next(iter)) != NULL) { const char *str = ec_completed_item_get_str(item); if (str != NULL && strcmp(str, s) == 0) @@ -162,10 +162,10 @@ int ec_test_check_complete(struct ec_node *tk, ...) } /* check if we have more completions (or less) than expected */ - if (count != ec_completed_count(c, EC_COMP_FULL)) { + if (count != ec_completed_count(c, type)) { EC_LOG(EC_LOG_ERR, "nb_completion (%d) does not match (%d)\n", - count, ec_completed_count(c, EC_COMP_FULL)); + count, ec_completed_count(c, type)); ec_completed_dump(stdout, c); ret = -1; } diff --git a/lib/ecoli_test.h b/lib/ecoli_test.h index fa3fe6c..90159f1 100644 --- a/lib/ecoli_test.h +++ b/lib/ecoli_test.h @@ -31,7 +31,9 @@ #include #include -#include + +struct ec_node; +enum ec_completed_type; // XXX check if already exists? #define EC_TEST_REGISTER(t) \ @@ -96,10 +98,18 @@ int ec_test_check_parse(struct ec_node *node, int expected, ...); ret_; \ }) -int ec_test_check_complete(struct ec_node *node, ...); +int ec_test_check_complete(struct ec_node *node, + enum ec_completed_type type, ...); #define EC_TEST_CHECK_COMPLETE(node, args...) ({ \ - int ret_ = ec_test_check_complete(node, args); \ + int ret_ = ec_test_check_complete(node, EC_COMP_FULL, args); \ + if (ret_) \ + EC_TEST_ERR("complete test failed"); \ + ret_; \ +}) + +#define EC_TEST_CHECK_COMPLETE_PARTIAL(node, args...) ({ \ + int ret_ = ec_test_check_complete(node, EC_COMP_PARTIAL, args); \ if (ret_) \ EC_TEST_ERR("complete test failed"); \ ret_; \ diff --git a/lib/main-readline.c b/lib/main-readline.c index 304b074..a8a5840 100644 --- a/lib/main-readline.c +++ b/lib/main-readline.c @@ -93,7 +93,7 @@ static char *my_completion_entry(const char *s, int state) return NULL; item_str = ec_completed_item_get_str(item); - if (c->count_match == 1) { + if (c->count_full == 1) { /* don't add the trailing space for partial completions */ if (state == 0) {