 CommandPrefix = 'vim-mode-plus-user'
 stateByEditor = new Map
 checkPointByEditor = new Map
+disposableByEditor = new Map
 # -------------------------
 class MoveSelectedText extends TransformString
+  countTimes: (fn) ->
+    _.times @getCount(), ->
+      fn()
+
   getSelectedTexts: ->
     @editor.getSelections().map((selection) -> selection.getText()).join('')
 
   withUndoJoin: (fn) ->
-    unless (isSequential = stateByEditor.get(@editor) is @getSelectedTexts())
+    unless disposableByEditor.has(@editor)
+      disposableByEditor.set @editor, @editor.onDidDestroy =>
+        checkPointByEditor.delete(@editor)
+        stateByEditor.delete(@editor)
+
+    isSequential = stateByEditor.get(@editor) is @getSelectedTexts()
+    unless isSequential
       checkPointByEditor.set(@editor, @editor.createCheckpoint())
-
     fn()
 
     stateByEditor.set(@editor, @getSelectedTexts())
-    if isSequential and checkPointByEditor.has(@editor)
-      @editor.groupChangesSinceCheckpoint(checkPointByEditor.get(@editor))
+    if isSequential and (checkpoint = checkPointByEditor.get(@editor))
+      @editor.groupChangesSinceCheckpoint(checkpoint)
 
 class MoveSelectedTextUp extends MoveSelectedText
   @commandPrefix: CommandPrefix


  execute: ->
    return unless @isMode('visual')
    @withUndoJoin =>
      @eachSelection (selection) =>
        @mutate(selection)

  mutate: (selection) ->
    switch @vimState.submode


  execute: ->
    return unless @isMode('visual')

    @withUndoJoin =>
      selections = @editor.getSelectionsOrderedByBufferPosition()
      selections.reverse() if @direction is 'down'
      @editor.transact =>
        for selection in selections
          @countTimes =>
            @mutate(selection)

  mutate: (selection) ->
    switch @vimState.submode
