/* New for v2.0: readline support -- daw */ /* all the tab completion support is here in this one file */ #ifdef HAVE_STDLIB_H #include <stdlib.h> #endif #include <stdio.h> #include <ctype.h> extern char *mystrdup(); typedef struct list_s { char *word; struct list_s *next; } list_t; static list_t *complist = 0; /* tab completion list */ /* * the completion generation function for readline. * this function will be called repeatedly with the * same s -- state=0 the first time, and state!=0 the * rest of the time. * * it returns a pointer to a match each time, and a * (char *) 0 pointer when it's done. */ char * rltab_generate(s, state) char *s; int state; { static list_t *p; char *match; if (state == 0) { if (complist == 0) return ((char *) 0); p = complist->next; } for (; p; p = p->next) if (strncasecmp(s, p->word, strlen(s)) == 0) { match = mystrdup(p->word); p = p->next; return (match); } return ((char *) 0); } static void rltab_add(word) char *word; { list_t *p; if (complist == 0) { /* add dummy header node */ if ((complist = (list_t *) malloc(sizeof(list_t))) == 0) syserr("rltab_add: malloc"); complist->word = 0; if ((complist->next = (list_t *) malloc(sizeof(list_t))) == 0) syserr("rltab_add: malloc"); p = complist->next; p->word = mystrdup(word); p->next = 0; return; } /* avoid duplicates */ for (p = complist->next; p; p = p->next) if (strcasecmp(p->word, word) == 0) return; /* add to head of list */ if ((p = (list_t *) malloc(sizeof(list_t))) == 0) syserr("rltab_add: malloc"); p->word = mystrdup(word); p->next = complist->next; complist->next = p; } void rltab_delete(word) char *word; { list_t *p, *q; if (complist == 0) { tintin_puts("#Delete failed: empty completion list.", 0); return; } for (p = complist; p->next; p = p->next) if (strcasecmp(p->next->word, word) == 0) { q = p->next; p->next = p->next->next; free(q->word); free(q); tintin_puts("#Ok, deleted.", 0); return; } tintin_puts("#Delete failed: word not in completion list.", 0); } void rltab_list( /* void */ ) { list_t *p; int col = 0, ncols = 4; char line[128]; if (complist == 0 || complist->next == 0) { tintin_puts("#Empty completion list.", 0); return; } line[0] = '\0'; for (p = complist->next; p; p = p->next) { sprintf(line + strlen(line), "%15.15s ", p->word); if (++col == ncols) { tintin_puts(line, 0); col = 0; line[0] = '\0'; } } if (line[0]) tintin_puts(line, 0); } static void rltab_purge( /* void */ ) { list_t *p, *q; if (complist == 0) { if ((complist = (list_t *) malloc(sizeof(list_t))) == 0) syserr("rltab_purge: malloc"); complist->word = 0; complist->next = 0; return; } for (p = complist->next; p; p = q) { q = p->next; free(p->word); free(p); } complist->next = 0; } void rltab_read( /* void */ ) { FILE *f; char *s, *t, line[128]; if ((f = fopen("tab.txt", "r")) == 0) { tintin_puts("#Couldn't open tab.txt", 0); return; } rltab_purge(); while (fgets(line, sizeof(line), f)) { /* delete leading and trailing whitespace */ for (s = line; isspace(*s); s++); for (t = s; *t && !isspace(*t); t++); *t = '\0'; rltab_add(s); } fclose(f); tintin_puts("#Read tab.txt, completion list initialized.", 0); } void do_tabadd(arg) char *arg; { char buf[128]; if (arg == 0 || *arg == '\0') { tintin_puts("#Add failed: no word specified.", 0); return; } get_arg_in_braces(arg, buf, 1); rltab_add(buf); tintin_puts("#Added.", 0); } void do_tabdel(arg) char *arg; { char buf[128]; if (arg == 0 || *arg == '\0') { tintin_puts("#Delete failed: no word specified.", 0); return; } get_arg_in_braces(arg, buf, 1); rltab_delete(buf); } void do_tabsave( /* void */ ) { FILE *f; list_t *p; if (complist == 0 || complist->next == 0) { tintin_puts("#Empty completion list, nothing to save.", 0); return; } if ((f = fopen("tab.txt", "w")) == 0) { tintin_puts("#Couldn't open tab.txt", 0); return; } for (p = complist->next; p; p = p->next) fprintf(f, "%s\n", p->word); fclose(f); tintin_puts("#Saved to tab.txt.", 0); }