xref: /inferno-os/appl/cmd/mc.b (revision 9f620229775d41f76096d9039c46ff368fd44d47)
10d13e2d8SCharles.Forsythimplement Mc;
237da2899SCharles.Forsyth
337da2899SCharles.Forsythinclude "sys.m";
437da2899SCharles.Forsyth	sys: Sys;
50d13e2d8SCharles.Forsyth	open, read, fprint, fildes, tokenize,
60d13e2d8SCharles.Forsyth	ORDWR, OREAD, OWRITE: import sys;
737da2899SCharles.Forsythinclude "draw.m";
80d13e2d8SCharles.Forsyth	draw: Draw;
90d13e2d8SCharles.Forsyth	Font: import draw;
1037da2899SCharles.Forsythinclude "bufio.m";
1137da2899SCharles.Forsyth	bufio: Bufio;
1237da2899SCharles.Forsyth	Iobuf: import bufio;
130d13e2d8SCharles.Forsythinclude "arg.m";
1437da2899SCharles.Forsyth
150d13e2d8SCharles.Forsythfont: ref Font;
160d13e2d8SCharles.Forsythcolumns := 65;
170d13e2d8SCharles.Forsythtabwid := 0;
180d13e2d8SCharles.Forsythmintab := 1;
190d13e2d8SCharles.Forsyth
200d13e2d8SCharles.ForsythMc: module{
2137da2899SCharles.Forsyth	init: fn(nil: ref Draw->Context, argv: list of string);
2237da2899SCharles.Forsyth};
2337da2899SCharles.Forsyth
240d13e2d8SCharles.Forsythinit(ctxt: ref Draw->Context, argv: list of string)
2537da2899SCharles.Forsyth{
2637da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
270d13e2d8SCharles.Forsyth	if((bufio = load Bufio Bufio->PATH) == nil)
280d13e2d8SCharles.Forsyth		fatal("can't load " + Bufio->PATH);
29*9f620229SCharles.Forsyth	draw = load Draw Draw->PATH;
300d13e2d8SCharles.Forsyth	if((arg := load Arg Arg->PATH) == nil)
310d13e2d8SCharles.Forsyth		fatal("can't load " + Arg->PATH);
3237da2899SCharles.Forsyth
330d13e2d8SCharles.Forsyth	getwidth(ctxt);
340d13e2d8SCharles.Forsyth	arg->init(argv);
350d13e2d8SCharles.Forsyth	arg->setusage("mc [-c columns] [file ...]");
360d13e2d8SCharles.Forsyth	while((c:=arg->opt()) != 0)
370d13e2d8SCharles.Forsyth		case c {
380d13e2d8SCharles.Forsyth		'c' =>	columns = int arg->earg() * mintab;
390d13e2d8SCharles.Forsyth		* =>		arg->usage();
400d13e2d8SCharles.Forsyth		}
410d13e2d8SCharles.Forsyth	argv = arg->argv();
420d13e2d8SCharles.Forsyth	if(len argv == 0)
430d13e2d8SCharles.Forsyth		argv = "/fd/0" :: nil;
4437da2899SCharles.Forsyth
450d13e2d8SCharles.Forsyth	a := array[1024] of (string, int);
460d13e2d8SCharles.Forsyth	n := 0;
470d13e2d8SCharles.Forsyth	maxwidth := 0;
480d13e2d8SCharles.Forsyth	for(; argv!=nil; argv=tl argv){
490d13e2d8SCharles.Forsyth		if((bin:=bufio->open(hd argv, OREAD)) == nil){
500d13e2d8SCharles.Forsyth			fprint(fildes(2), "mc: can't open %s: %r\n", hd argv);
510d13e2d8SCharles.Forsyth			continue;
5237da2899SCharles.Forsyth		}
530d13e2d8SCharles.Forsyth		while((s:=bin.gets('\n')) != nil){
540d13e2d8SCharles.Forsyth			if(s[len s-1] == '\n')
550d13e2d8SCharles.Forsyth				s = s[0:len s-1];
560d13e2d8SCharles.Forsyth			if(n == len a)
570d13e2d8SCharles.Forsyth				a = (array[n+1024] of (string, int))[0:] = a;
580d13e2d8SCharles.Forsyth			a[n].t0 = s;
590d13e2d8SCharles.Forsyth			a[n].t1 = wordsize(s);
600d13e2d8SCharles.Forsyth			if(a[n].t1 > maxwidth)
610d13e2d8SCharles.Forsyth				maxwidth = a[n].t1;
620d13e2d8SCharles.Forsyth			n++;
6337da2899SCharles.Forsyth		}
640d13e2d8SCharles.Forsyth		bin.close();
6537da2899SCharles.Forsyth	}
660d13e2d8SCharles.Forsyth	outcols(a[:n], maxwidth);
6737da2899SCharles.Forsyth}
6837da2899SCharles.Forsyth
690d13e2d8SCharles.Forsythoutcols(words: array of (string, int), maxwidth: int)
7037da2899SCharles.Forsyth{
710d13e2d8SCharles.Forsyth	maxwidth = nexttab(maxwidth+mintab-1);
720d13e2d8SCharles.Forsyth	numcols := columns / maxwidth;
730d13e2d8SCharles.Forsyth	if(numcols <= 0)
740d13e2d8SCharles.Forsyth		numcols = 1;
750d13e2d8SCharles.Forsyth	nwords := len words;
760d13e2d8SCharles.Forsyth	nlines := (nwords+numcols-1) / numcols;
770d13e2d8SCharles.Forsyth	bout := bufio->fopen(fildes(1), OWRITE);
780d13e2d8SCharles.Forsyth	for(i := 0; i < nlines; i++){
790d13e2d8SCharles.Forsyth		col := endcol := 0;
800d13e2d8SCharles.Forsyth		for(j:=i; j<nwords; j+=nlines){
810d13e2d8SCharles.Forsyth			endcol += maxwidth;
820d13e2d8SCharles.Forsyth			bout.puts(words[j].t0);
830d13e2d8SCharles.Forsyth			col += words[j].t1;
840d13e2d8SCharles.Forsyth			if(j+nlines < nwords){
850d13e2d8SCharles.Forsyth				while(col < endcol){
860d13e2d8SCharles.Forsyth					if(tabwid)
870d13e2d8SCharles.Forsyth						bout.putc('\t');
8837da2899SCharles.Forsyth					else
890d13e2d8SCharles.Forsyth						bout.putc(' ');
900d13e2d8SCharles.Forsyth					col = nexttab(col);
910d13e2d8SCharles.Forsyth				}
920d13e2d8SCharles.Forsyth			}
930d13e2d8SCharles.Forsyth		}
940d13e2d8SCharles.Forsyth		bout.putc('\n');
950d13e2d8SCharles.Forsyth	}
960d13e2d8SCharles.Forsyth	bout.close();
970d13e2d8SCharles.Forsyth}
980d13e2d8SCharles.Forsyth
990d13e2d8SCharles.Forsythwordsize(s: string): int
1000d13e2d8SCharles.Forsyth{
1010d13e2d8SCharles.Forsyth	if(font != nil)
1020d13e2d8SCharles.Forsyth		return font.width(s);
1030d13e2d8SCharles.Forsyth	return len s;
1040d13e2d8SCharles.Forsyth}
1050d13e2d8SCharles.Forsyth
1060d13e2d8SCharles.Forsythnexttab(col: int): int
1070d13e2d8SCharles.Forsyth{
1080d13e2d8SCharles.Forsyth	if(tabwid){
1090d13e2d8SCharles.Forsyth		col += tabwid;
1100d13e2d8SCharles.Forsyth		col -= col%tabwid;
1110d13e2d8SCharles.Forsyth		return col;
1120d13e2d8SCharles.Forsyth	}
1130d13e2d8SCharles.Forsyth	return col+1;
1140d13e2d8SCharles.Forsyth}
1150d13e2d8SCharles.Forsyth
1160d13e2d8SCharles.Forsythgetwidth(ctxt: ref Draw->Context)
1170d13e2d8SCharles.Forsyth{
118*9f620229SCharles.Forsyth	if(ctxt == nil || draw == nil)
119*9f620229SCharles.Forsyth		return;
120*9f620229SCharles.Forsyth	if((wid := rf("/env/acmewin")) == nil)
1210d13e2d8SCharles.Forsyth		return;
1220d13e2d8SCharles.Forsyth	if((fd := open("/chan/" + wid + "/ctl", ORDWR)) == nil)
1230d13e2d8SCharles.Forsyth		return;
1240d13e2d8SCharles.Forsyth	buf := array[256] of byte;
1250d13e2d8SCharles.Forsyth	if((n := read(fd, buf, len buf)) <= 0)
1260d13e2d8SCharles.Forsyth		return;
1270d13e2d8SCharles.Forsyth	(nf, f) := tokenize(string buf[:n], " ");
1280d13e2d8SCharles.Forsyth	if(nf != 8)
1290d13e2d8SCharles.Forsyth		return;
1300d13e2d8SCharles.Forsyth	f0 := tl tl tl tl tl f;
1310d13e2d8SCharles.Forsyth	if((font = Font.open(ctxt.display, hd tl f0)) == nil)
1320d13e2d8SCharles.Forsyth		return;
1330d13e2d8SCharles.Forsyth	tabwid = int hd tl tl f0;
1340d13e2d8SCharles.Forsyth	mintab = font.width("0");
1350d13e2d8SCharles.Forsyth	columns = int hd f0;
13637da2899SCharles.Forsyth}
13737da2899SCharles.Forsyth
13837da2899SCharles.Forsythfatal(s: string)
13937da2899SCharles.Forsyth{
1400d13e2d8SCharles.Forsyth	fprint(fildes(2), "mc: %s: %r\n", s);
1410d13e2d8SCharles.Forsyth	raise "fail:"+s;
14237da2899SCharles.Forsyth}
143*9f620229SCharles.Forsyth
144*9f620229SCharles.Forsythrf(f: string): string
145*9f620229SCharles.Forsyth{
146*9f620229SCharles.Forsyth	fd := sys->open(f, Sys->OREAD);
147*9f620229SCharles.Forsyth	if(fd == nil)
148*9f620229SCharles.Forsyth		return nil;
149*9f620229SCharles.Forsyth	b := array[Sys->NAMEMAX] of byte;
150*9f620229SCharles.Forsyth	n := sys->read(fd, b, len b);
151*9f620229SCharles.Forsyth	if(n < 0)
152*9f620229SCharles.Forsyth		return nil;
153*9f620229SCharles.Forsyth	return string b[0:n];
154*9f620229SCharles.Forsyth}
155