diff options
Diffstat (limited to 'atom/packages/vim-mode/lib/vim-state.coffee')
| -rw-r--r-- | atom/packages/vim-mode/lib/vim-state.coffee | 680 |
1 files changed, 0 insertions, 680 deletions
diff --git a/atom/packages/vim-mode/lib/vim-state.coffee b/atom/packages/vim-mode/lib/vim-state.coffee deleted file mode 100644 index db59ee5..0000000 --- a/atom/packages/vim-mode/lib/vim-state.coffee +++ /dev/null @@ -1,680 +0,0 @@ -Grim = require 'grim' -_ = require 'underscore-plus' -{Point, Range} = require 'atom' -{Emitter, Disposable, CompositeDisposable} = require 'event-kit' -settings = require './settings' - -Operators = require './operators/index' -Prefixes = require './prefixes' -Motions = require './motions/index' -InsertMode = require './insert-mode' - -TextObjects = require './text-objects' -Utils = require './utils' -Scroll = require './scroll' - -module.exports = -class VimState - editor: null - opStack: null - mode: null - submode: null - destroyed: false - replaceModeListener: null - - constructor: (@editorElement, @statusBarManager, @globalVimState) -> - @emitter = new Emitter - @subscriptions = new CompositeDisposable - @editor = @editorElement.getModel() - @opStack = [] - @history = [] - @marks = {} - @subscriptions.add @editor.onDidDestroy => @destroy() - - @editorElement.addEventListener 'mouseup', @checkSelections - if atom.commands.onDidDispatch? - @subscriptions.add atom.commands.onDidDispatch (e) => - if e.target is @editorElement - @checkSelections() - - @editorElement.classList.add("vim-mode") - @setupNormalMode() - if settings.startInInsertMode() - @activateInsertMode() - else - @activateNormalMode() - - destroy: -> - unless @destroyed - @destroyed = true - @subscriptions.dispose() - if @editor.isAlive() - @deactivateInsertMode() - @editorElement.component?.setInputEnabled(true) - @editorElement.classList.remove("vim-mode") - @editorElement.classList.remove("normal-mode") - @editorElement.removeEventListener 'mouseup', @checkSelections - @editor = null - @editorElement = null - @emitter.emit 'did-destroy' - - # Private: Creates the plugin's bindings - # - # Returns nothing. - setupNormalMode: -> - @registerCommands - 'activate-normal-mode': => @activateNormalMode() - 'activate-linewise-visual-mode': => @activateVisualMode('linewise') - 'activate-characterwise-visual-mode': => @activateVisualMode('characterwise') - 'activate-blockwise-visual-mode': => @activateVisualMode('blockwise') - 'reset-normal-mode': => @resetNormalMode() - 'repeat-prefix': (e) => @repeatPrefix(e) - 'reverse-selections': (e) => @reverseSelections(e) - 'undo': (e) => @undo(e) - 'replace-mode-backspace': => @replaceModeUndo() - 'insert-mode-put': (e) => @insertRegister(@registerName(e)) - 'copy-from-line-above': => InsertMode.copyCharacterFromAbove(@editor, this) - 'copy-from-line-below': => InsertMode.copyCharacterFromBelow(@editor, this) - - @registerOperationCommands - 'activate-insert-mode': => new Operators.Insert(@editor, this) - 'activate-replace-mode': => new Operators.ReplaceMode(@editor, this) - 'substitute': => [new Operators.Change(@editor, this), new Motions.MoveRight(@editor, this)] - 'substitute-line': => [new Operators.Change(@editor, this), new Motions.MoveToRelativeLine(@editor, this)] - 'insert-after': => new Operators.InsertAfter(@editor, this) - 'insert-after-end-of-line': => new Operators.InsertAfterEndOfLine(@editor, this) - 'insert-at-beginning-of-line': => new Operators.InsertAtBeginningOfLine(@editor, this) - 'insert-above-with-newline': => new Operators.InsertAboveWithNewline(@editor, this) - 'insert-below-with-newline': => new Operators.InsertBelowWithNewline(@editor, this) - 'delete': => @linewiseAliasedOperator(Operators.Delete) - 'change': => @linewiseAliasedOperator(Operators.Change) - 'change-to-last-character-of-line': => [new Operators.Change(@editor, this), new Motions.MoveToLastCharacterOfLine(@editor, this)] - 'delete-right': => [new Operators.Delete(@editor, this), new Motions.MoveRight(@editor, this)] - 'delete-left': => [new Operators.Delete(@editor, this), new Motions.MoveLeft(@editor, this)] - 'delete-to-last-character-of-line': => [new Operators.Delete(@editor, this), new Motions.MoveToLastCharacterOfLine(@editor, this)] - 'toggle-case': => new Operators.ToggleCase(@editor, this) - 'upper-case': => new Operators.UpperCase(@editor, this) - 'lower-case': => new Operators.LowerCase(@editor, this) - 'toggle-case-now': => new Operators.ToggleCase(@editor, this, complete: true) - 'yank': => @linewiseAliasedOperator(Operators.Yank) - 'yank-line': => [new Operators.Yank(@editor, this), new Motions.MoveToRelativeLine(@editor, this)] - 'put-before': => new Operators.Put(@editor, this, location: 'before') - 'put-after': => new Operators.Put(@editor, this, location: 'after') - 'join': => new Operators.Join(@editor, this) - 'indent': => @linewiseAliasedOperator(Operators.Indent) - 'outdent': => @linewiseAliasedOperator(Operators.Outdent) - 'auto-indent': => @linewiseAliasedOperator(Operators.Autoindent) - 'increase': => new Operators.Increase(@editor, this) - 'decrease': => new Operators.Decrease(@editor, this) - 'move-left': => new Motions.MoveLeft(@editor, this) - 'move-up': => new Motions.MoveUp(@editor, this) - 'move-down': => new Motions.MoveDown(@editor, this) - 'move-right': => new Motions.MoveRight(@editor, this) - 'move-to-next-word': => new Motions.MoveToNextWord(@editor, this) - 'move-to-next-whole-word': => new Motions.MoveToNextWholeWord(@editor, this) - 'move-to-end-of-word': => new Motions.MoveToEndOfWord(@editor, this) - 'move-to-end-of-whole-word': => new Motions.MoveToEndOfWholeWord(@editor, this) - 'move-to-previous-word': => new Motions.MoveToPreviousWord(@editor, this) - 'move-to-previous-whole-word': => new Motions.MoveToPreviousWholeWord(@editor, this) - 'move-to-next-paragraph': => new Motions.MoveToNextParagraph(@editor, this) - 'move-to-previous-paragraph': => new Motions.MoveToPreviousParagraph(@editor, this) - 'move-to-first-character-of-line': => new Motions.MoveToFirstCharacterOfLine(@editor, this) - 'move-to-first-character-of-line-and-down': => new Motions.MoveToFirstCharacterOfLineAndDown(@editor, this) - 'move-to-last-character-of-line': => new Motions.MoveToLastCharacterOfLine(@editor, this) - 'move-to-last-nonblank-character-of-line-and-down': => new Motions.MoveToLastNonblankCharacterOfLineAndDown(@editor, this) - 'move-to-beginning-of-line': (e) => @moveOrRepeat(e) - 'move-to-first-character-of-line-up': => new Motions.MoveToFirstCharacterOfLineUp(@editor, this) - 'move-to-first-character-of-line-down': => new Motions.MoveToFirstCharacterOfLineDown(@editor, this) - 'move-to-start-of-file': => new Motions.MoveToStartOfFile(@editor, this) - 'move-to-line': => new Motions.MoveToAbsoluteLine(@editor, this) - 'move-to-top-of-screen': => new Motions.MoveToTopOfScreen(@editorElement, this) - 'move-to-bottom-of-screen': => new Motions.MoveToBottomOfScreen(@editorElement, this) - 'move-to-middle-of-screen': => new Motions.MoveToMiddleOfScreen(@editorElement, this) - 'scroll-down': => new Scroll.ScrollDown(@editorElement) - 'scroll-up': => new Scroll.ScrollUp(@editorElement) - 'scroll-cursor-to-top': => new Scroll.ScrollCursorToTop(@editorElement) - 'scroll-cursor-to-top-leave': => new Scroll.ScrollCursorToTop(@editorElement, {leaveCursor: true}) - 'scroll-cursor-to-middle': => new Scroll.ScrollCursorToMiddle(@editorElement) - 'scroll-cursor-to-middle-leave': => new Scroll.ScrollCursorToMiddle(@editorElement, {leaveCursor: true}) - 'scroll-cursor-to-bottom': => new Scroll.ScrollCursorToBottom(@editorElement) - 'scroll-cursor-to-bottom-leave': => new Scroll.ScrollCursorToBottom(@editorElement, {leaveCursor: true}) - 'scroll-half-screen-up': => new Motions.ScrollHalfUpKeepCursor(@editorElement, this) - 'scroll-full-screen-up': => new Motions.ScrollFullUpKeepCursor(@editorElement, this) - 'scroll-half-screen-down': => new Motions.ScrollHalfDownKeepCursor(@editorElement, this) - 'scroll-full-screen-down': => new Motions.ScrollFullDownKeepCursor(@editorElement, this) - 'scroll-cursor-to-left': => new Scroll.ScrollCursorToLeft(@editorElement) - 'scroll-cursor-to-right': => new Scroll.ScrollCursorToRight(@editorElement) - 'select-inside-word': => new TextObjects.SelectInsideWord(@editor) - 'select-inside-whole-word': => new TextObjects.SelectInsideWholeWord(@editor) - 'select-inside-double-quotes': => new TextObjects.SelectInsideQuotes(@editor, '"', false) - 'select-inside-single-quotes': => new TextObjects.SelectInsideQuotes(@editor, '\'', false) - 'select-inside-back-ticks': => new TextObjects.SelectInsideQuotes(@editor, '`', false) - 'select-inside-curly-brackets': => new TextObjects.SelectInsideBrackets(@editor, '{', '}', false) - 'select-inside-angle-brackets': => new TextObjects.SelectInsideBrackets(@editor, '<', '>', false) - 'select-inside-tags': => new TextObjects.SelectInsideBrackets(@editor, '>', '<', false) - 'select-inside-square-brackets': => new TextObjects.SelectInsideBrackets(@editor, '[', ']', false) - 'select-inside-parentheses': => new TextObjects.SelectInsideBrackets(@editor, '(', ')', false) - 'select-inside-paragraph': => new TextObjects.SelectInsideParagraph(@editor, false) - 'select-a-word': => new TextObjects.SelectAWord(@editor) - 'select-a-whole-word': => new TextObjects.SelectAWholeWord(@editor) - 'select-around-double-quotes': => new TextObjects.SelectInsideQuotes(@editor, '"', true) - 'select-around-single-quotes': => new TextObjects.SelectInsideQuotes(@editor, '\'', true) - 'select-around-back-ticks': => new TextObjects.SelectInsideQuotes(@editor, '`', true) - 'select-around-curly-brackets': => new TextObjects.SelectInsideBrackets(@editor, '{', '}', true) - 'select-around-angle-brackets': => new TextObjects.SelectInsideBrackets(@editor, '<', '>', true) - 'select-around-square-brackets': => new TextObjects.SelectInsideBrackets(@editor, '[', ']', true) - 'select-around-parentheses': => new TextObjects.SelectInsideBrackets(@editor, '(', ')', true) - 'select-around-paragraph': => new TextObjects.SelectAParagraph(@editor, true) - 'register-prefix': (e) => @registerPrefix(e) - 'repeat': (e) => new Operators.Repeat(@editor, this) - 'repeat-search': (e) => new Motions.RepeatSearch(@editor, this) - 'repeat-search-backwards': (e) => new Motions.RepeatSearch(@editor, this).reversed() - 'move-to-mark': (e) => new Motions.MoveToMark(@editor, this) - 'move-to-mark-literal': (e) => new Motions.MoveToMark(@editor, this, false) - 'mark': (e) => new Operators.Mark(@editor, this) - 'find': (e) => new Motions.Find(@editor, this) - 'find-backwards': (e) => new Motions.Find(@editor, this).reverse() - 'till': (e) => new Motions.Till(@editor, this) - 'till-backwards': (e) => new Motions.Till(@editor, this).reverse() - 'repeat-find': (e) => new @globalVimState.currentFind.constructor(@editor, this, repeated: true) if @globalVimState.currentFind - 'repeat-find-reverse': (e) => new @globalVimState.currentFind.constructor(@editor, this, repeated: true, reverse: true) if @globalVimState.currentFind - 'replace': (e) => new Operators.Replace(@editor, this) - 'search': (e) => new Motions.Search(@editor, this) - 'reverse-search': (e) => (new Motions.Search(@editor, this)).reversed() - 'search-current-word': (e) => new Motions.SearchCurrentWord(@editor, this) - 'bracket-matching-motion': (e) => new Motions.BracketMatchingMotion(@editor, this) - 'reverse-search-current-word': (e) => (new Motions.SearchCurrentWord(@editor, this)).reversed() - - # Private: Register multiple command handlers via an {Object} that maps - # command names to command handler functions. - # - # Prefixes the given command names with 'vim-mode:' to reduce redundancy in - # the provided object. - registerCommands: (commands) -> - for commandName, fn of commands - do (fn) => - @subscriptions.add(atom.commands.add(@editorElement, "vim-mode:#{commandName}", fn)) - - # Private: Register multiple Operators via an {Object} that - # maps command names to functions that return operations to push. - # - # Prefixes the given command names with 'vim-mode:' to reduce redundancy in - # the given object. - registerOperationCommands: (operationCommands) -> - commands = {} - for commandName, operationFn of operationCommands - do (operationFn) => - commands[commandName] = (event) => @pushOperations(operationFn(event)) - @registerCommands(commands) - - # Private: Push the given operations onto the operation stack, then process - # it. - pushOperations: (operations) -> - return unless operations? - operations = [operations] unless _.isArray(operations) - - for operation in operations - # Motions in visual mode perform their selections. - if @mode is 'visual' and (operation instanceof Motions.Motion or operation instanceof TextObjects.TextObject) - operation.execute = operation.select - - # if we have started an operation that responds to canComposeWith check if it can compose - # with the operation we're going to push onto the stack - if (topOp = @topOperation())? and topOp.canComposeWith? and not topOp.canComposeWith(operation) - @resetNormalMode() - @emitter.emit('failed-to-compose') - break - - @opStack.push(operation) - - # If we've received an operator in visual mode, mark the current - # selection as the motion to operate on. - if @mode is 'visual' and operation instanceof Operators.Operator - @opStack.push(new Motions.CurrentSelection(@editor, this)) - - @processOpStack() - - onDidFailToCompose: (fn) -> - @emitter.on('failed-to-compose', fn) - - onDidDestroy: (fn) -> - @emitter.on('did-destroy', fn) - - # Private: Removes all operations from the stack. - # - # Returns nothing. - clearOpStack: -> - @opStack = [] - - undo: -> - @editor.undo() - @activateNormalMode() - - # Private: Processes the command if the last operation is complete. - # - # Returns nothing. - processOpStack: -> - unless @opStack.length > 0 - return - - unless @topOperation().isComplete() - if @mode is 'normal' and @topOperation() instanceof Operators.Operator - @activateOperatorPendingMode() - return - - poppedOperation = @opStack.pop() - if @opStack.length - try - @topOperation().compose(poppedOperation) - @processOpStack() - catch e - if (e instanceof Operators.OperatorError) or (e instanceof Motions.MotionError) - @resetNormalMode() - else - throw e - else - @history.unshift(poppedOperation) if poppedOperation.isRecordable() - poppedOperation.execute() - - # Private: Fetches the last operation. - # - # Returns the last operation. - topOperation: -> - _.last @opStack - - # Private: Fetches the value of a given register. - # - # name - The name of the register to fetch. - # - # Returns the value of the given register or undefined if it hasn't - # been set. - getRegister: (name) -> - if name is '"' - name = settings.defaultRegister() - if name in ['*', '+'] - text = atom.clipboard.read() - type = Utils.copyType(text) - {text, type} - else if name is '%' - text = @editor.getURI() - type = Utils.copyType(text) - {text, type} - else if name is "_" # Blackhole always returns nothing - text = '' - type = Utils.copyType(text) - {text, type} - else - @globalVimState.registers[name.toLowerCase()] - - # Private: Fetches the value of a given mark. - # - # name - The name of the mark to fetch. - # - # Returns the value of the given mark or undefined if it hasn't - # been set. - getMark: (name) -> - if @marks[name] - @marks[name].getBufferRange().start - else - undefined - - # Private: Sets the value of a given register. - # - # name - The name of the register to fetch. - # value - The value to set the register to. - # - # Returns nothing. - setRegister: (name, value) -> - if name is '"' - name = settings.defaultRegister() - if name in ['*', '+'] - atom.clipboard.write(value.text) - else if name is '_' - # Blackhole register, nothing to do - else if /^[A-Z]$/.test(name) - @appendRegister(name.toLowerCase(), value) - else - @globalVimState.registers[name] = value - - - # Private: append a value into a given register - # like setRegister, but appends the value - appendRegister: (name, value) -> - register = @globalVimState.registers[name] ?= - type: 'character' - text: "" - if register.type is 'linewise' and value.type isnt 'linewise' - register.text += value.text + '\n' - else if register.type isnt 'linewise' and value.type is 'linewise' - register.text += '\n' + value.text - register.type = 'linewise' - else - register.text += value.text - - # Private: Sets the value of a given mark. - # - # name - The name of the mark to fetch. - # pos {Point} - The value to set the mark to. - # - # Returns nothing. - setMark: (name, pos) -> - # check to make sure name is in [a-z] or is ` - if (charCode = name.charCodeAt(0)) >= 96 and charCode <= 122 - marker = @editor.markBufferRange(new Range(pos, pos), {invalidate: 'never', persistent: false}) - @marks[name] = marker - - # Public: Append a search to the search history. - # - # Motions.Search - The confirmed search motion to append - # - # Returns nothing - pushSearchHistory: (search) -> - @globalVimState.searchHistory.unshift search - - # Public: Get the search history item at the given index. - # - # index - the index of the search history item - # - # Returns a search motion - getSearchHistoryItem: (index = 0) -> - @globalVimState.searchHistory[index] - - ############################################################################## - # Mode Switching - ############################################################################## - - # Private: Used to enable normal mode. - # - # Returns nothing. - activateNormalMode: -> - @deactivateInsertMode() - @deactivateVisualMode() - - @mode = 'normal' - @submode = null - - @changeModeClass('normal-mode') - - @clearOpStack() - selection.clear(autoscroll: false) for selection in @editor.getSelections() - @ensureCursorsWithinLine() - - @updateStatusBar() - - # TODO: remove this method and bump the `vim-mode` service version number. - activateCommandMode: -> - Grim.deprecate("Use ::activateNormalMode instead") - @activateNormalMode() - - # Private: Used to enable insert mode. - # - # Returns nothing. - activateInsertMode: (subtype = null) -> - @mode = 'insert' - @editorElement.component.setInputEnabled(true) - @setInsertionCheckpoint() - @submode = subtype - @changeModeClass('insert-mode') - @updateStatusBar() - - activateReplaceMode: -> - @activateInsertMode('replace') - @replaceModeCounter = 0 - @editorElement.classList.add('replace-mode') - @subscriptions.add @replaceModeListener = @editor.onWillInsertText @replaceModeInsertHandler - @subscriptions.add @replaceModeUndoListener = @editor.onDidInsertText @replaceModeUndoHandler - - replaceModeInsertHandler: (event) => - chars = event.text?.split('') or [] - selections = @editor.getSelections() - for char in chars - continue if char is '\n' - for selection in selections - selection.delete() unless selection.cursor.isAtEndOfLine() - return - - replaceModeUndoHandler: (event) => - @replaceModeCounter++ - - replaceModeUndo: -> - if @replaceModeCounter > 0 - @editor.undo() - @editor.undo() - @editor.moveLeft() - @replaceModeCounter-- - - setInsertionCheckpoint: -> - @insertionCheckpoint = @editor.createCheckpoint() unless @insertionCheckpoint? - - deactivateInsertMode: -> - return unless @mode in [null, 'insert'] - @editorElement.component.setInputEnabled(false) - @editorElement.classList.remove('replace-mode') - @editor.groupChangesSinceCheckpoint(@insertionCheckpoint) - changes = getChangesSinceCheckpoint(@editor.buffer, @insertionCheckpoint) - item = @inputOperator(@history[0]) - @insertionCheckpoint = null - if item? - item.confirmChanges(changes) - for cursor in @editor.getCursors() - cursor.moveLeft() unless cursor.isAtBeginningOfLine() - if @replaceModeListener? - @replaceModeListener.dispose() - @subscriptions.remove @replaceModeListener - @replaceModeListener = null - @replaceModeUndoListener.dispose() - @subscriptions.remove @replaceModeUndoListener - @replaceModeUndoListener = null - - deactivateVisualMode: -> - return unless @mode is 'visual' - for selection in @editor.getSelections() - selection.cursor.moveLeft() unless (selection.isEmpty() or selection.isReversed()) - - # Private: Get the input operator that needs to be told about about the - # typed undo transaction in a recently completed operation, if there - # is one. - inputOperator: (item) -> - return item unless item? - return item if item.inputOperator?() - return item.composedObject if item.composedObject?.inputOperator?() - - # Private: Used to enable visual mode. - # - # type - One of 'characterwise', 'linewise' or 'blockwise' - # - # Returns nothing. - activateVisualMode: (type) -> - # Already in 'visual', this means one of following command is - # executed within `vim-mode.visual-mode` - # * activate-blockwise-visual-mode - # * activate-characterwise-visual-mode - # * activate-linewise-visual-mode - if @mode is 'visual' - if @submode is type - @activateNormalMode() - return - - @submode = type - if @submode is 'linewise' - for selection in @editor.getSelections() - # Keep original range as marker's property to get back - # to characterwise. - # Since selectLine lost original cursor column. - originalRange = selection.getBufferRange() - selection.marker.setProperties({originalRange}) - [start, end] = selection.getBufferRowRange() - selection.selectLine(row) for row in [start..end] - - else if @submode in ['characterwise', 'blockwise'] - # Currently, 'blockwise' is not yet implemented. - # So treat it as characterwise. - # Recover original range. - for selection in @editor.getSelections() - {originalRange} = selection.marker.getProperties() - if originalRange - [startRow, endRow] = selection.getBufferRowRange() - originalRange.start.row = startRow - originalRange.end.row = endRow - selection.setBufferRange(originalRange) - else - @deactivateInsertMode() - @mode = 'visual' - @submode = type - @changeModeClass('visual-mode') - - if @submode is 'linewise' - @editor.selectLinesContainingCursors() - else if @editor.getSelectedText() is '' - @editor.selectRight() - - @updateStatusBar() - - # Private: Used to re-enable visual mode - resetVisualMode: -> - @activateVisualMode(@submode) - - # Private: Used to enable operator-pending mode. - activateOperatorPendingMode: -> - @deactivateInsertMode() - @mode = 'operator-pending' - @submode = null - @changeModeClass('operator-pending-mode') - - @updateStatusBar() - - changeModeClass: (targetMode) -> - for mode in ['normal-mode', 'insert-mode', 'visual-mode', 'operator-pending-mode'] - if mode is targetMode - @editorElement.classList.add(mode) - else - @editorElement.classList.remove(mode) - - # Private: Resets the normal mode back to it's initial state. - # - # Returns nothing. - resetNormalMode: -> - @clearOpStack() - @editor.clearSelections() - @activateNormalMode() - - # Private: A generic way to create a Register prefix based on the event. - # - # e - The event that triggered the Register prefix. - # - # Returns nothing. - registerPrefix: (e) -> - new Prefixes.Register(@registerName(e)) - - # Private: Gets a register name from a keyboard event - # - # e - The event - # - # Returns the name of the register - registerName: (e) -> - keyboardEvent = e.originalEvent?.originalEvent ? e.originalEvent - name = atom.keymaps.keystrokeForKeyboardEvent(keyboardEvent) - if name.lastIndexOf('shift-', 0) is 0 - name = name.slice(6) - name - - # Private: A generic way to create a Number prefix based on the event. - # - # e - The event that triggered the Number prefix. - # - # Returns nothing. - repeatPrefix: (e) -> - keyboardEvent = e.originalEvent?.originalEvent ? e.originalEvent - num = parseInt(atom.keymaps.keystrokeForKeyboardEvent(keyboardEvent)) - if @topOperation() instanceof Prefixes.Repeat - @topOperation().addDigit(num) - else - if num is 0 - e.abortKeyBinding() - else - @pushOperations(new Prefixes.Repeat(num)) - - reverseSelections: -> - reversed = not @editor.getLastSelection().isReversed() - for selection in @editor.getSelections() - selection.setBufferRange(selection.getBufferRange(), {reversed}) - - # Private: Figure out whether or not we are in a repeat sequence or we just - # want to move to the beginning of the line. If we are within a repeat - # sequence, we pass control over to @repeatPrefix. - # - # e - The triggered event. - # - # Returns new motion or nothing. - moveOrRepeat: (e) -> - if @topOperation() instanceof Prefixes.Repeat - @repeatPrefix(e) - null - else - new Motions.MoveToBeginningOfLine(@editor, this) - - # Private: A generic way to handle Operators that can be repeated for - # their linewise form. - # - # constructor - The constructor of the operator. - # - # Returns nothing. - linewiseAliasedOperator: (constructor) -> - if @isOperatorPending(constructor) - new Motions.MoveToRelativeLine(@editor, this) - else - new constructor(@editor, this) - - # Private: Check if there is a pending operation of a certain type, or - # if there is any pending operation, if no type given. - # - # constructor - The constructor of the object type you're looking for. - # - isOperatorPending: (constructor) -> - if constructor? - for op in @opStack - return op if op instanceof constructor - false - else - @opStack.length > 0 - - updateStatusBar: -> - @statusBarManager.update(@mode, @submode) - - # Private: insert the contents of the register in the editor - # - # name - the name of the register to insert - # - # Returns nothing. - insertRegister: (name) -> - text = @getRegister(name)?.text - @editor.insertText(text) if text? - - # Private: ensure the mode follows the state of selections - checkSelections: => - return unless @editor? - if @editor.getSelections().every((selection) -> selection.isEmpty()) - @ensureCursorsWithinLine() if @mode is 'normal' - @activateNormalMode() if @mode is 'visual' - else - @activateVisualMode('characterwise') if @mode is 'normal' - - # Private: ensure the cursor stays within the line as appropriate - ensureCursorsWithinLine: => - for cursor in @editor.getCursors() - {goalColumn} = cursor - if cursor.isAtEndOfLine() and not cursor.isAtBeginningOfLine() - cursor.moveLeft() - cursor.goalColumn = goalColumn - - @editor.mergeCursors() - -# This uses private APIs and may break if TextBuffer is refactored. -# Package authors - copy and paste this code at your own risk. -getChangesSinceCheckpoint = (buffer, checkpoint) -> - {history} = buffer - - if (index = history.getCheckpointIndex(checkpoint))? - history.undoStack.slice(index) - else - [] |