<commit_before>requirejs.config({
    shim: {
        'underscore': {
            exports: '_'
        }
    }
});

require(["./sweet", "./syntax", "./rx.jquery.min", "./rx.dom.compat.min"], function(sweet, syn, Rx) {
    
    var storage_code = 'editor_code';
    var storage_mode = 'editor_mode';

    var starting_code = $("#editor").text();
    var compileWithSourcemap = $("body").attr("data-sourcemap") === "true";

    var editor = CodeMirror.fromTextArea($('#editor')[0], {
        lineNumbers: true,
        smartIndent: false,
        indentWithTabs: false,
        tabSize: 4,
        indentUnit: 4,
        autofocus: true,
        theme: 'solarized dark',
        extraKeys: {
            Tab: function(cm) {
                if(cm.somethingSelected()) {
                    return cm.indentSelection("add");
                } else if(cm.options.indentWithTabs) {
                    return cm.replaceSelection("\t", "end", "+input");
                } else {
                    return cm.execCommand("insertSoftTab");
                }
            },
            Left: function(cm) {
                return cm.setCursor(cm.somethingSelected() ? cm.getCursor("from") : nextCursorPos(-1, 0, cm).cursor);
            },
            Right: function(cm) {
                return cm.setCursor(cm.somethingSelected() ? cm.getCursor("to") : nextCursorPos(1, 0, cm).cursor);
            },
            Backspace: function(cm) {
                var coords = cm.somethingSelected() ?
                    cm.listSelections().reduce(function(x, selection) {
                        x.left = selection.anchor;
                        x.right = selection.head;
                        x.cursor = x.left.ch - x.right.ch < 0 ? x.left : x.right;
                        return x;
                    }, {}) :
                    nextCursorPos(-1, 1, cm);
                var range = cm.getRange(coords.left, coords.right);
                cm.replaceRange("", coords.left, coords.right, range);
                cm.setCursor(coords.cursor);
            }
        }
    });

    var currentStep = 1;

    if (window.location.hash) {
        editor.setValue(decodeURI(window.location.hash.slice(1)));
    } else {
        editor.setValue(localStorage[storage_code] ? localStorage[storage_code] : starting_code);
    }
    if(localStorage[storage_mode]) {
        editor.setOption("keyMap", localStorage[storage_mode]);
    }

    var output = CodeMirror.fromTextArea($('#output')[0], {
        lineNumbers: true,
        theme: 'solarized dark',
        readOnly: true
    });
    
    $('#btn-vim').click(function() {
        editor.setOption('keyMap', 'vim');
        editor.focus();
        localStorage[storage_mode] = "vim";
    });
    $('#btn-emacs').click(function() {
        editor.setOption('keyMap', 'emacs');
        editor.focus();
        localStorage[storage_mode] = "emacs";
    });

    $('#btn-step').click(function() {
        var unparsedString = syn.prettyPrint(
            sweet.expand(editor.getValue(), 
                         undefined, 
                         currentStep++),
            $("#ck-hygiene").prop("checked"));
        $("#lab-step").text(currentStep);
        output.setValue(unparsedString); 
    });

    var updateTimeout;
    editor.on("change", function(e) {
        clearTimeout(updateTimeout);
        updateTimeout = setTimeout(updateExpand, 200);
    });

    function updateExpand() {
        var code = editor.getValue();
        var expanded, compiled, res;
        window.location = "editor.html#" + encodeURI(code);
        localStorage[storage_code] = code;
        try {
            if (compileWithSourcemap) {
                res = sweet.compile(code, {
                    sourceMap: true,
                    filename: "test.js",
                    readableNames: true
                });
            } else {
                res = sweet.compile(code, {
                    sourceMap: false,
                    readableNames: true
                });
            }
            compiled = res.code;
            output.setValue(compiled);

            $('#errors').text('');
            $('#errors').hide();
        } catch (e) {
            $('#errors').text(e);
            $('#errors').show();
        }
    }

    updateExpand();

    var resizeGutter = $(output.getGutterElement()).css("cursor", "ew-resize");
    var editorGutter = $(editor.getGutterElement());
    var resizeObs = $(window).resizeAsObservable().startWith(0).debounce(100);
    var downObs = resizeGutter.mousedownAsObservable();
    var moveObs = $(window).mousemoveAsObservable();
    var upObs   = $(window).mouseupAsObservable();
    
    // Start with the latest window width when the browser resizes.
    resizeObs.flatMapLatest(function(resizeEvent) {
        
        var windowWidth = $(window).width(),
            leftGutterWidth  = editorGutter.outerWidth(),
            rightGutterWidth = resizeGutter.outerWidth();
        
        // project each mousedown event into a series of future mousemove events.
        return downObs.flatMap(function(downEvent) {
            var editorWidth = $("#edit-box").outerWidth();
            
            // project each mousemove event into an editorWidth integer
            return moveObs.map(function(moveEvent) {
                return editorWidth + (moveEvent.pageX - downEvent.pageX);
            }).
            // stop listening to mousemoves when we receive a mouseup
            takeUntil(upObs);
        }).
        // don't update the DOM between browser repaints
        debounce(0, Rx.Scheduler.requestAnimationFrameScheduler).
        map(function(editorWidth) {
            return {
                editBoxWidth:   Math.max(Math.min(editorWidth, windowWidth - leftGutterWidth), leftGutterWidth),
                outputBoxLeft:  Math.max(Math.min(editorWidth, windowWidth - leftGutterWidth), leftGutterWidth),
                editBoxRight:   Math.min(Math.max(windowWidth - editorWidth, rightGutterWidth), windowWidth - rightGutterWidth),
                outputBoxWidth: Math.min(Math.max(windowWidth - editorWidth, rightGutterWidth), windowWidth - rightGutterWidth),
            };
        });
    }).
    forEach(function(coords) {
        $("#edit-box").css("right", coords.editBoxRight + "px");
        editor.setSize(coords.editBoxWidth, null);
        
        $("#output-box").css("left", coords.outputBoxLeft + "px");
        output.setSize(coords.outputBoxWidth, null);
    });

    function nextCursorPos(dir, tabStop, cm) {
        
        // 0 if dir == -1, else 1
        var rightOffset = Number(Boolean(~dir));
        // 0 if dir == !1, else -1
        var leftOffset = -1 * Number(Boolean(dir - 1));
        
        var position = cm.getCursor("head");
        var line = position.line;
        var ch   = position.ch;
        var content = cm.getLine(line);
        
        var hBound = ~dir ? content.length - ch : ch;
        var vBound = rightOffset * (cm.lineCount() - 1);
        var unit = cm.options.indentUnit;
        var range, left, right, cursor;
        
        // Is there enough room to jump over a tab-width of spaces?
        if(hBound < unit) {
            // should we jump lines?
            if(hBound === 0) {<commit_msg>Fixes editor resize behavior on window resize, adds left border to output gutter to make dragging easier.<commit_after>requirejs.config({
    shim: {
        'underscore': {
            exports: '_'
        }
    }
});

require(["./sweet", "./syntax", "./rx.jquery.min", "./rx.dom.compat.min"], function(sweet, syn, Rx) {
    
    var storage_code = 'editor_code';
    var storage_mode = 'editor_mode';

    var starting_code = $("#editor").text();
    var compileWithSourcemap = $("body").attr("data-sourcemap") === "true";

    var editor = CodeMirror.fromTextArea($('#editor')[0], {
        lineNumbers: true,
        smartIndent: false,
        indentWithTabs: false,
        tabSize: 4,
        indentUnit: 4,
        autofocus: true,
        theme: 'solarized dark',
        extraKeys: {
            Tab: function(cm) {
                if(cm.somethingSelected()) {
                    return cm.indentSelection("add");
                } else if(cm.options.indentWithTabs) {
                    return cm.replaceSelection("\t", "end", "+input");
                } else {
                    return cm.execCommand("insertSoftTab");
                }
            },
            Left: function(cm) {
                return cm.setCursor(cm.somethingSelected() ? cm.getCursor("from") : nextCursorPos(-1, 0, cm).cursor);
            },
            Right: function(cm) {
                return cm.setCursor(cm.somethingSelected() ? cm.getCursor("to") : nextCursorPos(1, 0, cm).cursor);
            },
            Backspace: function(cm) {
                var coords = cm.somethingSelected() ?
                    cm.listSelections().reduce(function(x, selection) {
                        x.left = selection.anchor;
                        x.right = selection.head;
                        x.cursor = x.left.ch - x.right.ch < 0 ? x.left : x.right;
                        return x;
                    }, {}) :
                    nextCursorPos(-1, 1, cm);
                var range = cm.getRange(coords.left, coords.right);
                cm.replaceRange("", coords.left, coords.right, range);
                cm.setCursor(coords.cursor);
            }
        }
    });

    var currentStep = 1;

    if (window.location.hash) {
        editor.setValue(decodeURI(window.location.hash.slice(1)));
    } else {
        editor.setValue(localStorage[storage_code] ? localStorage[storage_code] : starting_code);
    }
    if(localStorage[storage_mode]) {
        editor.setOption("keyMap", localStorage[storage_mode]);
    }

    var output = CodeMirror.fromTextArea($('#output')[0], {
        lineNumbers: true,
        theme: 'solarized dark',
        readOnly: true
    });
    
    $('#btn-vim').click(function() {
        editor.setOption('keyMap', 'vim');
        editor.focus();
        localStorage[storage_mode] = "vim";
    });
    $('#btn-emacs').click(function() {
        editor.setOption('keyMap', 'emacs');
        editor.focus();
        localStorage[storage_mode] = "emacs";
    });

    $('#btn-step').click(function() {
        var unparsedString = syn.prettyPrint(
            sweet.expand(editor.getValue(), 
                         undefined, 
                         currentStep++),
            $("#ck-hygiene").prop("checked"));
        $("#lab-step").text(currentStep);
        output.setValue(unparsedString); 
    });

    var updateTimeout;
    editor.on("change", function(e) {
        clearTimeout(updateTimeout);
        updateTimeout = setTimeout(updateExpand, 200);
    });

    function updateExpand() {
        var code = editor.getValue();
        var expanded, compiled, res;
        window.location = "editor.html#" + encodeURI(code);
        localStorage[storage_code] = code;
        try {
            if (compileWithSourcemap) {
                res = sweet.compile(code, {
                    sourceMap: true,
                    filename: "test.js",
                    readableNames: true
                });
            } else {
                res = sweet.compile(code, {
                    sourceMap: false,
                    readableNames: true
                });
            }
            compiled = res.code;
            output.setValue(compiled);

            $('#errors').text('');
            $('#errors').hide();
        } catch (e) {
            $('#errors').text(e);
            $('#errors').show();
        }
    }

    updateExpand();
    
    var editBox = $("#edit-box");
    var outputBox = $("#output-box");
    var resizeGutter = $(output.getGutterElement()).css({
        "cursor": "ew-resize",
        "border-left": "3px rgba(0,0,0,0.5) solid"
    });
    var editorGutter = $(editor.getGutterElement());
    var resizeObs = $(window).resizeAsObservable().startWith(0).debounce(100);
    var downObs = resizeGutter.mousedownAsObservable();
    var moveObs = $(window).mousemoveAsObservable();
    var upObs   = $(window).mouseupAsObservable();
    
    // Start with the latest window width when the browser resizes.
    resizeObs.flatMapLatest(function(resizeEvent) {
        
        var windowWidth = $(window).width(),
            editorWidth = editBox.outerWidth(),
            leftGutterWidth  = editorGutter.outerWidth(),
            rightGutterWidth = resizeGutter.outerWidth();
        
        // project each mousedown event into a series of future mousemove events.
        return downObs.flatMap(function(downEvent) {
            editorWidth = editBox.outerWidth();
            leftGutterWidth  = editorGutter.outerWidth();
            rightGutterWidth = resizeGutter.outerWidth();
            
            // project each mousemove event into an editorWidth integer
            return moveObs.map(function(moveEvent) {
                return editorWidth + (moveEvent.pageX - downEvent.pageX);
            }).
            // stop listening to mousemoves when we receive a mouseup
            takeUntil(upObs);
        }).
        // don't update the DOM between browser repaints
        debounce(0, Rx.Scheduler.requestAnimationFrameScheduler).
        startWith(editorWidth).
        map(function(editorWidth) {
            return {
                editBoxWidth:   Math.max(Math.min(editorWidth, windowWidth - leftGutterWidth), leftGutterWidth),
                outputBoxLeft:  Math.max(Math.min(editorWidth, windowWidth - leftGutterWidth), leftGutterWidth),
                editBoxRight:   Math.min(Math.max(windowWidth - editorWidth, rightGutterWidth), windowWidth - rightGutterWidth),
                outputBoxWidth: Math.min(Math.max(windowWidth - editorWidth, rightGutterWidth), windowWidth - rightGutterWidth),
            };
        });
    }).
    forEach(function(coords) {
        editBox.css("right", coords.editBoxRight + "px");
        editor.setSize(coords.editBoxWidth, null);
        outputBox.css("left", coords.outputBoxLeft + "px");
        output.setSize(coords.outputBoxWidth, null);
    });

    function nextCursorPos(dir, tabStop, cm) {
        
        // 0 if dir == -1, else 1
        var rightOffset = Number(Boolean(~dir));
        // 0 if dir == !1, else -1
        var leftOffset = -1 * Number(Boolean(dir - 1));
        
        var position = cm.getCursor("head");
        var line = position.line;
        var ch   = position.ch;
        var content = cm.getLine(line);
        
        var hBound = ~dir ? content.length - ch : ch;
        var vBound = rightOffset * (cm.lineCount() - 1);
        var unit = cm.options.indentUnit;
        var range, left, right, cursor;
        
        // Is there enough room to jump over a tab-width of spaces?
        if(hBound < unit) {
            // should we jump lines?
            if(hBound === 0) {
{'fraction_non_alphanumeric': 0.1333780160857909, 'fraction_numerical': 0.004557640750670241, 'mean_word_length': 1.8573343546533896, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 3, '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': '6579923', 'n_tokens_mistral': 4232, 'n_tokens_neox': 4046, 'n_words': 821}