xref: /inferno-os/appl/lib/complete.b (revision 2b69dba5038ffd0b59cf30a4c44bce549e5097f8)
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