xref: /inferno-os/appl/cmd/fs.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Fs;
2include "sys.m";
3	sys: Sys;
4include "draw.m";
5include "sh.m";
6include "readdir.m";
7include "fslib.m";
8	fslib: Fslib;
9	Report, Value, type2s: import fslib;
10	Fschan, Fsdata, Entrychan, Entry,
11	Quit: import Fslib;
12
13# fs distribution:
14
15# {filter -d {not {match -r '\.(dis|sbl)$'}} {filter {path /module/fslib.m /module/bundle.m /module/unbundle.m /appl/cmd/fs.b /appl/cmd/fs /appl/lib/fslib.b} /}}
16
17Fs: module {
18	init: fn(nil: ref Draw->Context, argv: list of string);
19};
20
21badmod(path: string)
22{
23	sys->fprint(stderr(), "fs: cannot load %s: %r\n", path);
24	raise "fail:bad module";
25}
26
27init(ctxt: ref Draw->Context, argv: list of string)
28{
29	sys = load Sys Sys->PATH;
30	fslib = load Fslib Fslib->PATH;
31	if(fslib == nil)
32		badmod(Fslib->PATH);
33	fslib->init();
34	argv = tl argv;
35
36	if(argv == nil)
37		usage();
38	report := Report.new();
39	s := hd argv;
40	if(tl argv == nil && s != nil && s[0] == '{' && s[len s - 1] == '}')
41		s = "void " + hd argv;
42	else {
43		s = "void {" + hd argv;
44		for(argv = tl argv; argv != nil; argv = tl argv){
45			a := hd argv;
46			if(a == nil || a[0] != '{')		# }
47				s += sys->sprint(" %q", a);
48			else
49				s += " " + hd argv;
50		}
51		s += "}";
52	}
53	m := load Fsmodule "/dis/fs/eval.dis";
54	if(m == nil)
55		badmod("/dis/fs/eval.dis");
56	if(!fslib->typecompat("as", m->types())){
57		sys->fprint(stderr(), "fs: eval module implements incompatible type (usage: %s)\n",
58				fslib->cmdusage("eval", m->types()));
59		raise "fail:bad eval module";
60	}
61	m->init();
62	v := m->run(ctxt, report, nil, ref Value.S(s) :: nil);
63	fail: string;
64	if(v == nil)
65		fail = "error";
66	else{
67		sync := v.v().i;
68		sync <-= 1;
69	}
70	report.enable();
71	while((e := <-report.reportc) != nil)
72		sys->fprint(stderr(), "fs: %s\n", e);
73	if(fail != nil)
74		raise "fail:" +fail;
75}
76
77usage()
78{
79	fd := stderr();
80	sys->fprint(fd, "usage: fs expression\n");
81	sys->fprint(fd, "verbs are:\n");
82	if((readdir := load Readdir Readdir->PATH) == nil){
83		sys->fprint(fd, "fs: cannot load %s: %r\n", Readdir->PATH);
84	}else{
85		(a, nil) := readdir->init("/dis/fs", Readdir->NAME|Readdir->COMPACT);
86		for(i := 0; i < len a; i++){
87			f := a[i].name;
88			if(len f < 4 || f[len f - 4:] != ".dis")
89				continue;
90			m := load Fsmodule "/dis/fs/" + f;
91			if(m == nil)
92				sys->fprint(fd, "\t(%s: cannot load: %r)\n", f[0:len f - 4]);
93			else
94				sys->fprint(fd, "\t%s\n", fslib->cmdusage(f[0:len f - 4], m->types()));
95		}
96	}
97	sys->fprint(fd, "automatic conversions:\n");
98	sys->fprint(fd, "\tstring -> fs {walk string}\n");
99	sys->fprint(fd, "\tfs -> entries {entries fs}\n");
100	sys->fprint(fd, "\tstring -> gate {match string}\n");
101	sys->fprint(fd, "\tentries -> void {print entries}\n");
102	sys->fprint(fd, "\tcommand -> string {run command}\n");
103	raise "fail:usage";
104}
105
106stderr(): ref Sys->FD
107{
108	return sys->fildes(2);
109}
110