Add fnmatch() filtering to output to improve tab-completion.
authorKristian Høgsberg <krh@redhat.com>
Tue, 23 Oct 2007 05:57:39 +0000 (01:57 -0400)
committerKristian Høgsberg <krh@redhat.com>
Tue, 23 Oct 2007 05:57:39 +0000 (01:57 -0400)
bash-completion.sh
main.c
razor.c
razor.h

index ff6f274..b0b0ce8 100644 (file)
@@ -1,17 +1,19 @@
 __razor_commands () {
-    COMPREPLY=($(compgen -W "list-requires list-provides list-files list-file-packages what-requires what-provides import-yum import-rpmdb validate update diff" -- $1))
+    local IFS=$'\n'
+    COMPREPLY=($(IFS=: compgen -S' ' -W "list-requires:list-provides:list-files:list-file-packages:what-requires:what-provides:import-yum:import-rpmdb:validate:update:diff" -- $1))
 }
 
 __razor_packages () {
-    COMPREPLY=($(compgen -W "$(./razor list)" -- $1))
+    local IFS=$'\n'
+
+    COMPREPLY=($(./razor list "$1*" | while read p; do echo "$p "; done))
 }
 
 __razor_files() {
-    COMPREPLY=($(compgen -W "$(./razor list-files)" -- $1))
+    COMPREPLY=($(./razor list-files "$1*"))
 }
 
 __razor_requires() {
-    echo requires
     COMPREPLY=($(compgen -W "$(./razor list-requires)" -- $1))
 }
 
@@ -34,4 +36,4 @@ __razor() {
     fi
 }
 
-complete -F __razor razor
+complete -o nospace -F __razor razor
diff --git a/main.c b/main.c
index 49b0daf..eb0c177 100644 (file)
--- a/main.c
+++ b/main.c
@@ -16,7 +16,7 @@ command_list(int argc, const char *argv[])
        struct razor_set *set;
 
        set = razor_set_open(repo_filename);
-       razor_set_list(set);
+       razor_set_list(set, argv[0]);
        razor_set_destroy(set);
 
        return 0;
diff --git a/razor.c b/razor.c
index f15b471..b6b83c0 100644 (file)
--- a/razor.c
+++ b/razor.c
@@ -11,6 +11,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <ctype.h>
+#include <fnmatch.h>
 
 #include "razor.h"
 
@@ -834,56 +835,74 @@ build_file_tree(struct razor_importer *importer)
        array_release(&importer->files);
 }
 
-static struct razor_entry *
-find_entry(struct razor_set *set, struct razor_entry *dir, const char *name)
+static const char *
+find_dir(struct razor_set *set, struct razor_entry **dir, const char *pattern)
 {
        struct razor_entry *e, *end;
-       char *pool = set->string_pool.data;
-       char *p, *n;
-
-       if (name == NULL)
-               return dir;
+       const char *n, *pool = set->string_pool.data;
+       int len;
 
-       p = strchr(name + 1, '/');
-       e = (struct razor_entry *) set->file_tree.data + dir->start;
-       end = e + dir->count;
+       e = (struct razor_entry *) set->file_tree.data + (*dir)->start;
+       end = e + (*dir)->count;
 
        while (e < end) {
                n = pool + e->name;
-               if ((p != NULL && strncmp(n, name + 1, p - (name + 1)) == 0) ||
-                   (p == NULL && strcmp(n, name + 1) == 0))
-                       return find_entry(set, e, p);
+               len = strlen(n);
+               if (len == 0) {
+                       /* FIXME: Shouldn't have 0-length entries... */
+                       e++;
+                       continue;
+               }
+                       
+               if (strncmp(pattern + 1, n, len) == 0 &&
+                   pattern[len + 1] == '/') {
+                       *dir = e;
+                       return find_dir(set, dir, pattern + len + 1);
+               }
                e++;
        }
 
-       return NULL;
+       return pattern + 1;
 }
 
 static void
