diff --git a/gui/dialogs/nasal-console.xml b/gui/dialogs/nasal-console.xml index 8d89c3cad..cc6273eed 100644 --- a/gui/dialogs/nasal-console.xml +++ b/gui/dialogs/nasal-console.xml @@ -6,81 +6,249 @@ nasal-console vbox - - - + + hbox + 1 + + + + + + 1 + + + + editfield fill - 120 450 + 200 20 true - /sim/gui/dialogs/nasal-console/code + /sim/gui/dialogs/nasal-console/edit + + dialog-apply + editfield + hbox - 8 + fill + 4 - - + + 1 fill - - 0.5 - 0.5 - 0.5 - - - - - hbox - 0 - - - - - - - + 20 + 20 + 0 + 1 + ## 1 ## + ## /sim/gui/dialogs/nasal-console/tab-down[1] ## + + dialog-apply + editfield + + + nasal + + + + dialog-update + editfield + + + + + + + hbox + 4 + + + + 1 + + + + + + + + + + + var dlg = props.globals.getNode("/sim/gui/dialogs/nasal-console"); + var kbdctrl = props.globals.getNode("/devices/status/keyboard/ctrl", 1); + var printf = func { print(call(sprintf, arg)) } + var edit = dlg.getNode("edit", 1); + if (!contains(globals, "__nasal_console_locals")) { + globals["__nasal_console_locals"] = {}; + } + var locals = globals["__nasal_console_locals"]; + var numtabs = size(dlg.getChildren("code")); + if (!numtabs) { + numtabs = 10; + } + + var dump = func { + rule = "--------------------------------------------------------------------------------"; + print(rule ~ "\n"); + print(edit.getValue()); + print(rule); + } + + var clear = func { + edit.setValue(""); + } + + var execute = func(what = nil) { + var tag = "<nasal-console>"; + var err = []; + if (what == nil) { + what = edit; + } + var f = call(func { compile(what.getValue(), tag) }, nil, nil, nil, err); + if (size(err)) { + print(tag ~ ": " ~ err[0]); + return; + } + f = bind(f, globals); + call(f, nil, nil, locals, err); + if (size(err)) { + printf("%s at %s line %d\n", err[0], err[1], err[2]); + for (var i = 3; i < size(err); i += 2) { + printf(" called from %s line %d\n", err[i], err[i + 1]); + } + } + } + + var tabs = cmdarg().getNode("group[1]"); + var select = func(which, init = 0) { + if (active) { # false in help mode + dlg.getNode("active").setIntValue(active); + if (!init) { + dlg.getChild("code", active).setValue(screen.trim(edit.getValue())); + } + } + if (kbdctrl.getValue()) { + execute(dlg.getChild("code", which)); + return; + } + active = which; + foreach (var c; dlg.getChildren("tab-down")) { + c.setBoolValue(c.getIndex() == active); + } + # animate tab buttons + dlg.getNode("active").setIntValue(active = which); + edit.setValue(dlg.getChild("code", active).getValue()); + } + + var help = func { + active = 0; + foreach (var c; dlg.getChildren("tab-down")) { + c.setBoolValue(0); + } + edit.setValue("Keys:\n" + ~ " tab ... leave edit mode (visible text cursor)\n" + ~ " return ... execute active code\n" + ~ " ctrl-c ... clear input field\n" + ~ " ctrl-p ... print input field contents to terminal\n" + ~ " escape ... close dialog\n\n" + ~ "Ctrl-click on tab buttons executes code without switching to the tab.\n" + ~ "Add more <code> properties in ~/.fgfs/autosave.xml for more tab buttons."); + } + + # setup tab buttons and properties from the template + tabs.removeChildren("button"); + var template = tabs.getNode("button-template"); + var d = dlg.getPath(); + for (var i = 1; i <= numtabs; i += 1) { + var button = tabs.getChild("button", i, 1); + var state = dlg.getChild("tab-down", i, 1); + state.setBoolValue(0); + + props.copy(template, button); + button.getNode("hide").setValue(0); + button.getNode("legend").setIntValue(i); + button.getNode("binding[1]/script").setValue("select(" ~ i ~ ")"); + button.getNode("property").setValue(state.getPath()); + var c = dlg.getChild("code", i); + if (c == nil or c.getType() == "NONE") { + c = dlg.getChild("code", i, 1); + c.setValue(""); + c.setAttribute("userarchive", 1); + } + } + + edit.setValue(""); + var active = dlg.getNode("active", 1).getValue(); + if (active == nil) { + active = 1; + } + select(active, 1); + +