diff --git a/lib/operators/input.coffee b/lib/operators/input.coffee index 2c982425..1610bd4f 100644 --- a/lib/operators/input.coffee +++ b/lib/operators/input.coffee @@ -111,11 +111,11 @@ class Change extends Insert # # Returns nothing. execute: (count) -> - # If we've typed, we're being repeated. If we're being repeated, - # undo transactions are already handled. - @vimState.setInsertionCheckpoint() unless @typingCompleted - if _.contains(@motion.select(count, excludeWhitespace: true), true) + # If we've typed, we're being repeated. If we're being repeated, + # undo transactions are already handled. + @vimState.setInsertionCheckpoint() unless @typingCompleted + @setTextRegister(@register, @editor.getSelectedText()) if @motion.isLinewise?() and not @typingCompleted for selection in @editor.getSelections() @@ -125,10 +125,12 @@ class Change extends Insert for selection in @editor.getSelections() selection.deleteSelectedText() - return super if @typingCompleted + return super if @typingCompleted - @vimState.activateInsertMode() - @typingCompleted = true + @vimState.activateInsertMode() + @typingCompleted = true + else + @vimState.activateNormalMode() class SubstituteLine extends Change standalone: true diff --git a/spec/motions-spec.coffee b/spec/motions-spec.coffee index e7fe3377..9dc3ee69 100644 --- a/spec/motions-spec.coffee +++ b/spec/motions-spec.coffee @@ -1521,6 +1521,14 @@ describe "Motions", -> normalModeInputKeydown('a') expect(editor.getText()).toEqual 'abcbc\n' + it "cancels c when no match found", -> + keydown('c') + keydown('f') + normalModeInputKeydown('d') + expect(editor.getText()).toBe("abcabcabcabc\n") + expect(editor.getCursorScreenPosition()).toEqual [0, 0] + expect(vimState.mode).toBe "normal" + describe 'the t/T keybindings', -> beforeEach -> editor.setText("abcabcabcabc\n") diff --git a/spec/operators-spec.coffee b/spec/operators-spec.coffee index ac8b2569..a7058115 100644 --- a/spec/operators-spec.coffee +++ b/spec/operators-spec.coffee @@ -709,6 +709,91 @@ describe "Operators", -> keydown('escape') expect(editor.getText()).toBe("12345\n\n") + describe "when followed by a %", -> + beforeEach -> + editor.setText("12345(67)8\nabc(d)e\nA()BCDE") + + describe "before brackets or on the first one", -> + beforeEach -> + editor.setCursorScreenPosition([0, 1]) + editor.addCursorAtScreenPosition([1, 1]) + editor.addCursorAtScreenPosition([2, 1]) + keydown('c') + keydown('%') + editor.insertText('x') + + it "replaces inclusively until matching bracket", -> + expect(editor.getText()).toBe("1x8\naxe\nAxBCDE") + expect(vimState.mode).toBe "insert" + + it "undoes correctly with u", -> + keydown('escape') + expect(vimState.mode).toBe "normal" + keydown 'u' + expect(editor.getText()).toBe("12345(67)8\nabc(d)e\nA()BCDE") + + describe "inside brackets or on the ending one", -> + it "replaces inclusively backwards until matching bracket", -> + editor.setCursorScreenPosition([0, 6]) + editor.addCursorAtScreenPosition([1, 5]) + editor.addCursorAtScreenPosition([2, 2]) + keydown('c') + keydown('%') + editor.insertText('x') + # this differs from VIM, which deletes the character originally under cursor + expect(editor.getText()).toBe("12345x67)8\nabcx)e\nAx)BCDE") + expect(vimState.mode).toBe "insert" + + describe "after or without brackets", -> + it "deletes nothing", -> + editor.setText("12345(67)8\nabc(d)e\nABCDE") + editor.setCursorScreenPosition([0, 9]) + editor.addCursorAtScreenPosition([2, 2]) + keydown('c') + keydown('%') + expect(editor.getText()).toBe("12345(67)8\nabc(d)e\nABCDE") + expect(vimState.mode).toBe "normal" + + describe "repetition with .", -> + beforeEach -> + editor.setCursorScreenPosition([0, 1]) + keydown('c') + keydown('%') + editor.insertText('x') + keydown('escape') + + it "repeats correctly before a bracket", -> + editor.setCursorScreenPosition([1, 0]) + keydown('.') + expect(editor.getText()).toBe("1x8\nxe\nA()BCDE") + expect(vimState.mode).toBe "normal" + + it "repeats correctly on the opening bracket", -> + editor.setCursorScreenPosition([1, 3]) + keydown('.') + expect(editor.getText()).toBe("1x8\nabcxe\nA()BCDE") + expect(vimState.mode).toBe "normal" + + it "repeats correctly inside brackets", -> + editor.setCursorScreenPosition([1, 4]) + keydown('.') + # this differs from VIM, which deletes the character originally under cursor + expect(editor.getText()).toBe("1x8\nabcxd)e\nA()BCDE") + expect(vimState.mode).toBe "normal" + + it "repeats correctly on the closing bracket", -> + editor.setCursorScreenPosition([1, 5]) + keydown('.') + # this differs from VIM, which deletes the character originally under cursor + expect(editor.getText()).toBe("1x8\nabcx)e\nA()BCDE") + expect(vimState.mode).toBe "normal" + + it "does nothing when repeated after a bracket", -> + editor.setCursorScreenPosition([2, 3]) + keydown('.') + expect(editor.getText()).toBe("1x8\nabc(d)e\nA()BCDE") + expect(vimState.mode).toBe "normal" + describe "when followed by a goto line G", -> beforeEach -> editor.setText "12345\nabcde\nABCDE"