diff options
Diffstat (limited to 'appl/cmd/lookman.b')
-rw-r--r-- | appl/cmd/lookman.b | 250 |
1 files changed, 0 insertions, 250 deletions
diff --git a/appl/cmd/lookman.b b/appl/cmd/lookman.b deleted file mode 100644 index 53557c8b..00000000 --- a/appl/cmd/lookman.b +++ /dev/null @@ -1,250 +0,0 @@ -implement Lookman; -include "sys.m"; -include "bufio.m"; -include "draw.m"; - - -Lookman : module { - init : fn (ctxt : ref Draw->Context, argv : list of string); -}; - -sys : Sys; -bufio : Bufio; -Iobuf : import bufio; - -ctype := array [256] of { * => byte 0 }; - -MANINDEX : con "/man/index"; - -init(nil : ref Draw->Context, argv : list of string) -{ - sys = load Sys Sys->PATH; - bufio = load Bufio Bufio->PATH; - - if (bufio == nil) - raise "init:fail"; - - # setup our char conversion table - # map upper-case to lower-case - for (i := 'A'; i <= 'Z'; i++) - ctype[i] = byte ((i - 'A') + 'a'); - - # only allow the following chars - okchars := "abcdefghijklmnopqrstuvwxyz0123456789+.:½ "; - for (i = 0; i < len okchars; i++) { - ch := okchars[i]; - ctype[ch] = byte ch; - } - - stdout := bufio->fopen(sys->fildes(1), Sys->OWRITE); - - argv = tl argv; - paths := lookup(argv); - for (; paths != nil; paths = tl paths) - stdout.puts(sys->sprint("%s\n", hd paths)); - stdout.flush(); -} - -lookup(words : list of string) : list of string -{ - # open the index file - manindex := bufio->open(MANINDEX, Sys->OREAD); - if (manindex == nil) { - sys->print("cannot open %s: %r\n", MANINDEX); - return nil; - } - - # convert to lower-case and discard funny chars - keywords : list of string; - for (; words != nil; words = tl words) { - word := hd words; - kw := ""; - for (i := 0; i < len word; i++) { - ch := word[i]; - if (ch < len ctype && ctype[ch] != byte 0) - kw[len kw] = int ctype[ch]; - } - if (kw != "") - keywords = kw :: keywords; - } - - if (keywords == nil) - return nil; - - keywords = sortuniq(keywords); - matches : list of list of string; - - for (; keywords != nil; keywords = tl keywords) { - kw := hd keywords; - matchlist := look(manindex, '\t', kw); - pathlist : list of string = nil; - for (; matchlist != nil; matchlist = tl matchlist) { - line := hd matchlist; - (n, toks) := sys->tokenize(line, "\t"); - if (n != 2) - continue; - pathlist = hd tl toks :: pathlist; - } - if (pathlist != nil) - matches = pathlist :: matches; - } - - return intersect(matches); -} - -getentry(iob : ref Iobuf) : (string, string) -{ - while ((s := iob.gets('\n')) != nil) { - if (s[len s -1] == '\n') - s = s[0:len s -1]; - if (s == nil) - continue; - (n, toks) := sys->tokenize(s, "\t"); - if (n != 2) - continue; - return (hd toks, hd tl toks); - } - return (nil, nil); -} - -sortuniq(strlist : list of string) : list of string -{ - strs := array [len strlist] of string; - for (i := 0; strlist != nil; (i, strlist) = (i+1, tl strlist)) - strs[i] = hd strlist; - - # simple sort (greatest first) - for (i = 0; i < len strs - 1; i++) { - for (j := i+1; j < len strs; j++) - if (strs[i] < strs[j]) - (strs[i], strs[j]) = (strs[j], strs[i]); - } - - # construct list (result is ascending) - r : list of string; - prev := ""; - for (i = 0; i < len strs; i++) { - if (strs[i] != prev) { - r = strs[i] :: r; - prev = strs[i]; - } - } - return r; -} - -intersect(strlists : list of list of string) : list of string -{ - if (strlists == nil) - return nil; - - okl := hd strlists; - for (strlists = tl strlists; okl != nil && strlists != nil; strlists = tl strlists) { - find := hd strlists; - found : list of string = nil; - for (; okl != nil; okl = tl okl) { - ok := hd okl; - for (scanl := find; scanl != nil; scanl = tl scanl) { - scan := hd scanl; - if (scan == ok) { - found = ok :: found; - break; - } - } - } - okl = found; - } - return sortuniq(okl); -} - -# binary search for key in f. -# based on Plan 9 look.c -# -look(f: ref Iobuf, sep: int, key: string): list of string -{ - bot := mid := 0; - top := int f.seek(big 0, Sys->SEEKEND); - key = canon(key, sep); - - for (;;) { - mid = (top + bot) / 2; - f.seek(big mid, Sys->SEEKSTART); - c: int; - do { - c = f.getb(); - mid++; - } while (c != Bufio->EOF && c != Bufio->ERROR && c != '\n'); - (entry, eof) := getword(f); - if (entry == nil && eof) - break; - entry = canon(entry, sep); - case comparewords(key, entry) { - -2 or -1 or 0 => - if (top <= mid) - break; - top = mid; - continue; - 1 or 2 => - bot = mid; - continue; - } - break; - } - matchlist : list of string; - f.seek(big bot, Sys->SEEKSTART); - for (;;) { - (entry, eof) := getword(f); - if (entry == nil && eof) - return matchlist; - word := canon(entry, sep); - case comparewords(key, word) { - -1 or 0 => - matchlist = entry :: matchlist; - continue; - 1 or 2 => - continue; - } - break; - } - return matchlist; -} - -comparewords(s, t: string): int -{ - if (s == t) - return 0; - i := 0; - for (; i < len s && i < len t && s[i] == t[i]; i++) - ; - if (i >= len s) - return -1; - if (i >= len t) - return 1; - if (s[i] < t[i]) - return -2; - return 2; -} - -getword(f: ref Iobuf): (string, int) -{ - ret := ""; - for (;;) { - c := f.getc(); - if (c == Bufio->EOF || c == Bufio->ERROR) - return (ret, 0); - if (c == '\n') - break; - ret[len ret] = c; - } - return (ret, 1); -} - -canon(s: string, sep: int): string -{ - if (sep < 0) - return s; - i := 0; - for (; i < len s; i++) - if (s[i] == sep) - break; - return s[0:i]; -} |