     atom.config.get('vim-mode-plus-move-selected-text.overwrite')
 
   withUndoJoin: (fn) ->
+    stateByEditor.set(@editor, newState()) unless stateByEditor.has(@editor)
+
     unless disposableByEditor.has(@editor)
-      disposable = @vimState.modeManager.onDidDeactivateMode ({mode}) ->
+      disposable = @vimState.modeManager.onDidDeactivateMode ({mode}) =>
         if mode is 'visual'
           stateByEditor.delete(@editor)
-          overwrittenByEditor.delete(@editor)
 
       disposableByEditor.set @editor, @editor.onDidDestroy =>
-        checkPointByEditor.delete(@editor)
         stateByEditor.delete(@editor)
-        disposableByEditor.delete(@editor)
-        overwrittenByEditor.delete(@editor)
         disposable.dispose()
 
-    isSequential = stateByEditor.get(@editor) is @getSelectedTexts()
+    state = stateByEditor.get(@editor)
+    isSequential = state.selectedTexts is @getSelectedTexts()
     unless isSequential
-      checkPointByEditor.set(@editor, @editor.createCheckpoint())
-      overwrittenByEditor.delete(@editor)
+      state.checkpoint = @editor.createCheckpoint()
+      state.overwritten = null
+
     fn()
 
-    stateByEditor.set(@editor, @getSelectedTexts())
-    if isSequential and (checkpoint = checkPointByEditor.get(@editor))
-      @editor.groupChangesSinceCheckpoint(checkpoint)
+    state.selectedTexts = @getSelectedTexts()
+    if isSequential
+      @editor.groupChangesSinceCheckpoint(state.checkpoint)
 
   getOverwrittenText: (replacedText) ->
-    overwrittenArea = overwrittenByEditor.get(@editor)[@selectionIndex]
+    state = stateByEditor.get(@editor)
+    overwrittenArea = state.overwritten[@selectionIndex]
     replacedText = switch @direction
       when 'up'
         [overwritten, rest...] = overwrittenArea.split("\n")

            @extendMovingArea(selection)
            @mutate(selection) if @isMovable(selection)

  initOverwrittenByEditor: ->
    unless overwrittenByEditor.has(@editor)
      if @isLinewise()
        overwrittenArea = @editor.getSelections().map (selection) ->
          _.multiplyString("\n", swrap(selection).getRowCount()-1)
      else
        overwrittenArea = @editor.getSelections().map (selection) ->
          _.multiplyString(' ', selection.getBufferRange().getExtent().column)
      overwrittenByEditor.set(@editor, overwrittenArea)

  getSelectedTexts: ->
    @editor.getSelections().map((selection) -> selection.getText()).join("\n")

      selections = @editor.getSelectionsOrderedByBufferPosition()
      topSelection = selections[0]
      selections.reverse() if @direction is 'down'
      @initOverwrittenArea()
      @editor.transact =>
        @countTimes =>
          return if (not @isLinewise()) and (not @isMovable(topSelection))
