Browse Source

Plan 9 from Bell Labs 2004-01-01

David du Colombier 20 years ago
parent
commit
bf9d4f92ca

+ 5 - 0
dist/replica/plan9.db

@@ -3383,6 +3383,7 @@ sys/include/authsrv.h - 664 sys sys 1014929062 4542
 sys/include/bin.h - 664 sys sys 1014929062 215
 sys/include/bio.h - 664 sys sys 1014929062 1854
 sys/include/bootexec.h - 664 sys sys 1014929062 3144
+sys/include/complete.h - 664 sys sys 1072904891 517
 sys/include/control.h - 664 sys sys 1045419238 4801
 sys/include/ctype.h - 664 sys sys 1014929062 951
 sys/include/cursor.h - 664 sys sys 1014929062 102
@@ -4756,6 +4757,7 @@ sys/man/2/cachechars - 664 sys sys 944959696 7061
 sys/man/2/chdir - 664 sys sys 944959694 552
 sys/man/2/cleanname - 664 sys sys 950593488 709
 sys/man/2/color - 664 sys sys 944959697 1335
+sys/man/2/complete - 664 sys sys 1072905221 2175
 sys/man/2/control - 664 sys sys 1037465511 42782
 sys/man/2/cputime - 664 sys sys 1015091518 713
 sys/man/2/ctime - 664 sys sys 954378853 2547
@@ -11734,6 +11736,9 @@ sys/src/libc/sparc/strcpy.s - 664 sys sys 944961720 1115
 sys/src/libc/sparc/tas.s - 664 sys sys 944961721 67
 sys/src/libc/sparc/vlop.s - 664 sys sys 944961720 2423
 sys/src/libc/sparc/vlrt.c - 664 sys sys 1067723054 9066
+sys/src/libcomplete - 20000000775 sys sys 1072904881 0
+sys/src/libcomplete/complete.c - 664 sys sys 1072904881 2673
+sys/src/libcomplete/mkfile - 664 sys sys 1072904881 208
 sys/src/libcontrol - 20000000775 sys sys 1016857569 0
 sys/src/libcontrol/box.c - 664 sys sys 1015095043 3276
 sys/src/libcontrol/button.c - 664 sys sys 1015095044 4508

+ 5 - 0
dist/replica/plan9.log

@@ -13251,3 +13251,8 @@
 1072836117 0 c 386/lib/ape/libap.a - 664 sys sys 1072835459 812790
 1072836117 1 c sys/src/ape/lib/ap/plan9/_buf.c - 664 sys sys 1072835434 9924
 1072836117 2 c sys/src/ape/lib/ap/plan9/lib.h - 664 sys sys 1072835434 2071
+1072909862 0 a sys/include/complete.h - 664 sys sys 1072904891 517
+1072909862 1 a sys/man/2/complete - 664 sys sys 1072905221 2175
+1072909862 2 a sys/src/libcomplete - 20000000775 sys sys 1072904881 0
+1072909862 3 a sys/src/libcomplete/complete.c - 664 sys sys 1072904881 2673
+1072909862 4 a sys/src/libcomplete/mkfile - 664 sys sys 1072904881 208

+ 15 - 0
sys/include/complete.h

@@ -0,0 +1,15 @@
+#pragma	lib	"libcomplete.a"
+#pragma src "/sys/src/libcomplete"
+
+typedef struct Completion Completion;
+
+struct Completion{
+	uchar advance;		/* whether forward progress has been made */
+	uchar complete;	/* whether the completion now represents a file or directory */
+	char *string;		/* the string to advance, suffixed " " or "/" for file or directory */
+	int nfile;			/* number of files that matched */
+	char **filename;	/* their names */
+};
+
+Completion* complete(char *dir, char *s);
+void freecompletion(Completion*);

+ 94 - 0
sys/man/2/complete

@@ -0,0 +1,94 @@
+.TH COMPLETE 2
+.SH NAME
+complete \- file name completion
+.SH SYNOPSIS
+.B #include <u.h>
+.br
+.B #include <libc.h>
+.br
+.B #include <complete.h>
+.PP
+.ft L
+.nf
+.ta \w'    'u +\w'    'u +\w'    'u +\w'    'u +\w'    'u
+typedef struct Completion	Completion;
+struct Completion{
+	uchar advance;		/* whether forward progress has been made */
+	uchar complete;	/* whether the completion now represents a file or directory */
+	char *string;		/* the string to advance, suffixed " " or "/" for file or directory */
+	int nfile;			/* number of files that matched */
+	char **filename;	/* their names */
+};
+
+.fi
+.PP
+.B
+.ta \w'\fLchar* 'u
+
+.PP
+.B
+Completion* complete(char *dir, char *s);
+.PP
+.B
+void freecompletion(Completion *c);
+.SH DESCRIPTION
+The
+.I complete
+function implements file name completion.
+Given a directory
+.I dir
+and a string
+.IR s ,
+it returns an analysis of the file names in that directory that begin with the string
+.IR s .
+The field
+.B nfile
+will be set to the number of files that match the prefix and
+.B filename
+will be filled in with their names.
+If the file named is a directory, a slash character will be appended to it.
+.PP
+The flag
+.B advance
+reports whether the string
+.I s
+can be extended without changing the set of files that match.  If true,
+.B string
+will be set to the extension; that is, the value of
+.B string
+may be appended to
+.I s
+by the caller to extend the embryonic file name unambiguously.
+.PP
+The flag
+.B complete
+reports whether the extended file name uniquely identifies a file.
+If true,
+.B string
+will be suffixed with a blank, or a slash and a blank,
+depending on whether the resulting file name identifies a plain file or a directory.
+.PP
+The
+.I freecompletion
+function frees a
+.B Completion
+structure and its contents.
+.PP
+In
+.IR rio (1)
+and
+.IR acme (1),
+file name completion is triggered by a control-F character or an Insert character.
+.SH SOURCE
+.B /sys/src/libcomplete
+.SH SEE ALSO
+.IR rio (1),
+.IR acme (1)
+.SH DIAGNOSTICS
+The
+.I complete
+function returns a null pointer and sets
+.I errstr
+if the directory is unreadable or there is some other error.
+.SH BUGS
+The behavior of file name completion should be controlled by the plumber.