-list_dir(struct razor_set *set, struct razor_entry *e, int indent)
+list_dir(struct razor_set *set, struct razor_entry *dir,
+        const char *pattern, const char *base)
 {
-       struct razor_entry *c;
+       struct razor_entry *e, *end;
        char *pool = set->string_pool.data;
-       int i;
 
-       for (i = 0; i < indent; i++)
-               putchar(' ');
-       printf("%s\n", pool + e->name);
-       for (i = 0; i < e->count; i++) {
-               c = (struct razor_entry *) set->file_tree.data + e->start + i;
-               list_dir(set, c, indent + 2);
+       e = (struct razor_entry *) set->file_tree.data + dir->start;
+       end = e + dir->count;
+
+       for ( ; e < end; e++) {
+               if (base && base[0] && fnmatch(base, &pool[e->name], 0) != 0)
+                       continue;
+               if (base && pattern)
+                       printf("%.*s%s%s\n",
+                              base - pattern, pattern, pool + e->name,
+                              e->count > 0 ? "/" : "");
+               else
+                       printf("%s%s\n", pool + e->name,
+                              e->count > 0 ? "/" : "");
+               
        }
 }
 
 void
-razor_set_list_files(struct razor_set *set, const char *prefix)
+razor_set_list_files(struct razor_set *set, const char *pattern)
 {
        struct razor_entry *e;
+       const char *base;
 
-       e = find_entry(set, set->file_tree.data, prefix);
-       if (e == NULL)
+       if (pattern == NULL)
+               pattern = "/";
+
+       e = set->file_tree.data;
+       base = find_dir(set, &e, pattern);
+       if (base == NULL)
                return;
-       list_dir(set, e, 2);
+       list_dir(set, e, pattern, base);
 }
 
 void
@@ -891,11 +910,12 @@ razor_set_list_file_packages(struct razor_set *set, const char *filename)
 {
        struct razor_entry *e;
        struct razor_package *packages, *p;
-       const char *pool;
+       const char *pool, *base;
        unsigned long *r;
 
-       e = find_entry(set, set->file_tree.data, filename);
-       if (e == NULL)
+       e = set->file_tree.data;
+       base = find_dir(set, &e, filename);
+       if (base == NULL)
                return;
        
        r = (unsigned long *) set->package_pool.data + e->packages;
@@ -946,15 +966,22 @@ razor_importer_finish(struct razor_importer *importer)
 }
 
 void
-razor_set_list(struct razor_set *set)
+razor_set_list(struct razor_set *set, const char *pattern)
 {
        struct razor_package *p, *end;
+       int with_version = 0;
        char *pool;
 
        pool = set->string_pool.data;
        end = set->packages.data + set->packages.size;
-       for (p = set->packages.data; p < end; p++)
-               printf("%s %s\n", &pool[p->name], &pool[p->version]);
+       for (p = set->packages.data; p < end; p++) {
+               if (pattern && fnmatch(pattern, &pool[p->name], 0) != 0)
+                   continue;
+               if (with_version)
+                       printf("%s %s\n", &pool[p->name], &pool[p->version]);
+               else
+                       printf("%s\n", &pool[p->name]);
+       }
 }
 
 struct razor_set *bsearch_set;
diff --git a/razor.h b/razor.h
index 07ee51d..09e98f9 100644 (file)
--- a/razor.h
+++ b/razor.h
@@ -9,7 +9,7 @@ struct razor_set *razor_set_open(const char *filename);
 void razor_set_destroy(struct razor_set *set);
 int razor_set_write(struct razor_set *set, const char *filename);
 
-void razor_set_list(struct razor_set *set);
+void razor_set_list(struct razor_set *set, const char *pattern);
 void razor_set_list_requires(struct razor_set *set, const char *name);
 void razor_set_list_provides(struct razor_set *set, const char *name);
 void razor_set_list_requires_packages(struct razor_set *set,