Mochkit JavaScript DHTML





    
        Interpreter - JavaScript Interactive Interpreter
        
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; }
        
        
        
        
/*
    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)) {
        throw new 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;
    }
});
        
        
    
    
        


            Interpreter - JavaScript Interactive Interpreter
        


        

            


                This demo is a JavaScript interpreter.  Type some code into
                the text input and press enter to see the results.  It uses
                MochiKit's
                MochiKit.DOM
                to manipulate the display.  It also supports waiting for
                MochiKit.Async
                 Deferreds via blockOn(aDeferred).
            


        

        

            View Source: [
            index.html |
            interpreter.js
            ]
        

        
            
                

            

            
                
            

            
                
                
            
        
        

            Notes:
            

                    

  •                     To show the signature of a MochiKit function and link
                        to its documentation, type help(fn) on any MochiKit
                        function.
                    

  •                 

  •                     To write multi-line code snippets, use the lower text area
                        and press ctrl-enter or cmd-enter to submit.
                    

  •                 

  •                     function name() {} syntax might not end up in
                        window scope, so use name = function () {}
                        syntax instead
                    

  •                 

  •                     If you want to stuff something into the output window
                        other than the repr(...) of the expression
                        result, use the writeln(...) function.
                        It accepts anything that MochiKit.DOM does, so you can
                        even put styled stuff in there!
                    

  •                 

  •                     Use clear() to clear the interpreter window.
                    

  •                 

  •                     You can use blockOn(aDeferred) to wait on a
                        Deferred.  This expression must be used by itself, so
                        the value must be obtained from _ or
                        last_exc.  Typing any expression will
                        cancel the Deferred.
                    

  •                 

  •                     Up and down arrow keys work as a rudimentary history
                    

  •                 

  •                     _ is the value of the last expression
                        that was not undefinedlast_exc is
                        the value of the last unhandled exception.
                    

  •