<commit_before>utilities.namespace("SymPy");
SymPy.DEFAULT_ANIMATION_DURATION = 500;
SymPy.SphinxShell = SymPy.Shell.$extend({
    evalModeTypes: ['eval', 'copy'],
    evalMode: 'eval',

    __init__: function(config) {
        this.$super(config);
        this.visible = true;
        this.queuedStatements = [];

        index = this.evalModeTypes.indexOf(config.record);
        this.evalMode = (index == -1) ? this.getCookie('sympy-evalMode', 'eval') : config.evalMode;
        this.banner = config.banner ? config.banner : '';
    },

    render: function(el) {
        this.$super(el);

        this.shellEl = $(el);

        var headerLink =
            $('<a href="http://live.sympy.org">SymPy Live Shell</a>');
        var header = $("<h2/>").append(headerLink);
        this.shellEl.prepend(header);

        this.toggleShellEl = $('<button/>').
            html("<span>Hide SymPy Live Shell</span>").
            attr("id", "toggleShell").
            addClass('shown');
        this.toggleShellEl.prepend($('<div class="arrow" />'));

        this.toggleShellEl.appendTo(document.body);
        this.toggleShellEl.click($.proxy(function() {
            this.toggle();
        }, this));

        // Add a link to Python code that will evaluate it in SymPy Live
        this.processCodeBlocks();

        // Don't expand the list of tab completions (saves space)
        this.completer.expandCompletions = false;

        // Change Fullscreen to go to main website
        $("#fullscreen-button").html("Go to SymPy Live");

	    this.evalModeEl.change($.proxy(function(event) {
            this.updateSettings();
            this.focus();
        }, this));
    },

    renderToolbar: function(settings) {
        this.$super(settings);

        $('<h3 class="shown">Settings</h3>').
            prependTo($("#settings")).
            click($.proxy(this.toggleSettings, this));
        $("#settings h3").prepend($('<div class="arrow"/>'));

        // We don't need the "force desktop version" option since there is
        // no mobile version
        var checkbox = $('#settings input[type="checkbox"]');
        checkbox.prev().hide();
        checkbox.next().hide();
        checkbox.hide();

        this.toolbarEl.append(
            $('<br/>'),
            $('<label for="evalMode">Evaluation Mode:</label>'),
            $('<select id="evalMode"/>').append(
                $('<option value="eval">Evaluate</option>'),
                $('<option value="copy">Copy</option>')
            ),
            $('<br/>')
        );
        this.evalModeEl = $('#evalMode');

        var index = this.evalModeTypes.indexOf(this.evalMode);
        this.evalModeEl.children('option')[index].selected = true;

        // Make enter the default submission button
        $("#submit-behavior").val("enter");
    },

    done: function(response) {
        this.$super(response);
        if (this.queuedStatements.length !== 0) {
            this.dequeueStatement();
            this.evaluate();
        }
    },

    error: function(xhr, status, error) {
        this.$super(xhr, status, error);
        this.queuedStatements.length = 0;
    },

    dequeueStatement: function() {
        if (this.queuedStatements.length !== 0) {
            this.setValue(this.queuedStatements.shift());
        }
    },

    processCodeBlocks: function() {
        $('.highlight-python').each($.proxy(function(index, el) {
            var el = $(el);
            var promptsFound = this.processIndividualCodeBlocks(el.find('pre'));

            if (promptsFound) {
                // Add the toolbar
                var container = $("<div/>").addClass('sympy-live-eval-toolbar');
                var evaluate = $("<button>Run code block in SymPy Live</button>").
                    addClass('sympy-live-eval-button').
                    appendTo(container);
                el.prepend(container);

                evaluate.click($.proxy(function() {
                    this.show();
                    var statementBlocks = el.find('div.live-statement');
                    var codeBlocks = [];
                    for (var i = 0; i < statementBlocks.length; i++) {
                        codeBlocks.push(
                            this.stripCode($(statementBlocks[i]).text())
                        );
                    }
                    if (this.evalModeEl.val() === "eval") {
                        this.queuedStatements = codeBlocks;
                        this.dequeueStatement();
                        this.evaluate();
                    }
                    else {
                        this.setValue(codeBlocks.join("\n"));
                        this.focus();
                    }
                }, this));
            }
        }, this));
    },

    /**
     * Processes a <pre> block, wrapping each line in a <div>. Additionally,
     * if the line is a Python prompt, it will be made executable-on-click.
     *
     * @return {Boolean} true if prompts were found
     */
    processIndividualCodeBlocks: function(codeEl) {
        // childNodes gives text nodes which we want for whitespace
        var childNodes = codeEl.get(0).childNodes;
        var currentLine = [];
        var lines = [];

        for (var i = 0; i < childNodes.length; i++) {
            var domNode = childNodes[i];
            if (domNode.nodeType === domNode.ELEMENT_NODE) {
                currentLine.push(domNode.cloneNode(true));

                if (currentLine.length === 1 &&
                    domNode.innerText.substr(0, 3) === "...") {
                    // First node on line and continuation, so continue from
                    // the previous line
                    currentLine = lines.pop();
                    currentLine.push(domNode.cloneNode(true));
                }
            }
            else if (domNode.nodeType === domNode.TEXT_NODE) {
                currentLine.push(domNode.cloneNode(true));
                if (domNode.data.substr(-1) === '\n') {
                    lines.push(currentLine);
                    currentLine = [];
                }
            }
        }

        if (lines.length !== 0) {
            var foundPrompt = false;

            codeEl.empty();
            for (var i = 0; i < lines.length; i++) {
                var line = $('<div />');
                var processingLine = lines[i];
                if (processingLine[0].innerText.substr(0, 4) === ">>> ") {
                    foundPrompt = true;

                    line.addClass('live-statement');<commit_msg>Use textContent || innerText for Firefox compatibility<commit_after>utilities.namespace("SymPy");
SymPy.DEFAULT_ANIMATION_DURATION = 500;
SymPy.SphinxShell = SymPy.Shell.$extend({
    evalModeTypes: ['eval', 'copy'],
    evalMode: 'eval',

    __init__: function(config) {
        this.$super(config);
        this.visible = true;
        this.queuedStatements = [];

        index = this.evalModeTypes.indexOf(config.record);
        this.evalMode = (index == -1) ? this.getCookie('sympy-evalMode', 'eval') : config.evalMode;
        this.banner = config.banner ? config.banner : '';
    },

    render: function(el) {
        this.$super(el);

        this.shellEl = $(el);

        var headerLink =
            $('<a href="http://live.sympy.org">SymPy Live Shell</a>');
        var header = $("<h2/>").append(headerLink);
        this.shellEl.prepend(header);

        this.toggleShellEl = $('<button/>').
            html("<span>Hide SymPy Live Shell</span>").
            attr("id", "toggleShell").
            addClass('shown');
        this.toggleShellEl.prepend($('<div class="arrow" />'));

        this.toggleShellEl.appendTo(document.body);
        this.toggleShellEl.click($.proxy(function() {
            this.toggle();
        }, this));

        // Add a link to Python code that will evaluate it in SymPy Live
        this.processCodeBlocks();

        // Don't expand the list of tab completions (saves space)
        this.completer.expandCompletions = false;

        // Change Fullscreen to go to main website
        $("#fullscreen-button").html("Go to SymPy Live");

	    this.evalModeEl.change($.proxy(function(event) {
            this.updateSettings();
            this.focus();
        }, this));
    },

    renderToolbar: function(settings) {
        this.$super(settings);

        $('<h3 class="shown">Settings</h3>').
            prependTo($("#settings")).
            click($.proxy(this.toggleSettings, this));
        $("#settings h3").prepend($('<div class="arrow"/>'));

        // We don't need the "force desktop version" option since there is
        // no mobile version
        var checkbox = $('#settings input[type="checkbox"]');
        checkbox.prev().hide();
        checkbox.next().hide();
        checkbox.hide();

        this.toolbarEl.append(
            $('<br/>'),
            $('<label for="evalMode">Evaluation Mode:</label>'),
            $('<select id="evalMode"/>').append(
                $('<option value="eval">Evaluate</option>'),
                $('<option value="copy">Copy</option>')
            ),
            $('<br/>')
        );
        this.evalModeEl = $('#evalMode');

        var index = this.evalModeTypes.indexOf(this.evalMode);
        this.evalModeEl.children('option')[index].selected = true;

        // Make enter the default submission button
        $("#submit-behavior").val("enter");
    },

    done: function(response) {
        this.$super(response);
        if (this.queuedStatements.length !== 0) {
            this.dequeueStatement();
            this.evaluate();
        }
    },

    error: function(xhr, status, error) {
        this.$super(xhr, status, error);
        this.queuedStatements.length = 0;
    },

    dequeueStatement: function() {
        if (this.queuedStatements.length !== 0) {
            this.setValue(this.queuedStatements.shift());
        }
    },

    processCodeBlocks: function() {
        $('.highlight-python').each($.proxy(function(index, el) {
            var el = $(el);
            var promptsFound = this.processIndividualCodeBlocks(el.find('pre'));

            if (promptsFound) {
                // Add the toolbar
                var container = $("<div/>").addClass('sympy-live-eval-toolbar');
                var evaluate = $("<button>Run code block in SymPy Live</button>").
                    addClass('sympy-live-eval-button').
                    appendTo(container);
                el.prepend(container);

                evaluate.click($.proxy(function() {
                    this.show();
                    var statementBlocks = el.find('div.live-statement');
                    var codeBlocks = [];
                    for (var i = 0; i < statementBlocks.length; i++) {
                        codeBlocks.push(
                            this.stripCode($(statementBlocks[i]).text())
                        );
                    }
                    if (this.evalModeEl.val() === "eval") {
                        this.queuedStatements = codeBlocks;
                        this.dequeueStatement();
                        this.evaluate();
                    }
                    else {
                        this.setValue(codeBlocks.join("\n"));
                        this.focus();
                    }
                }, this));
            }
        }, this));
    },

    /**
     * Processes a <pre> block, wrapping each line in a <div>. Additionally,
     * if the line is a Python prompt, it will be made executable-on-click.
     *
     * @return {Boolean} true if prompts were found
     */
    processIndividualCodeBlocks: function(codeEl) {
        // childNodes gives text nodes which we want for whitespace
        var childNodes = codeEl.get(0).childNodes;
        var currentLine = [];
        var lines = [];

        for (var i = 0; i < childNodes.length; i++) {
            var domNode = childNodes[i];
            if (domNode.nodeType === domNode.ELEMENT_NODE) {
                currentLine.push(domNode.cloneNode(true));

                // innerText is non-standard but only Firefox does not
                // support it; textContent is standard but IE < 9
                // does not support it
                var textContent = domNode.textContent || domNode.innerText;
                if (currentLine.length === 1 &&
                    textContent.substr(0, 3) === "...") {
                    // First node on line and continuation, so continue from
                    // the previous line
                    currentLine = lines.pop();
                    currentLine.push(domNode.cloneNode(true));
                }
            }
            else if (domNode.nodeType === domNode.TEXT_NODE) {
                currentLine.push(domNode.cloneNode(true));
                if (domNode.data.substr(-1) === '\n') {
                    lines.push(currentLine);
                    currentLine = [];
                }
            }
        }

        if (lines.length !== 0) {
            var foundPrompt = false;

            codeEl.empty();
            for (var i = 0; i < lines.length; i++) {
                var line = $('<div />');
                var processingLine = lines[i];
                var firstLineContent = processingLine[0].textContent ||
                    processingLine[0].innerText;
                if (firstLineContent.substr(0, 4) === ">>> ") {
                    foundPrompt = true;

                    line.addClass('live-statement');
{'fraction_non_alphanumeric': 0.14521035838836535, 'fraction_numerical': 0.003561623506715144, 'mean_word_length': 1.6479371316306484, 'pattern_counts': {'":': 0, '<': 60, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4587567', 'n_tokens_mistral': 3687, 'n_tokens_neox': 3461, 'n_words': 738}