xref: /inferno-os/appl/cmd/tkcmd.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Tkcmd;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsyth	stderr: ref Sys->FD;
6*37da2899SCharles.Forsythinclude "draw.m";
7*37da2899SCharles.Forsyth	draw: Draw;
8*37da2899SCharles.Forsyth	Display, Image, Point: import draw;
9*37da2899SCharles.Forsythinclude "tk.m";
10*37da2899SCharles.Forsyth	tk: Tk;
11*37da2899SCharles.Forsythinclude "tkclient.m";
12*37da2899SCharles.Forsyth	tkclient: Tkclient;
13*37da2899SCharles.Forsythinclude "bufio.m";
14*37da2899SCharles.Forsythinclude "arg.m";
15*37da2899SCharles.Forsyth
16*37da2899SCharles.ForsythTkcmd : module {
17*37da2899SCharles.Forsyth	init:	fn(ctxt: ref Draw->Context, argv: list of string);
18*37da2899SCharles.Forsyth};
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsythusage()
21*37da2899SCharles.Forsyth{
22*37da2899SCharles.Forsyth	sys->print("usage: tkcmd [-iu] [toplevelarg]\n");
23*37da2899SCharles.Forsyth	raise "fail:usage";
24*37da2899SCharles.Forsyth}
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsythbadmodule(m: string)
27*37da2899SCharles.Forsyth{
28*37da2899SCharles.Forsyth		sys->fprint(stderr, "tkcmd: cannot load %s: %r\n", m);
29*37da2899SCharles.Forsyth		raise "fail:bad module";
30*37da2899SCharles.Forsyth}
31*37da2899SCharles.Forsyth
32*37da2899SCharles.Forsythinit(ctxt: ref Draw->Context, argv: list of string)
33*37da2899SCharles.Forsyth{
34*37da2899SCharles.Forsyth	sys  = load Sys  Sys->PATH;
35*37da2899SCharles.Forsyth	stderr = sys->fildes(2);
36*37da2899SCharles.Forsyth	draw = load Draw Draw->PATH;
37*37da2899SCharles.Forsyth	tk = load Tk   Tk->PATH;
38*37da2899SCharles.Forsyth	if (tk == nil)
39*37da2899SCharles.Forsyth		badmodule(Tk->PATH);
40*37da2899SCharles.Forsyth	tkclient = load Tkclient Tkclient->PATH;
41*37da2899SCharles.Forsyth	if (tkclient==nil)
42*37da2899SCharles.Forsyth		badmodule(Tkclient->PATH);
43*37da2899SCharles.Forsyth	arg := load Arg Arg->PATH;
44*37da2899SCharles.Forsyth	if (arg == nil)
45*37da2899SCharles.Forsyth		badmodule(Arg->PATH);
46*37da2899SCharles.Forsyth
47*37da2899SCharles.Forsyth	arg->init(argv);
48*37da2899SCharles.Forsyth	update := 1;
49*37da2899SCharles.Forsyth	interactive := isconsole(sys->fildes(0));
50*37da2899SCharles.Forsyth	while ((opt := arg->opt()) != 0) {
51*37da2899SCharles.Forsyth		case opt {
52*37da2899SCharles.Forsyth		'i' =>
53*37da2899SCharles.Forsyth			interactive = 1;
54*37da2899SCharles.Forsyth		'u' =>
55*37da2899SCharles.Forsyth			update = 0;
56*37da2899SCharles.Forsyth		* =>
57*37da2899SCharles.Forsyth			usage();
58*37da2899SCharles.Forsyth		}
59*37da2899SCharles.Forsyth	}
60*37da2899SCharles.Forsyth	argv = arg->argv();
61*37da2899SCharles.Forsyth	arg = nil;
62*37da2899SCharles.Forsyth	tkarg := "";
63*37da2899SCharles.Forsyth	if (argv != nil) {
64*37da2899SCharles.Forsyth		if (tl argv != nil)
65*37da2899SCharles.Forsyth			usage();
66*37da2899SCharles.Forsyth		tkarg = hd argv;
67*37da2899SCharles.Forsyth	}
68*37da2899SCharles.Forsyth
69*37da2899SCharles.Forsyth	sys->pctl(Sys->NEWPGRP, nil);
70*37da2899SCharles.Forsyth	tkclient->init();
71*37da2899SCharles.Forsyth	shellit(ctxt, tkarg, interactive, update);
72*37da2899SCharles.Forsyth}
73*37da2899SCharles.Forsyth
74*37da2899SCharles.Forsythisconsole(fd: ref Sys->FD): int
75*37da2899SCharles.Forsyth{
76*37da2899SCharles.Forsyth	(ok1, d1) := sys->fstat(fd);
77*37da2899SCharles.Forsyth	(ok2, d2) := sys->stat("/dev/cons");
78*37da2899SCharles.Forsyth	if (ok1 < 0 || ok2 < 0)
79*37da2899SCharles.Forsyth		return 0;
80*37da2899SCharles.Forsyth	return d1.dtype == d2.dtype && d1.qid.path == d2.qid.path;
81*37da2899SCharles.Forsyth}
82*37da2899SCharles.Forsyth
83*37da2899SCharles.Forsythshellit(ctxt: ref Draw->Context, arg: string, interactive, update: int)
84*37da2899SCharles.Forsyth{
85*37da2899SCharles.Forsyth	(Wwsh, winctl) := tkclient->toplevel(ctxt, arg, "Tk", Tkclient->Appl);
86*37da2899SCharles.Forsyth	tkclient->onscreen(Wwsh, nil);
87*37da2899SCharles.Forsyth	tkclient->startinput(Wwsh, "ptr" :: "kbd" :: nil);
88*37da2899SCharles.Forsyth	wm := Wwsh.ctxt;
89*37da2899SCharles.Forsyth	if(update)
90*37da2899SCharles.Forsyth		tk->cmd(Wwsh, "update");
91*37da2899SCharles.Forsyth	ps1 := "";
92*37da2899SCharles.Forsyth	ps2 := "";
93*37da2899SCharles.Forsyth	if (!interactive)
94*37da2899SCharles.Forsyth		ps1 = ps2 = "";
95*37da2899SCharles.Forsyth
96*37da2899SCharles.Forsyth	lines := chan of string;
97*37da2899SCharles.Forsyth	sync := chan of int;
98*37da2899SCharles.Forsyth	spawn grab_lines(ps1, ps2, lines, sync);
99*37da2899SCharles.Forsyth	output := chan of string;
100*37da2899SCharles.Forsyth	tk->namechan(Wwsh, output, "stdout");
101*37da2899SCharles.Forsyth	pid := <-sync;
102*37da2899SCharles.ForsythLoop:
103*37da2899SCharles.Forsyth	for(;;) alt {
104*37da2899SCharles.Forsyth	c := <-wm.kbd =>
105*37da2899SCharles.Forsyth		tk->keyboard(Wwsh, c);
106*37da2899SCharles.Forsyth	m := <-wm.ptr =>
107*37da2899SCharles.Forsyth		tk->pointer(Wwsh, *m);
108*37da2899SCharles.Forsyth	c := <-wm.ctl or
109*37da2899SCharles.Forsyth	c = <-Wwsh.wreq =>
110*37da2899SCharles.Forsyth		tkclient->wmctl(Wwsh, c);
111*37da2899SCharles.Forsyth	line := <-lines =>
112*37da2899SCharles.Forsyth		if (line == nil)
113*37da2899SCharles.Forsyth			break Loop;
114*37da2899SCharles.Forsyth		if (line[0] == '#')
115*37da2899SCharles.Forsyth			break;
116*37da2899SCharles.Forsyth		line = line[0:len line - 1];
117*37da2899SCharles.Forsyth		result := tk->cmd(Wwsh, line);
118*37da2899SCharles.Forsyth		if (result != nil)
119*37da2899SCharles.Forsyth			sys->print("#%s\n", result);
120*37da2899SCharles.Forsyth		if (update)
121*37da2899SCharles.Forsyth			tk->cmd(Wwsh, "update");
122*37da2899SCharles.Forsyth		sys->print("%s", ps1);
123*37da2899SCharles.Forsyth	menu := <-winctl =>
124*37da2899SCharles.Forsyth		tkclient->wmctl(Wwsh, menu);
125*37da2899SCharles.Forsyth	s := <-output =>
126*37da2899SCharles.Forsyth		sys->print("#<stdout>%s\n", s);
127*37da2899SCharles.Forsyth		sys->print("%s", ps1);
128*37da2899SCharles.Forsyth	}
129*37da2899SCharles.Forsyth}
130*37da2899SCharles.Forsyth
131*37da2899SCharles.Forsythgrab_lines(new_inp, unfin: string, lines: chan of string, sync: chan of int)
132*37da2899SCharles.Forsyth{
133*37da2899SCharles.Forsyth	sync <-= sys->pctl(0, nil);
134*37da2899SCharles.Forsyth	{
135*37da2899SCharles.Forsyth		bufmod := load Bufio Bufio->PATH;
136*37da2899SCharles.Forsyth		Iobuf:	import bufmod;
137*37da2899SCharles.Forsyth		if (bufmod == nil) {
138*37da2899SCharles.Forsyth			lines <-= nil;
139*37da2899SCharles.Forsyth			return;
140*37da2899SCharles.Forsyth		}
141*37da2899SCharles.Forsyth		sys->print("%s", new_inp);
142*37da2899SCharles.Forsyth		iob := bufmod->fopen(sys->fildes(0),bufmod->OREAD);
143*37da2899SCharles.Forsyth		if (iob==nil){
144*37da2899SCharles.Forsyth			sys->fprint(stderr, "tkcmd: cannot open stdin for reading.\n");
145*37da2899SCharles.Forsyth			lines <-= nil;
146*37da2899SCharles.Forsyth			return;
147*37da2899SCharles.Forsyth		}
148*37da2899SCharles.Forsyth		line := "";
149*37da2899SCharles.Forsyth		while((input := iob.gets('\n')) != nil) {
150*37da2899SCharles.Forsyth			line+=input;
151*37da2899SCharles.Forsyth			if (!finished(line,0))
152*37da2899SCharles.Forsyth				sys->print("%s", unfin);
153*37da2899SCharles.Forsyth			else{
154*37da2899SCharles.Forsyth				lines <-= line;
155*37da2899SCharles.Forsyth				line=nil;
156*37da2899SCharles.Forsyth			}
157*37da2899SCharles.Forsyth		}
158*37da2899SCharles.Forsyth		lines <-= nil;
159*37da2899SCharles.Forsyth	}exception e{
160*37da2899SCharles.Forsyth	"*" =>
161*37da2899SCharles.Forsyth		sys->fprint(stderr, "tkcmd: fail: %s\n", e);
162*37da2899SCharles.Forsyth		lines <-= nil;
163*37da2899SCharles.Forsyth	}
164*37da2899SCharles.Forsyth}
165*37da2899SCharles.Forsyth
166*37da2899SCharles.Forsyth# returns 1 if the line has matching braces, brackets and
167*37da2899SCharles.Forsyth# double-quotes and does not end in "\\\n"
168*37da2899SCharles.Forsythfinished(s : string, termchar : int) : int {
169*37da2899SCharles.Forsyth	cb:=0;
170*37da2899SCharles.Forsyth	dq:=0;
171*37da2899SCharles.Forsyth	sb:=0;
172*37da2899SCharles.Forsyth	if (s==nil) return 1;
173*37da2899SCharles.Forsyth	if (termchar=='}') cb++;
174*37da2899SCharles.Forsyth	if (termchar==']') sb++;
175*37da2899SCharles.Forsyth	if (len s > 1 && s[len s -2]=='\\')
176*37da2899SCharles.Forsyth		return 0;
177*37da2899SCharles.Forsyth	if (s[0]=='{') cb++;
178*37da2899SCharles.Forsyth	if (s[0]=='}' && cb>0) cb--;
179*37da2899SCharles.Forsyth	if (s[0]=='[') sb++;
180*37da2899SCharles.Forsyth	if (s[0]==']' && sb>0) sb--;
181*37da2899SCharles.Forsyth	if (s[0]=='"') dq=1-dq;
182*37da2899SCharles.Forsyth	for(i:=1;i<len s;i++){
183*37da2899SCharles.Forsyth		if (s[i]=='{' && s[i-1]!='\\') cb++;
184*37da2899SCharles.Forsyth		if (s[i]=='}' && s[i-1]!='\\' && cb>0) cb--;
185*37da2899SCharles.Forsyth		if (s[i]=='[' && s[i-1]!='\\') sb++;
186*37da2899SCharles.Forsyth		if (s[i]==']' && s[i-1]!='\\' && sb>0) sb--;
187*37da2899SCharles.Forsyth		if (s[i]=='"' && s[i-1]!='\\') dq=1-dq;
188*37da2899SCharles.Forsyth	}
189*37da2899SCharles.Forsyth	return (cb==0 && sb==0 && dq==0);
190*37da2899SCharles.Forsyth}
191