code: 9ferno

ref: 6d69f6fba35087686f79adb2ea0d67944a62ca7b
dir: /appl/lib/fsfilter.b/

View raw version
implement Fsfilter;

#
# Copyright © 2004 Vita Nuova Holdings Limited
#

include "sys.m";
include "draw.m";
include "sh.m";
include "fslib.m";
	Fschan, Next, Quit, Skip, Down: import Fslib;

filter[T](t: T, src, dst: Fschan)
	for{
	T =>
		query: fn(t: self T, d: ref Sys->Dir, name: string, depth: int): int;
	}
{
	names: list of string;
	name: string;
	indent := 0;
	myreply := chan of int;
loop:
	for(;;){
		(d, reply) := <-src;
		if(d.dir != nil){
			p := name;
			if(indent > 0){
				if(p != nil && p[len p - 1] != '/')
					p[len p] = '/';
			}
			if(t.query(d.dir, p + d.dir.name, indent) == 0 && indent > 0){
				reply <-= Next;
				continue;
			}
		}
		dst <-= (d, myreply);
		case reply <-= <-myreply {
		Quit =>
			break loop;
		Next =>
			if(d.dir == nil && d.data == nil){
				if(--indent == 0)
					break loop;
				(name, names) = (hd names, tl names);
			}
		Skip =>
			if(--indent == 0)
				break loop;
			(name, names) = (hd names, tl names);
		Down =>
			if(d.dir != nil){
				names = name :: names;
				if(d.dir.mode & Sys->DMDIR){
					if(indent == 0)
						name = d.dir.name;
					else{
						if(name[len name - 1] != '/')
							name[len name] = '/';
						name += d.dir.name;
					}
				}
				indent++;
			}
		}
	}
}