added completion lists
authortridge <>
Tue, 4 Jun 2002 04:39:03 +0000 (04:39 +0000)
committertridge <>
Tue, 4 Jun 2002 04:39:03 +0000 (04:39 +0000)
rline/rline.c

index 7d9881862d127d21877d0be92c8f33ac1856cf93..cf36b31e04c22f89955284bc57c3177e73b99149 100644 (file)
 static void usage(void)
 {
        printf("
-readline <command>
+readline [options] <command>
 
 This add readline support to any command line driven program. 
+
+Options:
+   -c FILE          load a list of command completions from FILE
+   -h               show this help
+   --               stop processing options (used to allow options to programs)
 ");
 }
 
+/* list of command completions */
+static char **cmd_list;
+static int num_commands;
+
+static void load_completions(const char *fname)
+{
+       FILE *f = fopen(fname, "r");
+       char line[200];
+
+       if (!f) {
+               perror(fname);
+               return;
+       }
+
+       while (fgets(line, sizeof(line), f)) {
+               int len = strlen(line);
+               if (len == 0) continue;
+               line[len-1] = 0;
+               cmd_list = (char **)realloc(cmd_list, sizeof(char *)*(num_commands+1));
+               if (!cmd_list) break;
+               cmd_list[num_commands++] = strdup(line);
+       }
+
+       fclose(f);
+}
+
+
+/*
+  command completion generator
+ */
+static char *command_generator(const char *line, int state)
+{
+       static int idx, len;
+
+       if (!cmd_list) return NULL;
+
+       if (!state) {
+               /* first call */
+               idx = 0;
+               len = strlen(line);
+       }
+
+       while (idx < num_commands &&
+              strncmp(line, cmd_list[idx], len) != 0) {
+               idx++;
+       }
+
+       if (idx == num_commands) return NULL;
+
+       return strdup(cmd_list[idx++]);
+}
+
+
+/* 
+   our completion function, so we can support tab completion
+ */
+static char **completion_function(const char *line, int start, int end)
+{
+       if (start != 0) {
+               /* they are trying to complete an argument */
+               return NULL;
+       }
+
+       return (char **)completion_matches(line, command_generator);
+}
+
+static int pipe_fd;
+
+/* callback function when readline has a whole line */
+void line_handler(char *line) 
+{
+       if (!line) exit(0);
+       dprintf(pipe_fd, "%s\n", line);
+       if (*line) {
+               add_history(line);
+       }
+}
+
 int main(int argc, char *argv[])
 {
        int fd1[2], fd2[2];
        char *prompt;
-
-       void line_handler(char *line) {
-               if (!line) exit(0);
-               dprintf(fd1[1], "%s\n", line);
-               if (*line) {
-                       add_history(line);
+       int c;
+       extern int optind;
+       extern char *optarg;
+
+       while ((c = getopt(argc, argv, "c:h")) != -1) {
+               switch (c) {
+               case '-':
+                       break;
+               case 'c':
+                       load_completions(optarg);
+                       break;
+               case 'h':
+               default:
+                       usage();
+                       exit(1);
                }
        }
 
-       if (argc < 2) {
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1) {
                usage();
                exit(1);
        }
@@ -50,14 +145,17 @@ int main(int argc, char *argv[])
                close(1);
                dup2(fd1[0], 0);
                dup2(fd2[1], 1);
-               return execvp(argv[1], argv+1);
+               return execvp(argv[0], argv);
        }
 
+       pipe_fd = fd1[1];
+
        close(fd2[1]);
        close(fd1[0]);
 
-       prompt = strdup("");
+       prompt = strdup("");
        rl_already_prompted = 1;
+       rl_attempted_completion_function = completion_function;
        rl_callback_handler_install(prompt, line_handler);
 
        while (1) {