<commit_before>/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, console*/
define(function (require, exports, module) {
    'use strict';
    
    var EditorManager       = brackets.getModule("editor/EditorManager"),
        CommandManager      = brackets.getModule("command/CommandManager"),
        Menus               = brackets.getModule("command/Menus"),
        Commands            = brackets.getModule("command/Commands"),
        KeyBindingManager   = brackets.getModule("command/KeyBindingManager"),
        AppInit             = brackets.getModule("utils/AppInit"),
        
        // Constants
        CHAR        = "character",
        WORD        = "word",
        LINE        = "line",
        MAX_LINE_LENGTH = 1000,
        
//        // Mark
//        isMarkSet   = false,

        // Text Selection Ring
        ring        = [],
        ringIndex   = 0,
        ringSize    = 15;
        
//    function setMarkCommand() {
//        isMarkSet = !isMarkSet;
//        
//        console.log("Mark " + (isMarkSet ? "un" : "") + "set");
//    }

    function _killRingSave(selectedText) {
        if (!selectedText) {
            return;
        }
        ring[ringIndex % ringSize] = selectedText;
        ringIndex++;
    }

    function killRingSave() {
        var editor  = EditorManager.getFocusedEditor();
        _killRingSave(editor.getSelectedText());
    }

    function killRegion(killLine) {
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            selection;
        if (killLine) {
            var start = editor.getCursorPos(),
                end = {line: start.line, ch: start.ch + MAX_LINE_LENGTH},
                text = doc.getRange(start, end);
            if (!text) {
                end.line++;
                end.ch = 0;
            }
            selection = {start: start, end: end};
            _killRingSave(text);
        } else {
            selection = editor.getSelection();
            _killRingSave(editor.getSelectedText());
        }
        doc.replaceRange("", selection.start, selection.end);
    }

    function yank() {
        if (ring.length === 0) {
            return;
        }
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            cursorPos   = editor.getCursorPos();
        doc.replaceRange(ring[(ringIndex - 1) % ringSize], cursorPos);
    }

//    function iSearchBackward() {
//        // @todo: stub
//    }
    
    /**
     * Function to move the cursor
     *
     * @param   {number}    unit        Number of units to move
     * @param   {number}    type        CHAR|WORD|LINE
     * @param   {boolean}   absolute    Flag to specify if the cursor isn't moved relative to the current
     *                                  position
     */
    function moveCursor(unit, type, absolute) {
        var editor      = EditorManager.getFocusedEditor(),
            cursorPos   = editor.getCursorPos(),
            line        = cursorPos.line,
            column        = cursorPos.ch;
        switch (type) {
        case CHAR:
            column += unit - (absolute ? column : 0);
            break;
        case LINE:
            line += unit - (absolute ? line : 0);
            break;
        case WORD:
            if (Math.abs(unit) !== 1) {
                console.error("Cursor positioning for multiple words is not supported");
                return;
            }
            var text = editor.document.getLine(line),
                lineLength = text.length;
            if (unit === 1) {
                text = text.substring(column);
            } else {
                // @todo: use a better implementation for reversing a string
                // http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
                text = text.split("").reverse().join("").substring(lineLength - column);
            }
                
            var indexOfNextWord = text.search(/\W\w/) + 1;
            if (indexOfNextWord > 0) {
                column += (unit * indexOfNextWord) - (absolute ? column : 0);
            } else {
                line += unit > 0 ? 1 : -1;
                column = MAX_LINE_LENGTH;
            }
            break;
        }
        editor.setCursorPos(line, column);
    }
    
    AppInit.appReady(function () {

        var menus = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU),
            
            // Command Ids
            MOVE_BEGINNING_OF_LINE  = "emacs.move-beginning-of-line",
            MOVE_END_OF_LINE        = "emacs.move-end-of-line",
            YANK                    = "emacs.yank",
            KILL_REGION             = "emacs.kill-region",
            KILL_RING_SAVE          = "emacs.kill-ring-save",
            KILL_LINE               = "emacs.kill-line",
            FORWARD_CHAR            = "emacs.forward-char",
            BACKWARD_CHAR           = "emacs.backward-char",
            FORWARD_WORD            = "emacs.forward-word",
            BACKWARD_WORD           = "emacs.backward-word",
            PREVIOUS_LINE           = "emacs.previous-line",
            NEXT_LINE               = "emacs.next-line",
            PREFIX_COMMAND          = "emacs.prefix-command",
            UNDO                    = "emacs.undo",
            ISEARCH_FORWARD         = "emacs.isearch-forward",
            FIND_FILE               = "emacs.find-file",
            SAVE_BUFFER             = "emacs.save-buffer",
            COMMENT_DWIM            = "emacs.comment-dwim",
            // .. not implemented ..
            SET_MARK_COMMAND        = "emacs.set-mark-command",
            ISEARCH_BACKWARD        = "emacs.isearch-backward",

            /*
             * Emacs commands
             *
             * Find list of commands in emacs: Ctrl-h b
             */
            commands = [
                {
                    id:         MOVE_BEGINNING_OF_LINE,
                    name:       "Move Beginning of Line",
                    key:        "Ctrl-A",
                    callback:   moveCursor.bind(this, 0, CHAR, true)
                },
                {
                    id:         MOVE_END_OF_LINE,
                    name:       "Move End of Line",
                    key:        "Ctrl-E",
                    callback:   moveCursor.bind(this, MAX_LINE_LENGTH, CHAR, true)
                },
                {
                    id:         YANK,
                    name:       "Yank",
                    key:        "Ctrl-Y",
                    callback:   yank
                },
                {
                    id:         KILL_REGION,
                    name:       "Kill Region",
                    key:        "Ctrl-W",
                    callback:   killRegion
                },
                {
                    id:         KILL_RING_SAVE,
                    name:       "Kill Ring Save",
                    key:        "Alt-W",
                    callback:   killRingSave
                },
                {
                    id:         KILL_LINE,
                    name:       "Kill Ring Save",
                    key:        "Ctrl-K",
                    callback:   killRegion.bind(null, true)
                },

//                {
//                    id:         ISEARCH_BACKWARD,
//                    name:       "Incremental Search Backward",
//                    key:        "Ctrl-R",
//                    callback:   iSearchBackward
//                },
                {
                    id:         FORWARD_CHAR,
                    name:       "Forward Character",
                    key:        "Ctrl-F",
                    callback:   moveCursor.bind(this, 1, CHAR)
                },
                {
                    id:         BACKWARD_CHAR,
                    name:       "Backward Character",
                    key:        "Ctrl-B",
                    callback:   moveCursor.bind(this, -1, CHAR)
                },
                {
                    id:         FORWARD_WORD,
                    name:       "Forward Word",
                    key:        "Alt-F",
                    callback:   moveCursor.bind(this, 1, WORD)
                },
                {
                    id:         BACKWARD_WORD,
                    name:       "Backward Word",
                    key:        "Alt-B",
                    callback:   moveCursor.bind(this, -1, WORD)
                },
                {
                    id:         NEXT_LINE,
                    name:       "Next Line",
                    key:        "Ctrl-N",
                    callback:   moveCursor.bind(this, 1, LINE)
                },
                {
                    id:         PREVIOUS_LINE,
                    name:       "Previous Line",
                    key:        "Ctrl-P",
                    callback:   moveCursor.bind(this, -1, LINE)
                },
                {
                    id:         PREFIX_COMMAND,
                    name:       "Prefix Command",
                    key:        "Ctrl-X",
                    commands:   [
                        {
                            id:         FIND_FILE,
                            key:        "Ctrl-F",
                            overrideId:   Commands.FILE_OPEN
                        },
                        {
                            id:         SAVE_BUFFER,
                            key:        "Ctrl-S",
                            overrideId:   Commands.FILE_SAVE
                        }
                    ]
                },
                {
                    id:         UNDO,
                    name:       "Undo",
                    key:        "Ctrl-/",
                    overrideId:   Commands.EDIT_UNDO
                },
                {
                    id:         COMMENT_DWIM,
                    name:       "Comment (Do What I Mean)",
                    key:        "Alt-;",
                    overrideId:   Commands.EDIT_LINE_COMMENT
                },
                {
                    id:         ISEARCH_FORWARD,
                    name:       "ISearch Forward",
                    key:        "Ctrl-S",
                    overrideId:   Commands.EDIT_FIND
                }
//              {
//                  id:         SET_MARK_COMMAND,
//                  name:       "Set Mark Command",
//                  key:        "Ctrl-Space",
//                  callback:   setMarkCommand
//              }
            ];


        /**
         * EventHandler Class
         *
         * Executes relevant commands when any of the specified keys are used.
         *
         * @param   {Array} commands    Commands that can be used for the next key.
         *
         * @todo: move the EventHandler to a separate module
         */
        function EventHandler(allCommands) {
            this.availableCommands = allCommands; // @todo: no need to copy array, right?
        }

        EventHandler.prototype.commands = commands;
        
        EventHandler.prototype.availableCommands = undefined; // set on instantiation
        
        EventHandler.prototype.getCommand = function (key) {
            var command = this.availableCommands.filter(function find(command) {
                return (command.key === key) ? command : false;
            });
            if (command.length === 0) { // not found
                return false;
            }
            return command[0]; // get the first match, there should only be one
        };

        /**
         * Function for reseting the context i.e. the number of available commands are not dependent on the last key used
         *
         * @param   {Array} commands    Commands that can be used for the next key.
         */
        EventHandler.prototype.resetContext = function (commands) {
            this.availableCommands = commands || this.commands;
        };

        EventHandler.prototype.handle = function (key) {
            // Get the command to execute based on the stack
            var command = this.getCommand(key);
            
            if (!command) {
                this.resetContext();
                return;
            }
            
            if (!command.commands) {
                if (command.overrideId) {
                    CommandManager.execute(command.overrideId);
                } else {
                    command.callback();
                }
            }
            
            // Update the context
            this.resetContext(command.commands || undefined);
        };
        
        var handler = new EventHandler(commands);

        function removeBinding(command) {
            KeyBindingManager.removeBinding(command.key);
            if (typeof command.commands !== "undefined" && command.commands.length > 0) {
                command.commands.forEach(removeBinding);
            }
        }

        function addBinding(command) {
            KeyBindingManager.addBinding(command.id, command.key);
        }

        function register(command) {
            CommandManager.register(command.name,
                                    command.id,
                                    handler.handle.bind(handler, command.key));
            menus.addMenuItem(command.id);
        }

        // @todo: using setTimeout since key module takes some time to load        
        window.setTimeout(function () {
            menus.addMenuItem(Menus.DIVIDER);
            commands.forEach(removeBinding);
            commands.forEach(register);
            commands.forEach(addBinding);
        }, 500);
         
    });
});<commit_msg>Preserving the newline i.e. \n when kill-line is used at the end of the line.<commit_after>/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, console*/
define(function (require, exports, module) {
    'use strict';
    
    var EditorManager       = brackets.getModule("editor/EditorManager"),
        CommandManager      = brackets.getModule("command/CommandManager"),
        Menus               = brackets.getModule("command/Menus"),
        Commands            = brackets.getModule("command/Commands"),
        KeyBindingManager   = brackets.getModule("command/KeyBindingManager"),
        AppInit             = brackets.getModule("utils/AppInit"),
        
        // Constants
        CHAR        = "character",
        WORD        = "word",
        LINE        = "line",
        MAX_LINE_LENGTH = 1000,
        
//        // Mark
//        isMarkSet   = false,

        // Text Selection Ring
        ring        = [],
        ringIndex   = 0,
        ringSize    = 15;
        
//    function setMarkCommand() {
//        isMarkSet = !isMarkSet;
//        
//        console.log("Mark " + (isMarkSet ? "un" : "") + "set");
//    }

    function _killRingSave(selectedText) {
        if (!selectedText) {
            return;
        }
        ring[ringIndex % ringSize] = selectedText;
        ringIndex++;
    }

    function killRingSave() {
        var editor  = EditorManager.getFocusedEditor();
        _killRingSave(editor.getSelectedText());
    }

    function killRegion(killLine) {
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            selection;
        if (killLine) {
            var start = editor.getCursorPos(),
                end = {line: start.line, ch: start.ch + MAX_LINE_LENGTH},
                text = doc.getRange(start, end);
            if (!text) {
                end.line++;
                end.ch = 0;
                text = "\n";
            }
            selection = {start: start, end: end};
            _killRingSave(text);
        } else {
            selection = editor.getSelection();
            _killRingSave(editor.getSelectedText());
        }
        doc.replaceRange("", selection.start, selection.end);
    }

    function yank() {
        if (ring.length === 0) {
            return;
        }
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            cursorPos   = editor.getCursorPos();
        doc.replaceRange(ring[(ringIndex - 1) % ringSize], cursorPos);
    }

//    function iSearchBackward() {
//        // @todo: stub
//    }
    
    /**
     * Function to move the cursor
     *
     * @param   {number}    unit        Number of units to move
     * @param   {number}    type        CHAR|WORD|LINE
     * @param   {boolean}   absolute    Flag to specify if the cursor isn't moved relative to the current
     *                                  position
     */
    function moveCursor(unit, type, absolute) {
        var editor      = EditorManager.getFocusedEditor(),
            cursorPos   = editor.getCursorPos(),
            line        = cursorPos.line,
            column        = cursorPos.ch;
        switch (type) {
        case CHAR:
            column += unit - (absolute ? column : 0);
            break;
        case LINE:
            line += unit - (absolute ? line : 0);
            break;
        case WORD:
            if (Math.abs(unit) !== 1) {
                console.error("Cursor positioning for multiple words is not supported");
                return;
            }
            var text = editor.document.getLine(line),
                lineLength = text.length;
            if (unit === 1) {
                text = text.substring(column);
            } else {
                // @todo: use a better implementation for reversing a string
                // http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
                text = text.split("").reverse().join("").substring(lineLength - column);
            }
                
            var indexOfNextWord = text.search(/\W\w/) + 1;
            if (indexOfNextWord > 0) {
                column += (unit * indexOfNextWord) - (absolute ? column : 0);
            } else {
                line += unit > 0 ? 1 : -1;
                column = MAX_LINE_LENGTH;
            }
            break;
        }
        editor.setCursorPos(line, column);
    }
    
    AppInit.appReady(function () {

        var menus = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU),
            
            // Command Ids
            MOVE_BEGINNING_OF_LINE  = "emacs.move-beginning-of-line",
            MOVE_END_OF_LINE        = "emacs.move-end-of-line",
            YANK                    = "emacs.yank",
            KILL_REGION             = "emacs.kill-region",
            KILL_RING_SAVE          = "emacs.kill-ring-save",
            KILL_LINE               = "emacs.kill-line",
            FORWARD_CHAR            = "emacs.forward-char",
            BACKWARD_CHAR           = "emacs.backward-char",
            FORWARD_WORD            = "emacs.forward-word",
            BACKWARD_WORD           = "emacs.backward-word",
            PREVIOUS_LINE           = "emacs.previous-line",
            NEXT_LINE               = "emacs.next-line",
            PREFIX_COMMAND          = "emacs.prefix-command",
            UNDO                    = "emacs.undo",
            ISEARCH_FORWARD         = "emacs.isearch-forward",
            FIND_FILE               = "emacs.find-file",
            SAVE_BUFFER             = "emacs.save-buffer",
            COMMENT_DWIM            = "emacs.comment-dwim",
            // .. not implemented ..
            SET_MARK_COMMAND        = "emacs.set-mark-command",
            ISEARCH_BACKWARD        = "emacs.isearch-backward",

            /*
             * Emacs commands
             *
             * Find list of commands in emacs: Ctrl-h b
             */
            commands = [
                {
                    id:         MOVE_BEGINNING_OF_LINE,
                    name:       "Move Beginning of Line",
                    key:        "Ctrl-A",
                    callback:   moveCursor.bind(this, 0, CHAR, true)
                },
                {
                    id:         MOVE_END_OF_LINE,
                    name:       "Move End of Line",
                    key:        "Ctrl-E",
                    callback:   moveCursor.bind(this, MAX_LINE_LENGTH, CHAR, true)
                },
                {
                    id:         YANK,
                    name:       "Yank",
                    key:        "Ctrl-Y",
                    callback:   yank
                },
                {
                    id:         KILL_REGION,
                    name:       "Kill Region",
                    key:        "Ctrl-W",
                    callback:   killRegion
                },
                {
                    id:         KILL_RING_SAVE,
                    name:       "Kill Ring Save",
                    key:        "Alt-W",
                    callback:   killRingSave
                },
                {
                    id:         KILL_LINE,
                    name:       "Kill Ring Save",
                    key:        "Ctrl-K",
                    callback:   killRegion.bind(null, true)
                },

//                {
//                    id:         ISEARCH_BACKWARD,
//                    name:       "Incremental Search Backward",
//                    key:        "Ctrl-R",
//                    callback:   iSearchBackward
//                },
                {
                    id:         FORWARD_CHAR,
                    name:       "Forward Character",
                    key:        "Ctrl-F",
                    callback:   moveCursor.bind(this, 1, CHAR)
                },
                {
                    id:         BACKWARD_CHAR,
                    name:       "Backward Character",
                    key:        "Ctrl-B",
                    callback:   moveCursor.bind(this, -1, CHAR)
                },
                {
                    id:         FORWARD_WORD,
                    name:       "Forward Word",
                    key:        "Alt-F",
                    callback:   moveCursor.bind(this, 1, WORD)
                },
                {
                    id:         BACKWARD_WORD,
                    name:       "Backward Word",
                    key:        "Alt-B",
                    callback:   moveCursor.bind(this, -1, WORD)
                },
                {
                    id:         NEXT_LINE,
                    name:       "Next Line",
                    key:        "Ctrl-N",
                    callback:   moveCursor.bind(this, 1, LINE)
                },
                {
                    id:         PREVIOUS_LINE,
                    name:       "Previous Line",
                    key:        "Ctrl-P",
                    callback:   moveCursor.bind(this, -1, LINE)
                },
                {
                    id:         PREFIX_COMMAND,
                    name:       "Prefix Command",
                    key:        "Ctrl-X",
                    commands:   [
                        {
                            id:         FIND_FILE,
                            key:        "Ctrl-F",
                            overrideId:   Commands.FILE_OPEN
                        },
                        {
                            id:         SAVE_BUFFER,
                            key:        "Ctrl-S",
                            overrideId:   Commands.FILE_SAVE
                        }
                    ]
                },
                {
                    id:         UNDO,
                    name:       "Undo",
                    key:        "Ctrl-/",
                    overrideId:   Commands.EDIT_UNDO
                },
                {
                    id:         COMMENT_DWIM,
                    name:       "Comment (Do What I Mean)",
                    key:        "Alt-;",
                    overrideId:   Commands.EDIT_LINE_COMMENT
                },
                {
                    id:         ISEARCH_FORWARD,
                    name:       "ISearch Forward",
                    key:        "Ctrl-S",
                    overrideId:   Commands.EDIT_FIND
                }
//              {
//                  id:         SET_MARK_COMMAND,
//                  name:       "Set Mark Command",
//                  key:        "Ctrl-Space",
//                  callback:   setMarkCommand
//              }
            ];


        /**
         * EventHandler Class
         *
         * Executes relevant commands when any of the specified keys are used.
         *
         * @param   {Array} commands    Commands that can be used for the next key.
         *
         * @todo: move the EventHandler to a separate module
         */
        function EventHandler(allCommands) {
            this.availableCommands = allCommands; // @todo: no need to copy array, right?
        }

        EventHandler.prototype.commands = commands;
        
        EventHandler.prototype.availableCommands = undefined; // set on instantiation
        
        EventHandler.prototype.getCommand = function (key) {
            var command = this.availableCommands.filter(function find(command) {
                return (command.key === key) ? command : false;
            });
            if (command.length === 0) { // not found
                return false;
            }
            return command[0]; // get the first match, there should only be one
        };

        /**
         * Function for reseting the context i.e. the number of available commands are not dependent on the last key used
         *
         * @param   {Array} commands    Commands that can be used for the next key.
         */
        EventHandler.prototype.resetContext = function (commands) {
            this.availableCommands = commands || this.commands;
        };

        EventHandler.prototype.handle = function (key) {
            // Get the command to execute based on the stack
            var command = this.getCommand(key);
            
            if (!command) {
                this.resetContext();
                return;
            }
            
            if (!command.commands) {
                if (command.overrideId) {
                    CommandManager.execute(command.overrideId);
                } else {
                    command.callback();
                }
            }
            
            // Update the context
            this.resetContext(command.commands || undefined);
        };
        
        var handler = new EventHandler(commands);

        function removeBinding(command) {
            KeyBindingManager.removeBinding(command.key);
            if (typeof command.commands !== "undefined" && command.commands.length > 0) {
                command.commands.forEach(removeBinding);
            }
        }

        function addBinding(command) {
            KeyBindingManager.addBinding(command.id, command.key);
        }

        function register(command) {
            CommandManager.register(command.name,
                                    command.id,
                                    handler.handle.bind(handler, command.key));
            menus.addMenuItem(command.id);
        }

        // @todo: using setTimeout since key module takes some time to load        
        window.setTimeout(function () {
            menus.addMenuItem(Menus.DIVIDER);
            commands.forEach(removeBinding);
            commands.forEach(register);
            commands.forEach(addBinding);
        }, 500);
         
    });
});
{'fraction_non_alphanumeric': 0.09568718488156988, 'fraction_numerical': 0.0026116290035909898, 'mean_word_length': 1.004216341959872, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '541761', 'n_tokens_mistral': 7132, 'n_tokens_neox': 6631, 'n_words': 1454}