[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Useful program: mc

This little limbo program is the first one I wrote.  Since ls doesn't 
multi-column-ize its output, I decided it would be nice to have somthing to do 
this.  This is probably not a good example of how to write limbo code since 
I'm still learning it but it may be useful.

THings left to do are flags to set the line width and tab space interval, 
currently hard-coded at 60 and 16 respectively.  This puts 4 files on a line, 
which is better than scrolling out of the window.  I was going to have it 
automagically determine the current line width but that turns out to be 
difficult, if not impossible.

Oh, and I am assured that as long as there is sufficient "new" code posting 
stuff here is OK.  I glommed the argv-loop from appl/cmd/cat.b.

implement Mc;

## Print input (stdin or files named in argv) in multiple columns.
##  -- Berry Kercheval, Xerox PARC

##  There standeth Minos horribly, and snarls;
## Examines the transgressions at the entrance;
## Judges, and sends according as he girds him.

##  I say, that when the spirit evil-born
## Cometh before him, wholly it confesses;
## And this discriminator of transgressions

##  Seeth what place in Hell is meet for it;
## Girds himself with his tail as many times
## As grades he wishes it should be thrust down.

##  Always before him many of them stand;
## They go by turns each one unto the judgment;
## They speak, and hear, and then are downward hurled.

##   -- Inferno, Canto V

include "sys.m";
	sys: Sys;
	utfbytes, FD: import Sys;
include "draw.m";
	draw: Draw;
include "bufio.m";
	bufio: Bufio;
	Iobuf: import bufio;

stderr, stdout: ref FD;

DEFWIDTH: con 60;
TABSPACE: con 16;

Mc: module
	init:	fn(ctxt: ref Draw->Context, argv: list of string);

init(ctxt: ref Draw->Context, argv: list of string)
	sys   = load Sys   Sys->PATH;
	draw  = load Draw  Draw->PATH;
	bufio = load Bufio Bufio->PATH;

	stdout = sys->fildes(1);
	stderr = sys->fildes(2);
	argv = tl argv;	
		# skip program name
	if(argv == nil)
		argv = "-" :: nil;  	# fake up list for just stdin
	while(argv != nil) {		# more args?
		process(hd argv);	# process head of list
		argv = tl argv;		# cdr down list to next arg

process( file: string)
	# Process a file (or stding, if file == "-") and print it's contents on
	# stdout in multiple columns.  This routine attempts to do the right thing
	# for utf by counting utf characters instead of blindly accepting
	# the byte count as equivalent to the number of spaces taken by the string.

	n: int;				# bytes in the string
	fd: ref Iobuf;			# what we read from
	s: string;			# string read from file
	buf := array[8192] of byte;	# byte array version of string since 
					# utfbytes wants that.
	width := DEFWIDTH;		# width of output line
	cur:= 0;			# where are we now?
	outline: string;

	if(file == "-")	
		fd = bufio->fopen(sys->fildes(0), sys->OREAD);
	else {
		fd = bufio->open(file, sys->OREAD);
		if(fd == nil) {
			sys->fprint(stderr, "mc: %s: %r\n", file);
	outline = "";
	for(;;) {
		s = fd.gets('\n');
		buf= array of byte s;
		n = len s;
		if (n==0) break;
		l := sys->utfbytes(buf, n);
		if ( cur + l > width ) {
			sys->print("%s\n", outline);
			outline = "";
			cur = 0;
		cur += l;
		outline += string buf[0:n-1] + " ";
		while(cur%TABSPACE) {
			outline += " ";
	sys->print("%s\n", outline);

Berry Kercheval :: kerch@parc.xerox.com :: Xerox Palo Alto Research Center