<commit_before>define(function(require, exports, module) {
    var session_manager = require("../../session_manager");
    var Range = require("ace/range").Range;
    var editor = require("../../editor");
    var sandbox = require("../../sandbox");
    var InlineAnnotation = require("../../lib/inline_annotation");
    var eventbus = require("../../lib/eventbus");

    function rangify(range) {
        return Range.fromPoints(range.start, range.end);
    }

    function getSession(path) {
        return path ? session_manager.getSessions()[path] : editor.getActiveSession();
    }

    var identifierRegex = /[a-zA-Z_0-9\$\-]/;

    return {
        goto: function(path, callback) {
            var edit = editor.getActiveEditor();
            session_manager.go(path, edit, edit.getSession(), function(err) {
                callback(err);
            });
        },
        setAnnotations: function(path, annos, callback) {
            var session = getSession(path);
            (session.annotations || []).forEach(function(anno) {
                console.log("Removing anno", anno);
                anno.remove();
            });
            session.annotations = [];
            for (var i = 0; i < annos.length; i++) {
                var anno = annos[i];
                // If no endColum, no inline marker is required
                if (anno.endColumn) {
                    session.annotations.push(new InlineAnnotation(session, anno));
                }
            }
            session.setAnnotations(annos);
            callback();
        },
        getText: function(path, callback) {
            var session = getSession(path);
            if (!session) {
                return callback("No session for: " + path);
            }
            callback(null, session.getValue());
        },
        // Don't use setText unless you are really changing the entire contents
        // of the document, because it interacts poorly with the selection,
        // cursor position, undo history, etc.
        setText: function(path, text, callback) {
            var session = getSession(path);

            // Save scroll/cursor state
            var scrollTop = session.getScrollTop();
            var scrollLeft = session.getScrollLeft();
            var cursorPos = session.selection.getCursor();

            var lineCount = session.getLength();
            var range = new Range(0, 0, lineCount, session.getLine(lineCount - 1).length);

            session.replace(range, text);

            session.selection.clearSelection();
            session.selection.moveCursorToPosition(cursorPos);
            session.setScrollTop(scrollTop);
            session.setScrollLeft(scrollLeft);
            callback();
        },
        insertAtCursor: function(path, text, callback) {
            var session = getSession(path);
            session.insert(session.selection.getCursor(), text);
            callback();
        },
        insert: function(path, pos, text, callback) {
            var session = getSession(path);
            session.insert(pos, text);
            callback();
        },
        append: function(path, text, callback) {
            var session = getSession(path);
            session.insert({
                row: session.getLength(),
                column: 0
            }, text);
            callback();
        },
        getPreceedingIdentifier: function(path, callback) {
            var session = getSession(path);
            var doc = session.getDocument();
            var pos = session.selection.getCursor();
            var line = doc.getLine(pos.row);

            var identBuf = [];
            for (var i = pos.column - 1; i >= 0; i--) {
                if (identifierRegex.test(line[i])) {
                    identBuf.push(line[i]);
                } else {
                    break;
                }
            }
            callback(null, identBuf.reverse().join(""));
        },
        getAllLines: function(path, callback) {
            callback(null, getSession(path).getDocument().getAllLines());
        },
        removeInLine: function(path, row, start, end, callback) {
            getSession(path).getDocument().removeInLine(row, start, end);
            callback();
        },
        removeLines: function(path, start, end, callback) {
            getSession(path).getDocument().removeLines(start, end);
            callback();
        },
        getSelectionRange: function(path, callback) {
            var range = getSession(path).selection.getRange();
            callback(null, {
                start: range.start,
                end: range.end
            });
        },
        getSelectionText: function(path, callback) {
            var session = getSession(path);
            var range = session.selection.getRange();
            callback(null, session.getTextRange(range));
        },
        getTextRange: function(path, start, end, callback) {
            callback(null, getSession(path).getTextRange(rangify({
                start: start,
                end: end
            })));
        },
        // getCursorIndex: partial(asyncInputable, "cursorIndex"),
        getCursorIndex: function(path, callback) {
            var inputable = "cursorIndex";
            callback(null, sandbox.getInputable(
                getSession(path), inputable));
        },
        setCursorIndex: function(path, index, callback) {
            var session = getSession(path);
            var text = session.getValue().slice(0, index);
            var lines = text.split("\n");
            var pos = {
                row: lines.length - 1,
                column: lines[lines.length - 1].length
            };
            session.selection.clearSelection();
            session.selection.moveCursorToPosition(pos);
            callback();
        },
        getCursorPosition: function(path, callback) {
            callback(null, getSession(path).selection.getCursor());
        },
        setCursorPosition: function(path, pos, callback) {
            var session = getSession(path);
            session.selection.clearSelection();
            session.selection.moveCursorToPosition(pos);
            callback();
        },
        getScrollPosition: function(path, callback) {
            var session = getSession(path);
            callback(null, {
                scrollTop: session.getScrollTop(),
                scrollLeft: session.getScrollLeft()
            });
        },
        setScrollPosition: function(path, pos, callback) {
            var session = getSession(path);
            session.setScrollTop(pos.scrollTop);
            session.setScrollLeft(pos.scrollLeft);
            callback();
        },
        replaceRange: function(path, range, text, callback) {
            var session = getSession(path);
            var cursorPos = session.selection.getCursor();

            session.replace(rangify(range), text);

            session.selection.clearSelection();
            session.selection.moveCursorToPosition(cursorPos);
            callback();
        },
        isInsertingSnippet: function(path, callback) {
            callback(null, editor.isInsertingSnippet());
        },
        flashMessage: function(path, message, length, callback) {<commit_msg>Use all available inputables to reduce code duplication.<commit_after>define(function(require, exports, module) {
    var session_manager = require("../../session_manager");
    var Range = require("ace/range").Range;
    var editor = require("../../editor");
    var sandbox = require("../../sandbox");
    var InlineAnnotation = require("../../lib/inline_annotation");
    var eventbus = require("../../lib/eventbus");

    function rangify(range) {
        return Range.fromPoints(range.start, range.end);
    }

    function getSession(path) {
        return path ? session_manager.getSessions()[path] : editor.getActiveSession();
    }

    // This function can take any defined inputable, a path, a callback,
    // and will call the callback with the result of the inputable for
    // the given path.
    function genericInputable(inputable, path, callback) {
        callback(null, sandbox.getInputable(
            getSession(path), inputable));
    }

    // This returns the above function bound to a given inputable, eg a function
    // that will take only path and callback arguments (as expected below), and
    // then call the callback with the result for the pre-determined inputable.
    function useInputable(inputable) {
        return genericInputable.bind(genericInputable, inputable);
    }

    var identifierRegex = /[a-zA-Z_0-9\$\-]/;

    return {
        getAllLines: useInputable("lines"),
        getCursorIndex: useInputable("cursorIndex"),
        getCursorPosition: useInputable("cursor"),
        getScrollPosition: useInputable("scrollPosition"),
        getSelectionRange: useInputable("selectionRange"),
        getSelectionText: useInputable("selectionText"),
        getText: useInputable("text"),
        isInsertingSnippet: useInputable("isInsertingSnippet"),
        goto: function(path, callback) {
            var edit = editor.getActiveEditor();
            session_manager.go(path, edit, edit.getSession(), function(err) {
                callback(err);
            });
        },
        setAnnotations: function(path, annos, callback) {
            var session = getSession(path);
            (session.annotations || []).forEach(function(anno) {
                console.log("Removing anno", anno);
                anno.remove();
            });
            session.annotations = [];
            for (var i = 0; i < annos.length; i++) {
                var anno = annos[i];
                // If no endColum, no inline marker is required
                if (anno.endColumn) {
                    session.annotations.push(new InlineAnnotation(session, anno));
                }
            }
            session.setAnnotations(annos);
            callback();
        },
        // Don't use setText unless you are really changing the entire contents
        // of the document, because it interacts poorly with the selection,
        // cursor position, undo history, etc.
        setText: function(path, text, callback) {
            var session = getSession(path);

            // Save scroll/cursor state
            var scrollTop = session.getScrollTop();
            var scrollLeft = session.getScrollLeft();
            var cursorPos = session.selection.getCursor();

            var lineCount = session.getLength();
            var range = new Range(0, 0, lineCount, session.getLine(lineCount - 1).length);

            session.replace(range, text);

            session.selection.clearSelection();
            session.selection.moveCursorToPosition(cursorPos);
            session.setScrollTop(scrollTop);
            session.setScrollLeft(scrollLeft);
            callback();
        },
        insertAtCursor: function(path, text, callback) {
            var session = getSession(path);
            session.insert(session.selection.getCursor(), text);
            callback();
        },
        insert: function(path, pos, text, callback) {
            var session = getSession(path);
            session.insert(pos, text);
            callback();
        },
        append: function(path, text, callback) {
            var session = getSession(path);
            session.insert({
                row: session.getLength(),
                column: 0
            }, text);
            callback();
        },
        getPreceedingIdentifier: function(path, callback) {
            var session = getSession(path);
            var doc = session.getDocument();
            var pos = session.selection.getCursor();
            var line = doc.getLine(pos.row);

            var identBuf = [];
            for (var i = pos.column - 1; i >= 0; i--) {
                if (identifierRegex.test(line[i])) {
                    identBuf.push(line[i]);
                } else {
                    break;
                }
            }
            callback(null, identBuf.reverse().join(""));
        },
        removeInLine: function(path, row, start, end, callback) {
            getSession(path).getDocument().removeInLine(row, start, end);
            callback();
        },
        removeLines: function(path, start, end, callback) {
            getSession(path).getDocument().removeLines(start, end);
            callback();
        },
        getTextRange: function(path, start, end, callback) {
            callback(null, getSession(path).getTextRange(rangify({
                start: start,
                end: end
            })));
        },
        setCursorIndex: function(path, index, callback) {
            var session = getSession(path);
            var text = session.getValue().slice(0, index);
            var lines = text.split("\n");
            var pos = {
                row: lines.length - 1,
                column: lines[lines.length - 1].length
            };
            session.selection.clearSelection();
            session.selection.moveCursorToPosition(pos);
            callback();
        },
        setCursorPosition: function(path, pos, callback) {
            var session = getSession(path);
            session.selection.clearSelection();
            session.selection.moveCursorToPosition(pos);
            callback();
        },
        setScrollPosition: function(path, pos, callback) {
            var session = getSession(path);
            session.setScrollTop(pos.scrollTop);
            session.setScrollLeft(pos.scrollLeft);
            callback();
        },
        replaceRange: function(path, range, text, callback) {
            var session = getSession(path);
            var cursorPos = session.selection.getCursor();

            session.replace(rangify(range), text);

            session.selection.clearSelection();
            session.selection.moveCursorToPosition(cursorPos);
            callback();
        },
        flashMessage: function(path, message, length, callback) {
{'fraction_non_alphanumeric': 0.11775594475295457, 'fraction_numerical': 0.0017086715079026058, 'mean_word_length': 1.8585673585673586, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '5369046', 'n_tokens_mistral': 3509, 'n_tokens_neox': 3399, 'n_words': 796}