+ 139 - 0
sys/src/libcomplete/complete.c

@@ -0,0 +1,139 @@
+#include <u.h>
+#include <libc.h>
+#include "complete.h"
+
+static int
+longestprefixlength(char *a, char *b, int n)
+{
+	int i, w;
+	Rune ra, rb;
+
+	for(i=0; i<n; i+=w){
+		w = chartorune(&ra, a);
+		chartorune(&rb, b);
+		if(ra != rb)
+			break;
+		a += w;
+		b += w;
+	}
+	return i;
+}
+
+void
+freecompletion(Completion *c)
+{
+	if(c){
+		free(c->filename);
+		free(c);
+	}
+}
+
+static int
+strpcmp(const void *va, const void *vb)
+{
+	char *a, *b;
+
+	a = *(char**)va;
+	b = *(char**)vb;
+	return strcmp(a, b);
+}
+
+Completion*
+complete(char *dir, char *s)
+{
+	long i, l, n, nmatch, len, nbytes;
+	int fd, minlen;
+	Dir *dirp;
+	char **name, *p;
+	ulong* mode;
+	Completion *c;
+
+	if(strchr(s, '/') != nil){
+		werrstr("slash character in name argument to complete()");
+		return nil;
+	}
+
+	fd = open(dir, OREAD);
+	if(fd < 0)
+		return nil;
+
+	n = dirreadall(fd, &dirp);
+	if(n <= 0)
+		return nil;
+
+	/* find longest string, for allocation */
+	len = 0;
+	for(i=0; i<n; i++){
+		l = strlen(dirp[i].name) + 1 + 1; /* +1 for /   +1 for \0 */
+		if(l > len)
+			len = l;
+	}
+
+	name = malloc(n*sizeof(char*));
+	mode = malloc(n*sizeof(ulong));
+	c = malloc(sizeof(Completion) + len);
+	if(name == nil || mode == nil || c == nil)
+		goto Return;
+	memset(c, 0, sizeof(Completion));
+
+	/* find the matches */
+	len = strlen(s);
+	nmatch = 0;
+	minlen = 1000000;
+	for(i=0; i<n; i++)
+		if(strncmp(s, dirp[i].name, len) == 0){
+			name[nmatch] = dirp[i].name;
+			mode[nmatch] = dirp[i].mode;
+			if(minlen > strlen(dirp[i].name))
+				minlen = strlen(dirp[i].name);
+			nmatch++;
+		}
+
+	if(nmatch > 0) {
+		/* report interesting results */
+		/* trim length back to longest common initial string */
+		for(i=1; i<nmatch; i++)
+			minlen = longestprefixlength(name[0], name[i], minlen);
+
+		/* build the answer */
+		c->complete = (nmatch == 1);
+		c->advance = c->complete || (minlen > len);
+		c->string = (char*)(c+1);
+		memmove(c->string, name[0]+len, minlen-len);
+		if(c->complete)
+			c->string[minlen++ - len] = (mode[0]&DMDIR)? '/' : ' ';
+		c->string[minlen - len] = '\0';
+	} else {
+		/* no match, so return all possible strings */
+		for(i=0; i<n; i++){
+			name[i] = dirp[i].name;
+			mode[i] = dirp[i].mode;
+		}
+		nmatch = n;
+	}
+
+	/* attach list of names */
+	nbytes = nmatch * sizeof(char*);
+	for(i=0; i<nmatch; i++)
+		nbytes += strlen(name[i]) + 1 + 1;
+	c->filename = malloc(nbytes);
+	if(c->filename == nil)
+		goto Return;
+	p = (char*)(c->filename + nmatch);
+	for(i=0; i<nmatch; i++){
+		c->filename[i] = p;
+		strcpy(p, name[i]);
+		p += strlen(p);
+		if(mode[i] & DMDIR)
+			*p++ = '/';
+		*p++ = '\0';
+	}
+	c->nfile = nmatch;
+	qsort(c->filename, c->nfile, sizeof(c->filename[0]), strpcmp);
+
+  Return:
+	free(name);
+	free(mode);
+	free(dirp);
+	return c;
+}

+ 15 - 0
sys/src/libcomplete/mkfile

@@ -0,0 +1,15 @@
+</$objtype/mkfile
+
+LIB=/$objtype/lib/libcomplete.a
+OFILES=\
+	complete.$O\
+
+HFILES=/sys/include/complete.h
+
+UPDATE=\
+	mkfile\
+	$HFILES\
+	${OFILES:%.$O=%.c}\
+	${LIB:/$objtype/%=/386/%}\
+
+</sys/src/cmd/mksyslib