1 var translate = { 356: '<', 357: '^', 358: '>', 359: '_' };
11 dialog = Dialog.new();
13 listener = setlistener("/devices/status/keyboard/event", func(event) {
14 var key = event.getNode("key");
15 if (!event.getNode("pressed").getValue()) {
16 if (cmd == "" and key.getValue() == `;`) # FIXME hack around kbd bug
20 if (handle_key(key.getValue()))
27 removelistener(listener);
33 var handle_key = func(key) {
39 cmd = substr(cmd, 0, size(cmd) - 1);
40 } elsif (key == `\t`) {
42 } elsif (key == `\n` or key == `\r`) {
44 } elsif (contains(translate, key)) {
45 cmd ~= translate[key];
46 } elsif (!string.isprint(key)) {
54 var desc = __multikey._ = nil;
55 if ((var node = find_entry(cmd, data, __multikey.arg = [])) != nil) {
56 desc = node.getNode("desc", 1).getValue() or "";
57 desc = call(sprintf, [desc] ~ __multikey.arg);
58 bindings = node.getChildren("binding");
59 if (node.getNode("no-exit") != nil) {
60 cmd = substr(cmd, 0, size(cmd) - 1);
62 } elsif (node.getNode("exit") != nil) {
66 foreach (var c; node.getChildren("key"))
67 if (size(c.getChildren("binding")) or size(c.getChildren("key")))
71 if (mode and size(bindings)) {
72 foreach (var b; bindings)
73 props.runBinding(b, "__multikey");
78 dialog.update(cmd, __multikey._ or desc, options);
85 var m = { parents: [Dialog] };
87 m.prop = props.Node.new({ "dialog-name": m.name });
93 me.isopen and fgcommand("dialog-close", me.prop);
96 update : func(cmd, title, options) {
97 var dlg = gui.Widget.new();
98 dlg.set("name", me.name);
100 dlg.set("layout", "vbox");
101 dlg.set("default-padding", 2);
104 var t = dlg.addChild("text");
106 t.set("label", " Command Mode ");
107 t.setColor(1, 0.7, 0);
109 t.set("label", " " ~ title ~ " ");
110 t.setColor(0.7, 1, 0.7);
112 t.set("label", " <unknown> ");
113 t.setColor(1, 0.4, 0.4);
117 var t = dlg.addChild("text");
120 cmd = " Use <Tab> to toggle options! ";
121 t.setColor(0.5, 0.5, 0.5);
126 if (var numopt = size(options)) {
127 dlg.addChild("hrule");
128 var g = dlg.addChild("group");
129 g.set("layout", "table");
130 g.set("default-padding", 2);
131 var numrows = numopt / (1 + (numopt > 15) + (numopt > 30));
132 forindex (var i; options) {
133 var col = 3 * int(i / numrows);
134 var row = math.mod(i, numrows);
136 var desc = (options[i].getNode("desc", 1).getValue() or "") ~ " ";
137 var name = " " ~ options[i].getNode("name", 1).getValue();
138 name = string.replace(name, "%%", "%");
140 var o = g.addChild("text");
141 o.set("label", name);
144 var o = g.addChild("text");
145 o.set("label", " ... ");
147 o.set("col", col + 1);
148 var o = g.addChild("text");
149 o.set("label", desc);
151 o.set("col", col + 2);
152 o.set("halign", "left");
156 fgcommand("dialog-new", dlg.prop());
157 fgcommand("dialog-show", me.prop);
164 var colorize = func(str) {
166 for (var i = 0; i < size(str); i += 1) {
168 if (c == `<` or c == `>` or c == `^` or c == `_`) {
169 s ~= string.color("35", chr(c));
171 if ((i += 1) < size(str) and str[i] == `%`) {
176 for (; i < size(str) and (c = str[i]) != nil and string.isdigit(c); i += 1)
179 s ~= string.color("31", f ~ 'd');
181 s ~= string.color("32", f ~ 'u');
183 s ~= string.color("36", f ~ 'f');
185 s ~= string.color("34", f ~ 's');
194 var read_list = func(data) {
195 foreach (var c; data.children)
197 if (size(data.format))
198 append(list, [data.format, data.node]);
202 var (curr, title) = (0, "");
203 foreach (var k; sort(list, func(a, b) cmp(a[0], b[0]))) {
204 var bndg = k[1].getChildren("binding");
205 var desc = k[1].getNode("desc", 1).getValue() or "??";
206 if (size(k[0]) == 1 or k[0][0] == `%`)
208 if (!size(bndg) or size(bndg) == 1 and bndg[0].getNode("command", 1).getValue() == "null")
210 if (string.isalnum(k[0][0]) and k[0][0] != curr) {
212 var line = "---------------------------------------------------";
213 print(string.color("33", sprintf("\n-- %s %s", title, substr(line, size(title) + 2))));
215 if (k[1].getNode("no-exit") != nil)
216 desc ~= string.color("32", " +");
217 elsif (k[1].getNode("exit") != nil)
218 desc ~= string.color("31", " $");
219 printf("%s\t%s", colorize(k[0]), desc);
221 print(string.color("33", "\n-- Legend -------------------------------------------"));
222 printf("\t%s ... unsigned number", colorize("%u"));
223 printf("\t%s ... signed number", colorize("%d"));
224 printf("\t%s ... floating point number", colorize("%f"));
225 printf("\t%s ... string", colorize("%s"));
226 printf("\t%s ... < or cursor left", colorize("<"));
227 printf("\t%s ... > or cursor right", colorize(">"));
228 printf("\t%s ... ^ or cursor up", colorize("^"));
229 printf("\t%s ... _ or cursor down", colorize("_"));
230 printf("\t%s ... repeatable action", string.color("32", "+"));
231 printf("\t%s ... immediate action", string.color("31", "$"));
235 var find_entry = func(str, data, result) {
236 foreach (var c; data.children)
237 if ((var n = find_entry(str, c, result)) != nil)
239 if (string.scanf(str, data.format, var res = [])) {
249 globals["__multikey"] = { _: };
250 var tree = props.globals.getNode("/input/keyboard/multikey", 1);
252 foreach (var n; tree.getChildren("nasal")) {
253 n.getNode("module", 1).setValue("__multikey");
254 fgcommand("nasal", n);
257 var scan = func(tree, format = "") {
259 foreach (var key; tree.getChildren("key"))
260 foreach (var name; key.getChildren("name"))
261 if ((var n = name.getValue()) != nil)
262 append(d, { format: format ~ n, node: key,
263 children: scan(key, format ~ n) });
267 data = { format: "", node: tree, children: scan(tree) };
271 _setlistener("/sim/signals/nasal-dir-initialized", init);