Interpreter - JavaScript Interactive Interpreter
<!-- MochiKit is dual-licensed software. It is available under the terms of the MIT License, or the Academic Free License version 2.1. The full text of each license is included below. --> <!-- Code revised from MochiKit demo code --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Interpreter - JavaScript Interactive Interpreter</title> <style type="text/css"> h1 { font-size: 2em; color: #4B4545; text-align: center; } textarea.textbox { font-family: Monaco, "lucida console", Courier; border: 1px solid #CCCCCC; font-size: .60em; padding: 2px 4px; margin-top: .3em; } input.textbox { font-family: Monaco, "lucida console", Courier; border: 1px solid #CCCCCC; font-size: .60em; padding: 2px 4px; margin-top: .3em; } #interpreter_area { display: block; border: 1px solid #CCCCCC; padding: 2px 4px; margin-top: .3em; width: 600px; height: 300px; overflow: auto; } #interpreter_output { display: inline; font-family: Monaco, "lucida console", Courier; font-size: .60em; } #interpreter_output span { white-space: -moz-pre-wrap; /* Mozilla */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS 2.1 */ white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */ word-wrap: break-word; /* IE */ wrap-option: emergency; /* CSS 3 */ } input.textbox:focus { background-color: #FFFEE3; } .code { color: blue; } .data { color: black; } .error { color: red; } .banner { color: green; } .invisible { display: none; } </style> <script type="text/javascript" src="MochiKit-1.4.2/lib/MochiKit/MochiKit.js"></script> <script type="text/javascript"> /* Interpreter: JavaScript Interactive Interpreter */ InterpreterManager = function () { bindMethods(this); }; InterpreterManager.prototype.initialize = function () { connect("interpreter_text", "onkeyup", this.keyUp); connect("interpreter_textarea", "onkeydown", this.areaKeyDown); connect("interpreter_form", "onsubmit", this.submit); getElement("interpreter_text").focus(); this.banner(); this.lines = []; this.history = []; this.currentHistory = ""; this.historyPos = -1; this.blockingOn = null; if (typeof(this.doEval) == "undefined") { // detect broken eval, warn at some point if a namespace ever gets used this.doEval = function () { return eval(arguments[0]); } } window.help = this.help; this.help.NAME = 'type help(func) for help on a MochiKit function'; }; InterpreterManager.prototype.banner = function () { var _ua = window.navigator.userAgent; var ua = _ua.replace(/^Mozilla\/.*?\(.*?\)\s*/, ""); if (ua == "") { // MSIE ua = _ua.replace(/^Mozilla\/4\.0 \(compatible; MS(IE .*?);.*$/, "$1"); } appendChildNodes("interpreter_output", SPAN({"class": "banner"}, "MochiKit v" + MochiKit.Base.VERSION + " [" + ua + "]", BR(), "Type your expression in the input box below and press return, or see the notes below for more information.", BR() ), BR() ); }; InterpreterManager.prototype.submit = function (event) { if (this.blockingOn) { try { this.blockingOn.cancel(); } catch (e) { this.showError(e); } this.blockingOn = null; } this.doSubmit(); this.doScroll(); event.stop(); }; InterpreterManager.prototype.help = function (fn) { if (fn && fn.NAME) { fn = fn.NAME; } if (typeof(fn) != "string" || fn.length == 0) { writeln("help(func) on any MochiKit function for help"); return; } var comps = fn.split('.'); var base = comps.splice(0, 2); var shortfn = comps.join('.'); var url = '../../doc/html/' + base.join('/') + '.html'; var d = doXHR(url, {mimeType: 'text/xml'}); d.addCallback(function (req) { var els = getElementsByTagAndClassName( 'a', 'mochidef', req.responseXML); var match = '#fn-' + shortfn.toLowerCase(); for (var i = 0; i < els.length; i++) { var elem = els[i]; var href = elem.href; var idx = href.indexOf('#'); if (idx != -1 && href.substring(idx) == match) { writeln(A({href: url + match, target: '_blank'}, scrapeText(elem))); return; } } writeln('documentation for ' + fn + ' not found'); }); blockOn(d); }; InterpreterManager.prototype.doScroll = function () { var p = getElement("interpreter_output").lastChild; if (typeof(p) == "undefined" || p == null) { return; } var area = getElement("interpreter_area"); if (area.offsetHeight > area.scrollHeight) { area.scrollTop = 0; } else { area.scrollTop = area.scrollHeight; } }; InterpreterManager.prototype.moveHistory = function (dir) { // totally bogus value if (dir == 0 || this.history.length == 0) { return; } var elem = getElement("interpreter_text"); if (this.historyPos == -1) { this.currentHistory = elem.value; if (dir > 0) { return; } this.historyPos = this.history.length - 1; elem.value = this.history[this.historyPos]; return; } if (this.historyPos == 0 && dir < 0) { return; } if (this.historyPos == this.history.length - 1 && dir > 0) { this.historyPos = -1; elem.value = this.currentHistory; return; } this.historyPos += dir; elem.value = this.history[this.historyPos]; } InterpreterManager.prototype.runMultipleLines = function (text) { var lines = rstrip(text).replace("\r\n", "\n").split(/\n/); appendChildNodes("interpreter_output", SPAN({"class": "code"}, ">>> ", izip(lines, imap(BR, cycle([null])))) ); this.runCode(text); } InterpreterManager.prototype.areaKeyDown = function (e) { var mod = e.modifier(); var hasMod = mod.alt || mod.ctrl || mod.meta; if (e.key().string == 'KEY_ENTER' && hasMod) { var elem = getElement("interpreter_textarea"); var text = elem.value; elem.value = ""; this.runMultipleLines(text); e.stop(); } }; InterpreterManager.prototype.keyUp = function (e) { var key = e.key(); // if any meta key is pressed, don't handle the signal if (e.modifier().any) { return; } switch (key.string) { case'KEY_ARROW_UP': this.moveHistory(-1); break; case'KEY_ARROW_DOWN': this.moveHistory(1); break; default: return; } e.stop(); }; InterpreterManager.prototype.blockOn = function (d) { var node = SPAN({"class": "banner"}, "blocking on " + repr(d) + "..."); this.blockingOn = d; appendChildNodes("interpreter_output", node); this.doScroll(); d.addBoth(function (res) { swapDOM(node); this.blockingOn = null; if (res instanceof CancelledError) { window.writeln(SPAN({"class": "error"}, repr(d) + " cancelled!")); return undefined; } return res; }); d.addCallbacks(this.showResult, this.showError); }; InterpreterManager.prototype.showError = function (e) { if (typeof(e) != "object") { e = new Error(e); } appendChildNodes("interpreter_output", SPAN({"class": "error"}, "Error:"), TABLE({"class": "error"}, THEAD({"class": "invisible"}, TD({"colspan": 2})), TFOOT({"class": "invisible"}, TD({"colspan": 2})), TBODY(null, map(function (kv) { var v = kv[1]; if (typeof(v) == "function") { return; } if (typeof(v) == "object") { v = repr(v); } return TR(null, TD({"class": "error"}, kv[0]), TD({"class": "data"}, v) ); }, sorted(items(e))) ) ) ); window.last_exc = e; this.doScroll(); }; EvalFunctions = { evalWith: function () { with (arguments[1] || window) { return eval(arguments[0]); }; }, evalCall: function () { return eval.call(arguments[1] || window, arguments[0]); }, choose: function () { var ns = {__test__: this}; var e; try { if (this.evalWith("return __test__", ns) === this) { return this.evalWith; } } catch (e) { // pass } try { if (this.evalCall("return __test__", ns) === this) { return this.evalCall; } } catch (e) { // pass } return undefined; } }; InterpreterManager.prototype.doEval = EvalFunctions.choose(); InterpreterManager.prototype.doSubmit = function () { var elem = getElement("interpreter_text"); var code = elem.value; elem.value = ""; var isContinuation = false; if (code.length >= 2 && code.lastIndexOf("//") == code.length - 2) { isContinuation = true; code = code.substr(0, code.length - 2); } appendChildNodes("interpreter_output", SPAN({"class": "code"}, ">>> ", code), BR() ); this.lines.push(code); this.history.push(code); this.historyPos = -1; this.currentHistory = ""; if (isContinuation) { return; } var allCode = this.lines.join("\n"); this.lines = []; this.runCode(allCode); return; }; InterpreterManager.prototype.runCode = function (allCode) { var res; try { res = this.doEval(allCode); } catch (e) { // mozilla shows some keys more than once! this.showError(e); return; } this.showResult(res); }; InterpreterManager.prototype.showResult = function (res) { if (typeof(res) != "undefined") { window._ = res; } if (typeof(res) != "undefined") { appendChildNodes("interpreter_output", SPAN({"class": "data"}, repr(res)), BR() ); this.doScroll(); } }; window.writeln = function () { appendChildNodes("interpreter_output", SPAN({"class": "data"}, arguments), BR() ); interpreterManager.doScroll(); }; window.clear = function () { replaceChildNodes("interpreter_output"); getElement("interpreter_area").scrollTop = 0; }; window.blockOn = function (d) { if (!(d instanceof Deferred)) { thrownew TypeError(repr(d) + " is not a Deferred!"); } interpreterManager.blockOn(d); }; window.dir = function (o) { // Python muscle memory! return sorted(keys(o)); }; window.inspect = function (o) { window._ = o; if ((typeof(o) != "function" && typeof(o) != "object") || o == null) { window.writeln(repr(o)); return; } var pairs = items(o); if (pairs.length == 0) { window.writeln(repr(o)); return; } window.writeln(TABLE({"border": "1"}, THEAD({"class": "invisible"}, TR(null, TD(), TD())), TFOOT({"class": "invisible"}, TR(null, TD(), TD())), TBODY(null, map( function (kv) { var click = function () { try { window.inspect(kv[1]); } catch (e) { interpreterManager.showError(e); } return false; } return TR(null, TD(null, A({href: "#", onclick: click}, kv[0])), TD(null, repr(kv[1])) ); }, pairs ) ) )); }; interpreterManager = new InterpreterManager(); addLoadEvent(interpreterManager.initialize); // rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "interpreter/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); </script> </head> <body> <h1> Interpreter - JavaScript Interactive Interpreter </h1> <div> <p> This demo is a JavaScript interpreter. Type some code into the text input and press enter to see the results. It uses <a href="http://mochikit.com">MochiKit</a>'s <a href="../../doc/html/lib/MochiKit/DOM.html">MochiKit.DOM</a> to manipulate the display. It also supports waiting for <a href="../../doc/html/lib/MochiKit/Async.html">MochiKit.Async</a> Deferreds via <tt>blockOn(aDeferred)</tt>. </p> </div> <div> View Source: [ <a href="index.html"class="view-source">index.html</a> | <a href="interpreter.js"class="view-source">interpreter.js</a> ] </div> <form id="interpreter_form" autocomplete="off"> <div id="interpreter_area"> <div id="interpreter_output"></div> </div> <div id="oneline"> <input id="interpreter_text" name="input_text" type="text"class="textbox" size="100" /> </div> <div id="multiline"> <textarea id="interpreter_textarea" name="input_textarea" type="text"class="textbox" cols="97" rows="10"></textarea> <br /> </div> </form> <div> Notes: <ul> <li> To show the signature of a MochiKit function and link to its documentation, type help(fn) on any MochiKit function. </li> <li> To write multi-line code snippets, use the lower text area and press ctrl-enter or cmd-enter to submit. </li> <li> <tt>function name() {}</tt> syntax might not end up in window scope, so use <tt>name = function () {}</tt> syntax instead </li> <li> If you want to stuff something into the output window other than the <tt>repr(...)</tt> of the expression result, use the <tt>writeln(...)</tt> function. It accepts anything that MochiKit.DOM does, so you can even put styled stuff in there! </li> <li> Use <tt>clear()</tt> to clear the interpreter window. </li> <li> You can use <tt>blockOn(aDeferred)</tt> to wait on a Deferred. This expression must be used by itself, so the value must be obtained from <tt>_</tt> or <tt>last_exc</tt>. Typing any expression will cancel the Deferred. </li> <li> Up and down arrow keys work as a rudimentary history </li> <li> <tt>_</tt> is the value of the last expression that was not <tt>undefined</tt>, <tt>last_exc</tt> is the value of the last unhandled exception. </li> </ul> </div> </body> </html>
Related examples in the same category