history.c (1746B)
1 #include "dat.h" 2 #include <assert.h> 3 #include <bio.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <unistd.h> 7 #include "fns.h" 8 9 static void 10 splice(Item *i) { 11 if(i->next != nil) 12 i->next->prev = i->prev; 13 if(i->prev != nil) 14 i->prev->next = i->next; 15 } 16 17 char* 18 history_search(int dir, char *string, int n) { 19 Item *i; 20 21 if(dir == FORWARD) { 22 if(histsel == &hist) 23 return hist.string; 24 for(i=histsel->next; i != hist.next; i=i->next) 25 if(!i->string || !compare(i->string, string, n)) { 26 histsel = i; 27 return i->string; 28 } 29 return string; 30 } 31 assert(dir == BACKWARD); 32 33 if(histsel == &hist) { 34 free(hist.string); 35 hist.string = estrdup(input.string); 36 } 37 38 for(i=histsel->prev; i != &hist; i=i->prev) 39 if(!compare(i->string, string, n)) { 40 histsel = i; 41 return i->string; 42 } 43 return string; 44 } 45 46 void 47 history_dump(const char *path, int max) { 48 static char *items[20]; 49 static char *tmp; 50 Biobuf b; 51 Item *h, *first; 52 int i, n, fd; 53 54 SET(first); 55 if(fork() != 0) 56 return; 57 58 tmp = smprint("%s.XXXXXX", path); 59 fd = mkstemp(tmp); 60 if(fd < 0) { 61 fprint(2, "%s: Can't create temporary history file %q: %r\n", argv0, path); 62 _exit(1); 63 } 64 65 hist.string = input.string; 66 n = 0; 67 hist.next->prev = nil; 68 for(h=&hist; h; h=h->prev) { 69 for(i=0; i < nelem(items); i++) 70 if(items[i] && !strcmp(h->string, items[i])) { 71 splice(h); 72 goto next; 73 } 74 items[n++ % nelem(items)] = h->string; 75 first = h; 76 if(!max || n >= max) 77 break; 78 next: 79 continue; 80 } 81 82 Binit(&b, fd, OWRITE); 83 hist.next = nil; 84 for(h=first; h; h=h->next) 85 if(Bprint(&b, "%s\n", h->string) < 0) { 86 unlink(tmp); 87 fprint(2, "%s: Can't write temporary history file %q: %r\n", argv0, path); 88 _exit(1); 89 } 90 Bterm(&b); 91 rename(tmp, path); 92 _exit(0); 93 } 94