diff options
| author | Charles.Forsyth <devnull@localhost> | 2007-01-15 21:04:26 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2007-01-15 21:04:26 +0000 |
| commit | 8911721efbf3b3721376e2baa30bae002c2975c2 (patch) | |
| tree | aa059ffa39c2c4f1cd5ed2e137dcb9b079de2717 /appl/lib/complete.b | |
| parent | 0e96539ff7cff23233d3f0a64bb285b385a3a1f4 (diff) | |
20070115
Diffstat (limited to 'appl/lib/complete.b')
| -rw-r--r-- | appl/lib/complete.b | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/appl/lib/complete.b b/appl/lib/complete.b new file mode 100644 index 00000000..1a2e7713 --- /dev/null +++ b/appl/lib/complete.b @@ -0,0 +1,93 @@ +implement Complete; + +# Limbo translation by caerwyn of libcomplete on Plan 9 +# Subject to the Lucent Public License 1.02 + +include "sys.m"; + sys: Sys; + +include "string.m"; + str: String; + +include "complete.m"; + +include "readdir.m"; + readdir: Readdir; + +init() +{ + sys = load Sys Sys->PATH; + str = load String String->PATH; + readdir = load Readdir Readdir->PATH; +} + + +longestprefixlength(a, b: string, n: int): int +{ + for(i := 0; i < n; i++) + if(a[i] != b[i]) + break; + return i; +} + +complete(dir, s: string): (ref Completion, string) +{ + if(str->splitl(s, "/").t1 != nil) + return (nil, "slash character in name argument to complete()"); + + (da, n) := readdir->init(dir, Readdir->COMPACT); + if(n < 0) + return (nil, sys->sprint("%r")); + if(n == 0) + return (nil, nil); + + readdir = nil; + + c := ref Completion(0, 0, nil, 0, nil); + + name := array[n] of string; + mode := array[n] of int; + length := len s; + nfile := 0; + minlen := 1000000; + for(i := 0; i < n; i++) + if(str->prefix(s,da[i].name)){ + name[nfile] = da[i].name; + mode[nfile] = da[i].mode; + if(minlen > len da[i].name) + minlen = len da[i].name; + nfile++; + } + + if(nfile > 0){ + # report interesting results + # trim length back to longest common initial string + for(i = 1; i < nfile; i++) + minlen = longestprefixlength(name[0], name[i], minlen); + + c.complete = (nfile == 1); + c.advance = c.complete || (minlen > length); + c.str = name[0][length:minlen]; + if(c.complete){ + if(mode[0]&Sys->DMDIR) + c.str[minlen++ - length] = '/'; + else + c.str[minlen++ - length] = ' '; + } + c.nmatch = nfile; + }else{ + # no match: return all names + for(i = 0; i < n; i++){ + name[i] = da[i].name; + mode[i] = da[i].mode; + } + nfile = n; + c.nmatch = 0; + } + c.filename = name; + for(i = 0; i < nfile; i++) + if(mode[i] & Sys->DMDIR) + c.filename[i] += "/"; + + return (c, nil); +} |
