xref: /inferno-os/appl/spree/lib/commandline.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Commandline;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsythinclude "tk.m";
7*37da2899SCharles.Forsyth	tk: Tk;
8*37da2899SCharles.Forsythinclude "tkclient.m";
9*37da2899SCharles.Forsyth	tkclient: Tkclient;
10*37da2899SCharles.Forsythinclude "commandline.m";
11*37da2899SCharles.Forsyth
12*37da2899SCharles.ForsythDebug: con 0;
13*37da2899SCharles.Forsyth
14*37da2899SCharles.Forsythnomodule(modpath: string)
15*37da2899SCharles.Forsyth{
16*37da2899SCharles.Forsyth	sys->fprint(stderr(), "fibs: couldn't load %s: %r\n", modpath);
17*37da2899SCharles.Forsyth	raise "fail:bad module";
18*37da2899SCharles.Forsyth}
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsythinit()
21*37da2899SCharles.Forsyth{	sys = load Sys Sys->PATH;
22*37da2899SCharles.Forsyth
23*37da2899SCharles.Forsyth	tk = load Tk Tk->PATH;
24*37da2899SCharles.Forsyth	if (tk == nil) nomodule(Tk->PATH);
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsyth	tkclient = load Tkclient Tkclient->PATH;
27*37da2899SCharles.Forsyth	if (tkclient == nil) nomodule(Tkclient->PATH);
28*37da2899SCharles.Forsyth	tkclient->init();
29*37da2899SCharles.Forsyth}
30*37da2899SCharles.Forsyth
31*37da2899SCharles.ForsythCmdline.new(top: ref Tk->Toplevel, w, textopts: string): (ref Cmdline, chan of string)
32*37da2899SCharles.Forsyth{
33*37da2899SCharles.Forsyth	window_cfg := array[] of {
34*37da2899SCharles.Forsyth		"frame " + w,
35*37da2899SCharles.Forsyth		"scrollbar " + w + ".scroll -command {" + w + ".t yview}",
36*37da2899SCharles.Forsyth		"text " + w + ".t -yscrollcommand {" + w + ".scroll set} " + textopts,
37*37da2899SCharles.Forsyth		"pack " + w + ".scroll -side left -fill y",
38*37da2899SCharles.Forsyth		"pack " + w + ".t -fill both -expand 1",
39*37da2899SCharles.Forsyth
40*37da2899SCharles.Forsyth		"bind " + w + ".t <Key> {send evch k {%A}}",
41*37da2899SCharles.Forsyth		"bind " + w + ".t <Control-d> {send evch k {%A}}",
42*37da2899SCharles.Forsyth		"bind " + w + ".t <Control-u> {send evch k {%A}}",
43*37da2899SCharles.Forsyth		"bind " + w + ".t <Control-w> {send evch k {%A}}",
44*37da2899SCharles.Forsyth		"bind " + w + ".t <Control-h> {send evch k {%A}}",
45*37da2899SCharles.Forsyth		# treat button 2 and button 3 the same so we're alright with a 2-button mouse
46*37da2899SCharles.Forsyth		"bind " + w + ".t <ButtonPress-2> {send evch b %x %y}",
47*37da2899SCharles.Forsyth		"bind " + w + ".t <ButtonPress-3> {send evch b %x %y}",
48*37da2899SCharles.Forsyth		w + ".t mark set outpoint end",
49*37da2899SCharles.Forsyth		w + ".t mark gravity outpoint left",
50*37da2899SCharles.Forsyth		w + ".t mark set inpoint end",
51*37da2899SCharles.Forsyth		w + ".t mark gravity inpoint left",
52*37da2899SCharles.Forsyth	};
53*37da2899SCharles.Forsyth	evch := chan of string;
54*37da2899SCharles.Forsyth	tk->namechan(top, evch, "evch");
55*37da2899SCharles.Forsyth
56*37da2899SCharles.Forsyth	for (i := 0; i < len window_cfg; i++) {
57*37da2899SCharles.Forsyth		e := cmd(top, window_cfg[i]);
58*37da2899SCharles.Forsyth		if (e != nil && e[0] == '!')
59*37da2899SCharles.Forsyth			break;
60*37da2899SCharles.Forsyth	}
61*37da2899SCharles.Forsyth
62*37da2899SCharles.Forsyth	err := tk->cmd(top, "variable lasterror");
63*37da2899SCharles.Forsyth	if (err != nil) {
64*37da2899SCharles.Forsyth		sys->fprint(stderr(), "error in commandline config: %s\n", err);
65*37da2899SCharles.Forsyth		raise "fail:commandline config error";
66*37da2899SCharles.Forsyth	}
67*37da2899SCharles.Forsyth	cmd(top, w + ".t mark set insert end;" + w + ".t see insert");
68*37da2899SCharles.Forsyth	return (ref Cmdline(w, top), evch);
69*37da2899SCharles.Forsyth}
70*37da2899SCharles.Forsyth
71*37da2899SCharles.ForsythCmdline.focus(cmdl: self ref Cmdline)
72*37da2899SCharles.Forsyth{
73*37da2899SCharles.Forsyth	cmd(cmdl.top, "focus " + cmdl.w + ".t");
74*37da2899SCharles.Forsyth}
75*37da2899SCharles.Forsyth
76*37da2899SCharles.ForsythCmdline.event(cmdl: self ref Cmdline, e: string): list of string
77*37da2899SCharles.Forsyth{
78*37da2899SCharles.Forsyth	case e[0] {
79*37da2899SCharles.Forsyth	'k' =>
80*37da2899SCharles.Forsyth		return handle_key(cmdl, e[2:]);
81*37da2899SCharles.Forsyth	'b' =>
82*37da2899SCharles.Forsyth		;
83*37da2899SCharles.Forsyth	}
84*37da2899SCharles.Forsyth	return nil;
85*37da2899SCharles.Forsyth}
86*37da2899SCharles.Forsyth
87*37da2899SCharles.ForsythBS:		con 8;		# ^h backspace character
88*37da2899SCharles.ForsythBSW:		con 23;		# ^w bacspace word
89*37da2899SCharles.ForsythBSL:		con 21;		# ^u backspace line
90*37da2899SCharles.Forsyth
91*37da2899SCharles.Forsythhandle_key(cmdl: ref Cmdline, c: string): list of string
92*37da2899SCharles.Forsyth{
93*37da2899SCharles.Forsyth	(w, top) := (cmdl.w, cmdl.top);
94*37da2899SCharles.Forsyth	# don't allow editing of the text before the inpoint.
95*37da2899SCharles.Forsyth	if (int cmd(top, w + ".t compare insert < inpoint"))
96*37da2899SCharles.Forsyth		return nil;
97*37da2899SCharles.Forsyth	lines: list of string;
98*37da2899SCharles.Forsyth	char := c[1];
99*37da2899SCharles.Forsyth	if (char == '\\')
100*37da2899SCharles.Forsyth		char = c[2];
101*37da2899SCharles.Forsyth	case char {
102*37da2899SCharles.Forsyth	* =>
103*37da2899SCharles.Forsyth		cmd(top, w + ".t insert insert "+c+" {}");
104*37da2899SCharles.Forsyth	'\n' =>
105*37da2899SCharles.Forsyth		cmd(top, w + ".t insert insert "+c+" {}");
106*37da2899SCharles.Forsyth		lines = sendinput(cmdl);
107*37da2899SCharles.Forsyth	BSL or BSW or BS =>
108*37da2899SCharles.Forsyth		delpoint: string;
109*37da2899SCharles.Forsyth		case char {
110*37da2899SCharles.Forsyth		BSL =>	delpoint = "{insert linestart}";
111*37da2899SCharles.Forsyth		BSW =>	delpoint = "{insert -1char wordstart}";	# wordstart isn't ideal
112*37da2899SCharles.Forsyth		BS  =>	delpoint = "{insert-1char}";
113*37da2899SCharles.Forsyth		}
114*37da2899SCharles.Forsyth		if (int cmd(top, w + ".t compare inpoint < " + delpoint))
115*37da2899SCharles.Forsyth			cmd(top, w + ".t delete "+delpoint+" insert");
116*37da2899SCharles.Forsyth		else
117*37da2899SCharles.Forsyth			cmd(top, w + ".t delete inpoint insert");
118*37da2899SCharles.Forsyth	}
119*37da2899SCharles.Forsyth	cmd(top, w + ".t see insert;update");
120*37da2899SCharles.Forsyth	return lines;
121*37da2899SCharles.Forsyth}
122*37da2899SCharles.Forsyth
123*37da2899SCharles.Forsythsendinput(cmdl: ref Cmdline): list of string
124*37da2899SCharles.Forsyth{
125*37da2899SCharles.Forsyth	(w, top) := (cmdl.w, cmdl.top);
126*37da2899SCharles.Forsyth	# loop through all the lines that have been entered,
127*37da2899SCharles.Forsyth	# processing each one in turn.
128*37da2899SCharles.Forsyth	nl, lines: list of string;
129*37da2899SCharles.Forsyth	for (;;) {
130*37da2899SCharles.Forsyth		input: string;
131*37da2899SCharles.Forsyth		input = cmd(top, w + ".t get inpoint end");
132*37da2899SCharles.Forsyth		if (len input == 0)
133*37da2899SCharles.Forsyth			break;
134*37da2899SCharles.Forsyth		for (i := 0; i < len input; i++)
135*37da2899SCharles.Forsyth			if (input[i] == '\n')
136*37da2899SCharles.Forsyth				break;
137*37da2899SCharles.Forsyth		if (i >= len input)
138*37da2899SCharles.Forsyth			break;
139*37da2899SCharles.Forsyth		cmd(top, w + ".t mark set outpoint inpoint+"+string (i+1)+"chars");
140*37da2899SCharles.Forsyth		cmd(top, w + ".t mark set inpoint outpoint");
141*37da2899SCharles.Forsyth		lines = input[0:i+1] :: lines;
142*37da2899SCharles.Forsyth	}
143*37da2899SCharles.Forsyth	for (; lines != nil; lines = tl lines)
144*37da2899SCharles.Forsyth		nl = hd lines :: nl;
145*37da2899SCharles.Forsyth	return nl;
146*37da2899SCharles.Forsyth}
147*37da2899SCharles.Forsyth
148*37da2899SCharles.Forsythadd(cmdl: ref Cmdline, t: string, n: int)
149*37da2899SCharles.Forsyth{
150*37da2899SCharles.Forsyth	(w, top) := (cmdl.w, cmdl.top);
151*37da2899SCharles.Forsyth	cmd(top, w + ".t insert outpoint " + t);
152*37da2899SCharles.Forsyth	cmd(top, w + ".t mark set outpoint outpoint+"+string n+"chars");
153*37da2899SCharles.Forsyth	cmd(top, w + ".t mark set inpoint outpoint");
154*37da2899SCharles.Forsyth	cmd(top, w + ".t see insert");
155*37da2899SCharles.Forsyth}
156*37da2899SCharles.Forsyth
157*37da2899SCharles.ForsythCmdline.tagaddtext(cmdl: self ref Cmdline, t: list of (string, string))
158*37da2899SCharles.Forsyth{
159*37da2899SCharles.Forsyth	txt := "";
160*37da2899SCharles.Forsyth	n := 0;
161*37da2899SCharles.Forsyth	for (; t != nil; t = tl t) {
162*37da2899SCharles.Forsyth		(tags, s) := hd t;
163*37da2899SCharles.Forsyth		txt += " " + tk->quote(s) + " {" + tags + "}";
164*37da2899SCharles.Forsyth		n += len s;
165*37da2899SCharles.Forsyth	}
166*37da2899SCharles.Forsyth	add(cmdl, txt, n);
167*37da2899SCharles.Forsyth}
168*37da2899SCharles.Forsyth
169*37da2899SCharles.ForsythCmdline.addtext(cmdl: self ref Cmdline, txt: string)
170*37da2899SCharles.Forsyth{
171*37da2899SCharles.Forsyth	if (Debug) sys->print("%s", txt);
172*37da2899SCharles.Forsyth	add(cmdl, tk->quote(txt) + " {}" , len txt);
173*37da2899SCharles.Forsyth}
174*37da2899SCharles.Forsyth
175*37da2899SCharles.ForsythCmdline.maketag(cmdl: self ref Cmdline, name, options: string)
176*37da2899SCharles.Forsyth{
177*37da2899SCharles.Forsyth	cmd(cmdl.top, cmdl.w + ".t tag configure " + name + " " + options);
178*37da2899SCharles.Forsyth}
179*37da2899SCharles.Forsyth
180*37da2899SCharles.Forsythstderr(): ref Sys->FD
181*37da2899SCharles.Forsyth{
182*37da2899SCharles.Forsyth	return sys->fildes(2);
183*37da2899SCharles.Forsyth}
184*37da2899SCharles.Forsyth
185*37da2899SCharles.Forsythcmd(top: ref Tk->Toplevel, s: string): string
186*37da2899SCharles.Forsyth{
187*37da2899SCharles.Forsyth	e := tk->cmd(top, s);
188*37da2899SCharles.Forsyth	if (e != nil && e[0] == '!')
189*37da2899SCharles.Forsyth		sys->fprint(stderr(), "cmd error on '%s': %s\n", s, e);
190*37da2899SCharles.Forsyth	return e;
191*37da2899SCharles.Forsyth}
192