<commit_before>/*
 * This file is part of gorilla-repl. Copyright (C) 2014-, <NAME>.
 *
 * gorilla-repl is licenced to you under the MIT licence. See the file LICENCE.txt for full details.
 */

// This viewmodel represents the worksheet document itself. Code to manage the "cursor" that is, the highlight on the
// active segment, and the position of the editor cursors, is in the worksheet, as it needs to know about the
// relationship between the segments.
var worksheet = function () {
    var self = {};

    // the content of the worksheet is a list of segments.
    self.segments = ko.observableArray();

    // serialises the worksheet for saving. The result is valid clojure code, marked up with some magic comments.
    self.toClojure = function () {
        return ";; gorilla-repl.fileformat = 1\n\n" +
            self.segments().map(function (s) {
                return s.toClojure()
            }).join('\n');
    };

    // ** Segment management helpers **

    self.segmentIndexForID = function (id) {
        // so, this is not perhaps the most efficient way you could think of doing this, but for reasonable conditions
        // it will be fine.
        for (var i = 0; i < self.segments().length; i++) {
            if (self.segments()[i].id == id) return i;
        }
        // this had better never happen!
        return -1;
    };

    self.getSegmentForID = function (id) {
        var index = self.segmentIndexForID(id);
        if (index >= 0) return self.segments()[index];
        else return null;
    };

    self.activeSegmentIndex = null;

    self.getActiveSegment = function () {
        if (self.activeSegmentIndex != null) return self.segments()[self.activeSegmentIndex];
        else return null;
    };

    self.activateSegment = function (index, fromTop) {
        self.segments()[index].activate(fromTop);
        self.activeSegmentIndex = index;
    };

    self.deactivateSegment = function (index) {
        self.segments()[index].deactivate();
        self.activeSegmentIndex = null;
    };

    self.deleteSegment = function (index) {
        self.segments.splice(index, 1);
    };

    // an offset of 1 inserts below the active segment, 0 above.
    self.insertNewSegment = function (offset) {
        // do nothing if no segment is active
        if (self.activeSegmentIndex == null) return;
        var seg = codeSegment("");
        var currentIndex = self.activeSegmentIndex;
        self.deactivateSegment(currentIndex);
        self.segments.splice(currentIndex + offset, 0, seg);
        self.activateSegment(currentIndex + offset);
    };

    self.moveSegment = function (up) {
        var index = self.activeSegmentIndex;
        if (index == null) return;
        if (up) {
            // can't move top segment up
            if (index == 0) return;
        } else {
            // or bottom segment down
            if (index == self.segments().length -1) return;
        }
        self.deactivateSegment(index);
        var offset = up ? -1 : 1;
        self.segments.splice(index + offset, 0, self.segments.splice(index, 1)[0]);
        self.activateSegment(index + offset);
    };


    // ** Event handlers **
    // TODO: this is slightly nasty. The event handlers close over worksheet properties, so need to be removed and re-
    // TODO: added whenever the worksheet is changed. Maybe they shouldn't live here?

    // We store a list of added event types, by using this helper function to add events. This allows us to cleanly
    // deregister all the event handlers if the worksheet is to be replaced.
    var eventTypeList = [];
    var addEventHandler = function (event, callback) {
        eventTypeList.push(event);
        eventBus.on(event, callback);
    };
    // remove all worksheet event handlers from the bus - note that this will remove event handlers for _all_ worksheets
    // that exist, not just this one!
    self.removeEventHandlers = function () {
        eventTypeList.map(function (e) {eventBus.off(e);});
    };

    self.addEventHandlers = function () {
        // * Activation cursor / focus handling *

        // activation/deactivation and focusing of segments.
        addEventHandler("worksheet:leaveForward", function () {
            var leavingIndex = self.activeSegmentIndex;
            // can't leave the bottom segment forwards
            if (leavingIndex == self.segments().length - 1) return;
            self.deactivateSegment(leavingIndex);
            self.activateSegment(leavingIndex + 1, true);
        });

        addEventHandler("worksheet:leaveBack", function () {
            var leavingIndex = self.activeSegmentIndex;
            // can't leave the top segment upwards
            if (leavingIndex == 0) return;
            self.deactivateSegment(leavingIndex);
            self.activateSegment(leavingIndex - 1, false);
        });

        // the event for this action contains the segment id
        addEventHandler("worksheet:segment-clicked", function (e, d) {
            if (self.activeSegmentIndex != null) self.deactivateSegment(self.activeSegmentIndex);
            var focusIndex = self.segmentIndexForID(d.id);
            self.activateSegment(focusIndex, true);
        });

        // * Manipulating segments *

        // this is called if the delete command is issued ...
        addEventHandler("worksheet:delete", function () {
            // if there's only one segment, don't delete it<commit_msg>Don't refocus already focussed segment. Fixes #108.<commit_after>/*
 * This file is part of gorilla-repl. Copyright (C) 2014-, <NAME>.
 *
 * gorilla-repl is licenced to you under the MIT licence. See the file LICENCE.txt for full details.
 */

// This viewmodel represents the worksheet document itself. Code to manage the "cursor" that is, the highlight on the
// active segment, and the position of the editor cursors, is in the worksheet, as it needs to know about the
// relationship between the segments.
var worksheet = function () {
    var self = {};

    // the content of the worksheet is a list of segments.
    self.segments = ko.observableArray();

    // serialises the worksheet for saving. The result is valid clojure code, marked up with some magic comments.
    self.toClojure = function () {
        return ";; gorilla-repl.fileformat = 1\n\n" +
            self.segments().map(function (s) {
                return s.toClojure()
            }).join('\n');
    };

    // ** Segment management helpers **

    self.segmentIndexForID = function (id) {
        // so, this is not perhaps the most efficient way you could think of doing this, but for reasonable conditions
        // it will be fine.
        for (var i = 0; i < self.segments().length; i++) {
            if (self.segments()[i].id == id) return i;
        }
        // this had better never happen!
        return -1;
    };

    self.getSegmentForID = function (id) {
        var index = self.segmentIndexForID(id);
        if (index >= 0) return self.segments()[index];
        else return null;
    };

    self.activeSegmentIndex = null;

    self.getActiveSegment = function () {
        if (self.activeSegmentIndex != null) return self.segments()[self.activeSegmentIndex];
        else return null;
    };

    self.activateSegment = function (index, fromTop) {
        self.segments()[index].activate(fromTop);
        self.activeSegmentIndex = index;
    };

    self.deactivateSegment = function (index) {
        self.segments()[index].deactivate();
        self.activeSegmentIndex = null;
    };

    self.deleteSegment = function (index) {
        self.segments.splice(index, 1);
    };

    // an offset of 1 inserts below the active segment, 0 above.
    self.insertNewSegment = function (offset) {
        // do nothing if no segment is active
        if (self.activeSegmentIndex == null) return;
        var seg = codeSegment("");
        var currentIndex = self.activeSegmentIndex;
        self.deactivateSegment(currentIndex);
        self.segments.splice(currentIndex + offset, 0, seg);
        self.activateSegment(currentIndex + offset);
    };

    self.moveSegment = function (up) {
        var index = self.activeSegmentIndex;
        if (index == null) return;
        if (up) {
            // can't move top segment up
            if (index == 0) return;
        } else {
            // or bottom segment down
            if (index == self.segments().length -1) return;
        }
        self.deactivateSegment(index);
        var offset = up ? -1 : 1;
        self.segments.splice(index + offset, 0, self.segments.splice(index, 1)[0]);
        self.activateSegment(index + offset);
    };


    // ** Event handlers **
    // TODO: this is slightly nasty. The event handlers close over worksheet properties, so need to be removed and re-
    // TODO: added whenever the worksheet is changed. Maybe they shouldn't live here?

    // We store a list of added event types, by using this helper function to add events. This allows us to cleanly
    // deregister all the event handlers if the worksheet is to be replaced.
    var eventTypeList = [];
    var addEventHandler = function (event, callback) {
        eventTypeList.push(event);
        eventBus.on(event, callback);
    };
    // remove all worksheet event handlers from the bus - note that this will remove event handlers for _all_ worksheets
    // that exist, not just this one!
    self.removeEventHandlers = function () {
        eventTypeList.map(function (e) {eventBus.off(e);});
    };

    self.addEventHandlers = function () {
        // * Activation cursor / focus handling *

        // activation/deactivation and focusing of segments.
        addEventHandler("worksheet:leaveForward", function () {
            var leavingIndex = self.activeSegmentIndex;
            // can't leave the bottom segment forwards
            if (leavingIndex == self.segments().length - 1) return;
            self.deactivateSegment(leavingIndex);
            self.activateSegment(leavingIndex + 1, true);
        });

        addEventHandler("worksheet:leaveBack", function () {
            var leavingIndex = self.activeSegmentIndex;
            // can't leave the top segment upwards
            if (leavingIndex == 0) return;
            self.deactivateSegment(leavingIndex);
            self.activateSegment(leavingIndex - 1, false);
        });

        // the event for this action contains the segment id
        addEventHandler("worksheet:segment-clicked", function (e, d) {
            // don't do anything if this segment is already selected
            var focusIndex = self.segmentIndexForID(d.id);
            if (self.activeSegmentIndex == focusIndex) return;
            if (self.activeSegmentIndex != null) self.deactivateSegment(self.activeSegmentIndex);
            self.activateSegment(focusIndex, true);
        });

        // * Manipulating segments *

        // this is called if the delete command is issued ...
        addEventHandler("worksheet:delete", function () {
            // if there's only one segment, don't delete it
{'fraction_non_alphanumeric': 0.10439262472885033, 'fraction_numerical': 0.0044287780187997105, 'mean_word_length': 2.3621999392281983, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '5086961', 'n_tokens_mistral': 3017, 'n_tokens_neox': 2892, 'n_words': 988}