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