summaryrefslogtreecommitdiff
path: root/appl/cmd/lc.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/lc.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/lc.b')
-rw-r--r--appl/cmd/lc.b156
1 files changed, 156 insertions, 0 deletions
diff --git a/appl/cmd/lc.b b/appl/cmd/lc.b
new file mode 100644
index 00000000..de5ec579
--- /dev/null
+++ b/appl/cmd/lc.b
@@ -0,0 +1,156 @@
+implement Lc;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+include "readdir.m";
+ readdir: Readdir;
+include "bufio.m";
+ bufio: Bufio;
+ Iobuf: import bufio;
+
+Lc: module {
+ init: fn(nil: ref Draw->Context, argv: list of string);
+};
+
+t_FILE, t_DIR, t_NUMTYPES: con iota;
+columns := 65;
+stderr: ref Sys->FD;
+stdout: ref Iobuf;
+
+usage()
+{
+ sys->fprint(stderr, "usage: lc [-df] [-c columns] [file ...]\n");
+ raise "fail:usage";
+}
+
+init(nil: ref Draw->Context, argv: list of string)
+{
+ sys = load Sys Sys->PATH;
+ stderr = sys->fildes(2);
+ readdir = load Readdir Readdir->PATH;
+ if (readdir == nil) {
+ sys->fprint(stderr, "lc: cannot load %s: %r\n", Readdir->PATH);
+ raise "fail:bad module";
+ }
+ bufio = load Bufio Bufio->PATH;
+ stdout = bufio->fopen(sys->fildes(1), Sys->OWRITE);
+ if (bufio == nil) {
+ sys->fprint(stderr, "lc: cannot load %s: %r\n", Bufio->PATH);
+ raise "fail:bad module";
+ }
+ if (argv == nil)
+ return;
+ argv = tl argv;
+ flags := 0;
+loop: while (argv != nil && hd argv != nil && (hd argv)[0] == '-') {
+ s := (hd argv)[1:];
+ argv = tl argv;
+ flagloop: for (; s != nil; s = s[1:]) {
+ case s[0] {
+ '-' =>
+ break loop;
+ 'd' =>
+ flags |= 1 << t_DIR;
+ 'f' =>
+ flags |= 1 << t_FILE;
+ 'c' =>
+ if (len s > 1) {
+ columns = int s[1:];
+ break flagloop;
+ }
+ if (argv == nil)
+ usage();
+ columns = int hd argv;
+ argv = tl argv;
+ * =>
+ usage();
+ }
+ }
+ }
+
+ headings := 0;
+ if (flags == 0) {
+ flags = (1<<t_DIR)|(1<<t_FILE);
+ headings = 1;
+ }
+ if (argv == nil)
+ argv = "." :: nil;
+ multi := tl argv != nil;
+ nondir: list of string;
+ for (; argv != nil; argv = tl argv) {
+ dname := hd argv;
+ (ok, dir) := sys->stat(dname);
+ if(ok < 0) {
+ sys->fprint(stderr, "lc: can't stat %s: %r\n", hd argv);
+ continue;
+ }
+ if (dir.mode & Sys->DMDIR) {
+ (d, n) := readdir->init(hd argv, Readdir->NAME | Readdir->COMPACT);
+ if (n < 0)
+ sys->fprint(stderr, "lc: cannot read %s: %r\n", hd argv);
+ else {
+ indent := 0;
+ if (multi && headings) {
+ stdout.puts(hd argv + "/\n");
+ indent = 2;
+ }
+ l: list of string = nil;
+ for (i := 0; i < n; i++) {
+ s := d[i].name;
+ if (!headings && dname != ".")
+ s = dname + "/" + s;
+ if (d[i].mode & Sys->DMDIR) {
+ if (flags & (1<<t_DIR))
+ l = s + "/" :: l;
+ } else if (flags & (1<<t_FILE))
+ l = s :: l;
+ }
+ d = nil;
+ lc(l, indent);
+ }
+ } else if (flags & (1 << t_FILE))
+ nondir = dname :: nondir;
+ }
+ lc(nondir, 0);
+ stdout.close();
+}
+
+lc(dl: list of string, indent: int)
+{
+ a := array[len dl] of string;
+ j := len a - 1;
+ maxwidth := 0;
+ for (; dl != nil; dl = tl dl) {
+ s := hd dl;
+ a[j--] = s;
+ if (len s > maxwidth)
+ maxwidth = len s;
+ }
+ outcols(a, maxwidth, indent);
+}
+
+outcols(stuff: array of string, maxwidth, indent: int)
+{
+ num := len stuff;
+ cols := columns - indent;
+ numcols := cols / (maxwidth + 1);
+ colwidth: int;
+ if (numcols == 0) {
+ numcols = 1;
+ colwidth = maxwidth;
+ } else
+ colwidth = cols / numcols;
+ numrows := (num + numcols - 1) / numcols;
+
+ for (i := 0; i < numrows; i++) {
+ if (indent)
+ stdout.puts(sys->sprint("%*s", indent, ""));
+ for (j := i; j < num; j += numrows) {
+ if (j + numrows < num)
+ stdout.puts(sys->sprint("%*.*s", -colwidth, colwidth, stuff[j]));
+ else
+ stdout.puts(sys->sprint("%.*s\n", colwidth, stuff[j]));
+ }
+ }
+}