1implement Complete; 2 3# Limbo translation by caerwyn of libcomplete on Plan 9 4# Subject to the Lucent Public License 1.02 5 6include "sys.m"; 7 sys: Sys; 8 9include "string.m"; 10 str: String; 11 12include "complete.m"; 13 14include "readdir.m"; 15 readdir: Readdir; 16 17init() 18{ 19 sys = load Sys Sys->PATH; 20 str = load String String->PATH; 21 readdir = load Readdir Readdir->PATH; 22} 23 24 25longestprefixlength(a, b: string, n: int): int 26{ 27 for(i := 0; i < n; i++) 28 if(a[i] != b[i]) 29 break; 30 return i; 31} 32 33complete(dir, s: string): (ref Completion, string) 34{ 35 if(str->splitl(s, "/").t1 != nil) 36 return (nil, "slash character in name argument to complete()"); 37 38 (da, n) := readdir->init(dir, Readdir->COMPACT); 39 if(n < 0) 40 return (nil, sys->sprint("%r")); 41 if(n == 0) 42 return (nil, nil); 43 44 45 c := ref Completion(0, 0, nil, 0, nil); 46 47 name := array[n] of string; 48 mode := array[n] of int; 49 length := len s; 50 nfile := 0; 51 minlen := 1000000; 52 for(i := 0; i < n; i++) 53 if(str->prefix(s,da[i].name)){ 54 name[nfile] = da[i].name; 55 mode[nfile] = da[i].mode; 56 if(minlen > len da[i].name) 57 minlen = len da[i].name; 58 nfile++; 59 } 60 61 if(nfile > 0){ 62 # report interesting results 63 # trim length back to longest common initial string 64 for(i = 1; i < nfile; i++) 65 minlen = longestprefixlength(name[0], name[i], minlen); 66 67 c.complete = (nfile == 1); 68 c.advance = c.complete || (minlen > length); 69 c.str = name[0][length:minlen]; 70 if(c.complete){ 71 if(mode[0]&Sys->DMDIR) 72 c.str[minlen++ - length] = '/'; 73 else 74 c.str[minlen++ - length] = ' '; 75 } 76 c.nmatch = nfile; 77 }else{ 78 # no match: return all names 79 for(i = 0; i < n; i++){ 80 name[i] = da[i].name; 81 mode[i] = da[i].mode; 82 } 83 nfile = n; 84 c.nmatch = 0; 85 } 86 c.filename = name; 87 for(i = 0; i < nfile; i++) 88 if(mode[i] & Sys->DMDIR) 89 c.filename[i] += "/"; 90 91 return (c, nil); 92} 93