helpers = require './spec-helper' describe "Operators", -> [editor, editorView, vimState] = [] beforeEach -> vimMode = atom.packages.loadPackage('vim-mode') vimMode.activateResources() editorView = helpers.cacheEditor(editorView) editor = editorView.editor vimState = editorView.vimState vimState.activateCommandMode() vimState.resetCommandMode() keydown = (key, options={}) -> options.element ?= editorView[0] helpers.keydown(key, options) commandModeInputKeydown = (key, opts = {}) -> opts.element = editor.commandModeInputView.editor.find('input').get(0) opts.raw = true keydown(key, opts) describe "cancel operation is robust", -> it "can call cancel operation, even if no operator pending", -> # cancel operation pushes an empty input operation # doing this without a pending operation throws an exception expect(-> vimState.pushOperations(new Input(''))).toThrow() # make sure commandModeInputView is created keydown('/') expect(vimState.isOperatorPending()).toBe true editor.commandModeInputView.viewModel.cancel() # now again cancel op, although there is none pending expect(vimState.isOperatorPending()).toBe false # which should not raise an exception expect(-> editor.commandModeInputView.viewModel.cancel()).not.toThrow() describe "the x keybinding", -> describe "on a line with content", -> beforeEach -> editor.setText("012345") editor.setCursorScreenPosition([0, 4]) it "deletes a character", -> keydown('x') expect(editor.getText()).toBe '01235' expect(editor.getCursorScreenPosition()).toEqual [0, 4] expect(vimState.getRegister('"').text).toBe '4' keydown('x') expect(editor.getText()).toBe '0123' expect(editor.getCursorScreenPosition()).toEqual [0, 3] expect(vimState.getRegister('"').text).toBe '5' keydown('x') expect(editor.getText()).toBe '012' expect(editor.getCursorScreenPosition()).toEqual [0, 2] expect(vimState.getRegister('"').text).toBe '3' describe "on an empty line", -> beforeEach -> editor.setText("012345\n\nabcdef") editor.setCursorScreenPosition([1, 0]) keydown('x') it "deletes nothing when cursor is on empty line", -> expect(editor.getText()).toBe "012345\n\nabcdef" describe "the X keybinding", -> describe "on a line with content", -> beforeEach -> editor.setText("012345") editor.setCursorScreenPosition([0, 2]) it "deletes a character", -> keydown('X', shift: true) expect(editor.getText()).toBe '02345' expect(editor.getCursorScreenPosition()).toEqual [0, 1] expect(vimState.getRegister('"').text).toBe '1' keydown('X', shift: true) expect(editor.getText()).toBe '2345' expect(editor.getCursorScreenPosition()).toEqual [0, 0] expect(vimState.getRegister('"').text).toBe '0' keydown('X', shift: true) expect(editor.getText()).toBe '2345' expect(editor.getCursorScreenPosition()).toEqual [0, 0] expect(vimState.getRegister('"').text).toBe '0' describe "on an empty line", -> beforeEach -> editor.setText("012345\n\nabcdef") editor.setCursorScreenPosition([1, 0]) keydown('X', shift: true) it "deletes nothing when cursor is on empty line", -> expect(editor.getText()).toBe "012345\n\nabcdef" describe "the s keybinding", -> beforeEach -> editor.setText('012345') editor.setCursorScreenPosition([0, 1]) it "deletes the character to the right and enters insert mode", -> keydown('s') expect(editorView).toHaveClass 'insert-mode' expect(editor.getText()).toBe '02345' expect(editor.getCursorScreenPosition()).toEqual [0, 1] expect(vimState.getRegister('"').text).toBe '1' it "is repeatable", -> editor.setCursorScreenPosition([0, 0]) keydown('3') keydown('s') editor.insertText("ab") keydown('escape') expect(editor.getText()).toBe 'ab345' editor.setCursorScreenPosition([0, 2]) keydown('.') expect(editor.getText()).toBe 'abab' it "is undoable", -> editor.setCursorScreenPosition([0, 0]) keydown('3') keydown('s') editor.insertText("ab") keydown('escape') expect(editor.getText()).toBe 'ab345' keydown('u') expect(editor.getText()).toBe '012345' describe "in visual mode", -> beforeEach -> keydown('v') editor.selectRight() editor.selectRight() keydown('s') it "deletes the selected characters and enters insert mode", -> expect(editorView).toHaveClass 'insert-mode' expect(editor.getText()).toBe '0345' expect(editor.getCursorScreenPosition()).toEqual [0, 1] expect(vimState.getRegister('"').text).toBe '12' describe "the S keybinding", -> beforeEach -> editor.setText("12345\nabcde\nABCDE") editor.setCursorScreenPosition([1, 3]) it "deletes the entire line and enters insert mode", -> keydown('S', shift: true) expect(editorView).toHaveClass 'insert-mode' expect(editor.getText()).toBe "12345\n\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [1, 0] expect(vimState.getRegister('"').text).toBe "abcde\n" expect(vimState.getRegister('"').type).toBe 'linewise' it "is repeatable", -> keydown('S', shift: true) editor.insertText("abc") keydown 'escape' expect(editor.getText()).toBe "12345\nabc\nABCDE" editor.setCursorScreenPosition([2, 3]) keydown '.' expect(editor.getText()).toBe "12345\nabc\nabc\n" it "is undoable", -> keydown('S', shift: true) editor.insertText("abc") keydown 'escape' expect(editor.getText()).toBe "12345\nabc\nABCDE" keydown 'u' expect(editor.getText()).toBe "12345\nabcde\nABCDE" # Can't be tested without setting grammar of test buffer xit "respects indentation", -> describe "the d keybinding", -> it "enters operator-pending mode", -> keydown('d') expect(editorView).toHaveClass('operator-pending-mode') expect(editorView).not.toHaveClass('command-mode') describe "when followed by a d", -> it "deletes the current line and exits operator-pending mode", -> editor.setText("12345\nabcde\n\nABCDE") editor.setCursorScreenPosition([1, 1]) keydown('d') keydown('d') expect(editor.getText()).toBe "12345\n\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [1, 0] expect(vimState.getRegister('"').text).toBe "abcde\n" expect(editorView).not.toHaveClass('operator-pending-mode') expect(editorView).toHaveClass('command-mode') it "deletes the last line", -> editor.setText("12345\nabcde\nABCDE") editor.setCursorScreenPosition([2, 1]) keydown('d') keydown('d') expect(editor.getText()).toBe "12345\nabcde" expect(editor.getCursorScreenPosition()).toEqual [1, 0] describe "undo behavior", -> beforeEach -> editor.setText("12345\nabcde\nABCDE\nQWERT") editor.setCursorScreenPosition([1,1]) keydown('d') keydown('2') keydown('d') keydown('u') it "undoes both lines", -> expect(editor.getText()).toBe "12345\nabcde\nABCDE\nQWERT" describe "when followed by a w", -> it "deletes the next word until the end of the line and exits operator-pending mode", -> editor.setText("abcd efg\nabc") editor.setCursorScreenPosition([0, 5]) keydown('d') keydown('w') expect(editor.getText()).toBe "abcd \nabc" expect(editor.getCursorScreenPosition()).toEqual [0, 4] expect(editorView).not.toHaveClass('operator-pending-mode') expect(editorView).toHaveClass('command-mode') it "deletes to the beginning of the next word", -> editor.setText('abcd efg') editor.setCursorScreenPosition([0, 2]) keydown('d') keydown('w') expect(editor.getText()).toBe 'abefg' expect(editor.getCursorScreenPosition()).toEqual [0, 2] editor.setText('one two three four') editor.setCursorScreenPosition([0, 0]) keydown('d') keydown('3') keydown('w') expect(editor.getText()).toBe 'four' expect(editor.getCursorScreenPosition()).toEqual [0, 0] describe "when followed by an iw", -> it "deletes the containing word", -> editor.setText("12345 abcde ABCDE") editor.setCursorScreenPosition([0, 9]) keydown('d') expect(editorView).toHaveClass('operator-pending-mode') keydown('i') keydown('w') expect(editor.getText()).toBe "12345 ABCDE" expect(editor.getCursorScreenPosition()).toEqual [0, 6] expect(vimState.getRegister('"').text).toBe "abcde" expect(editorView).not.toHaveClass('operator-pending-mode') expect(editorView).toHaveClass('command-mode') describe "when followed by an j", -> beforeEach -> originalText = "12345\nabcde\nABCDE" editor.setText(originalText) describe "on the beginning of the file", -> editor.setCursorScreenPosition([0, 0]) it "deletes the next two lines", -> keydown('d') keydown('j') expect(editor.getText()).toBe("ABCDE") describe "on the end of the file", -> editor.setCursorScreenPosition([4,2]) it "deletes nothing", -> keydown('d') keydown('j') expect(editor.getText()).toBe(originalText) describe "on the middle of second line", -> editor.setCursorScreenPosition([2,1]) it "deletes the last two lines", -> keydown('d') keydown('j') expect(editor.getText()).toBe("12345") describe "when followed by an k", -> beforeEach -> originalText = "12345\nabcde\nABCDE" editor.setText(originalText) describe "on the end of the file", -> editor.setCursorScreenPosition([4, 2]) it "deletes the bottom two lines", -> keydown('d') keydown('k') expect(editor.getText()).toBe("ABCDE") describe "on the beginning of the file", -> editor.setCursorScreenPosition([0,0]) it "deletes nothing", -> keydown('d') keydown('k') expect(editor.getText()).toBe(originalText) describe "when on the middle of second line", -> editor.setCursorScreenPosition([2,1]) it "deletes the first two lines", -> keydown('d') keydown('k') expect(editor.getText()).toBe("12345") describe "the D keybinding", -> beforeEach -> editor.getBuffer().setText("012\n") editor.setCursorScreenPosition([0, 1]) keydown('D', shift: true) it "deletes the contents until the end of the line", -> expect(editor.getText()).toBe "0\n" describe "the c keybinding", -> beforeEach -> editor.setText("12345\nabcde\nABCDE") describe "when followed by a c", -> it "deletes the current line and enters insert mode", -> editor.setCursorScreenPosition([1, 1]) keydown('c') keydown('c') expect(editor.getText()).toBe "12345\n\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [1, 0] expect(editorView).not.toHaveClass 'command-mode' expect(editorView).toHaveClass 'insert-mode' describe "when the cursor is on the last line", -> it "deletes the line's content and enters insert mode on the last line", -> editor.setCursorScreenPosition([2, 1]) keydown('c') keydown('c') expect(editor.getText()).toBe "12345\nabcde\n" expect(editor.getCursorScreenPosition()).toEqual [2, 0] expect(editorView).not.toHaveClass 'command-mode' expect(editorView).toHaveClass 'insert-mode' describe "when the cursor is on the only line", -> it "deletes the line's content and enters insert mode", -> editor.setText("12345") editor.setCursorScreenPosition([0, 2]) keydown('c') keydown('c') expect(editor.getText()).toBe "" expect(editor.getCursorScreenPosition()).toEqual [0, 0] expect(editorView).not.toHaveClass 'command-mode' expect(editorView).toHaveClass 'insert-mode' describe "when followed by i w", -> it "undo's and redo's completely", -> editor.setCursorScreenPosition([1, 1]) keydown('c') keydown('i') keydown('w') expect(editor.getText()).toBe "12345\n\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [1, 0] expect(editorView).toHaveClass 'insert-mode' # Just cannot get "typing" to work correctly in test. editor.setText("12345\nfg\nABCDE") keydown('escape') expect(editorView).toHaveClass 'command-mode' expect(editor.getText()).toBe "12345\nfg\nABCDE" keydown('u') expect(editor.getText()).toBe "12345\nabcde\nABCDE" keydown('r', ctrl: true) expect(editor.getText()).toBe "12345\nfg\nABCDE" describe "the C keybinding", -> beforeEach -> editor.getBuffer().setText("012\n") editor.setCursorScreenPosition([0, 1]) keydown('C', shift: true) it "deletes the contents until the end of the line and enters insert mode", -> expect(editor.getText()).toBe "0\n" expect(editor.getCursorScreenPosition()).toEqual [0, 1] expect(editorView).not.toHaveClass 'command-mode' expect(editorView).toHaveClass 'insert-mode' describe "the y keybinding", -> beforeEach -> editor.getBuffer().setText("012 345\nabc\n") editor.setCursorScreenPosition([0, 4]) describe "when selected lines in visual linewise mode", -> beforeEach -> keydown('V', shift: true) keydown('j') keydown('y') it "is in linewise motion", -> expect(vimState.getRegister('"').type).toEqual "linewise" it "saves the lines to the default register", -> expect(vimState.getRegister('"').text).toBe "012 345\nabc\n" describe "when followed by a second y ", -> beforeEach -> keydown('y') keydown('y') it "saves the line to the default register", -> expect(vimState.getRegister('"').text).toBe "012 345\n" expect(editor.getCursorScreenPosition()).toEqual [0, 4] describe "when followed with a repeated y", -> beforeEach -> keydown('y') keydown('2') keydown('y') it "copies n lines, starting from the current", -> expect(vimState.getRegister('"').text).toBe "012 345\nabc\n" describe "with a register", -> beforeEach -> keydown('"') keydown('a') keydown('y') keydown('y') it "saves the line to the a register", -> expect(vimState.getRegister('a').text).toBe "012 345\n" describe "with a motion", -> beforeEach -> keydown('y') keydown('w') it "saves the first word to the default register", -> expect(vimState.getRegister('"').text).toBe '345' describe "the yy keybinding", -> describe "on a single line file", -> beforeEach -> editor.getBuffer().setText "exclamation!\n" editor.setCursorScreenPosition [0, 0] it "copies the entire line and pastes it correctly", -> keydown('y') keydown('y') keydown('p') expect(vimState.getRegister('"').text).toBe "exclamation!\n" expect(editor.getText()).toBe "exclamation!\nexclamation!\n" describe "on a single line file with no newline", -> beforeEach -> editor.getBuffer().setText "no newline!" editor.setCursorScreenPosition [0, 0] it "copies the entire line and pastes it correctly", -> keydown('y') keydown('y') keydown('p') expect(vimState.getRegister('"').text).toBe "no newline!" expect(editor.getText()).toBe "no newline!\nno newline!" describe "the Y keybinding", -> beforeEach -> editor.getBuffer().setText "012 345\nabc\n" editor.setCursorScreenPosition [0, 4] it "saves the line to the default register", -> keydown('Y', shift: true) expect(vimState.getRegister('"').text).toBe "012 345\n" expect(editor.getCursorScreenPosition()).toEqual [0, 4] describe "the p keybinding", -> describe "with character contents", -> beforeEach -> editor.getBuffer().setText "012\n" editor.setCursorScreenPosition [0, 0] vimState.setRegister('"', text: '345') vimState.setRegister('a', text: 'a') describe "from the default register", -> beforeEach -> keydown('p') it "inserts the contents", -> expect(editor.getText()).toBe "034512\n" expect(editor.getCursorScreenPosition()).toEqual [0, 3] describe "from a specified register", -> beforeEach -> keydown('"') keydown('a') keydown('p') it "inserts the contents of the 'a' register", -> expect(editor.getText()).toBe "0a12\n" expect(editor.getCursorScreenPosition()).toEqual [0, 1] describe "at the end of a line", -> it "inserts before the current line's newline", -> editor.setText("abcde\none two three") editor.setCursorScreenPosition([1, 4]) keydown 'd' keydown '$' keydown 'k' keydown '$' keydown 'p' expect(editor.getText()).toBe "abcdetwo three\none " describe "with linewise contents", -> beforeEach -> editor.getBuffer().setText("012") editor.setCursorScreenPosition([0, 1]) vimState.setRegister('"', text: " 345\n", type: 'linewise') keydown('p') it "inserts the contents of the default register", -> expect(editor.getText()).toBe "012\n 345" expect(editor.getCursorScreenPosition()).toEqual [1, 1] describe "with linewise contents", -> beforeEach -> editor.getBuffer().setText("012\n 345") editor.setCursorScreenPosition([0, 1]) vimState.setRegister('"', text: " 456\n", type: 'linewise') keydown('p') it "inserts the contents of the default register at middle line", -> expect(editor.getText()).toBe "012\n 456\n 345" expect(editor.getCursorScreenPosition()).toEqual [1, 1] describe "with linewise contents", -> beforeEach -> editor.getBuffer().setText("012\n 345") editor.setCursorScreenPosition([1, 1]) vimState.setRegister('"', text: " 456", type: 'linewise') keydown('p') it "inserts the contents of the default register at end of line", -> expect(editor.getText()).toBe "012\n 345\n 456" expect(editor.getCursorScreenPosition()).toEqual [2, 1] describe "with multiple linewise contents", -> beforeEach -> editor.getBuffer().setText("012\nabc") editor.setCursorScreenPosition([1, 0]) vimState.setRegister('"', text: " 345\n 678\n", type: 'linewise') keydown('p') it "inserts the contents of the default register", -> expect(editor.getText()).toBe "012\nabc\n 345\n 678" expect(editor.getCursorScreenPosition()).toEqual [2, 1] describe "pasting twice", -> beforeEach -> editor.setText("12345\nabcde\nABCDE\nQWERT") editor.setCursorScreenPosition([1, 1]) vimState.setRegister('"', text: '123') keydown('2') keydown('p') it "inserts the same line twice", -> expect(editor.getText()).toBe "12345\nab123123cde\nABCDE\nQWERT" describe "when undone", -> beforeEach -> keydown('u') it "removes both lines", -> expect(editor.getText()).toBe "12345\nabcde\nABCDE\nQWERT" describe "the P keybinding", -> describe "with character contents", -> beforeEach -> editor.getBuffer().setText("012\n") editor.setCursorScreenPosition([0, 0]) vimState.setRegister('"', text: '345') vimState.setRegister('a', text: 'a') keydown('P', shift: true) it "inserts the contents of the default register above", -> expect(editor.getText()).toBe "345012\n" expect(editor.getCursorScreenPosition()).toEqual [0, 2] describe "the O keybinding", -> beforeEach -> spyOn(editor, 'shouldAutoIndent').andReturn(true) spyOn(editor, 'autoIndentBufferRow').andCallFake (line) -> editor.indent() editor.getBuffer().setText(" abc\n 012\n") editor.setCursorScreenPosition([1, 1]) it "switches to insert and adds a newline above the current one", -> keydown('O', shift: true) expect(editor.getText()).toBe " abc\n \n 012\n" expect(editor.getCursorScreenPosition()).toEqual [1, 2] expect(editorView).toHaveClass 'insert-mode' it "is repeatable", -> editor.getBuffer().setText(" abc\n 012\n 4spaces\n") editor.setCursorScreenPosition([1, 1]) keydown('O', shift: true) editor.insertText "def" keydown 'escape' expect(editor.getText()).toBe " abc\n def\n 012\n 4spaces\n" editor.setCursorScreenPosition([1, 1]) keydown '.' expect(editor.getText()).toBe " abc\n def\n def\n 012\n 4spaces\n" editor.setCursorScreenPosition([4, 1]) keydown '.' expect(editor.getText()).toBe " abc\n def\n def\n 012\n def\n 4spaces\n" it "is undoable", -> keydown('O', shift: true) editor.insertText "def" keydown 'escape' expect(editor.getText()).toBe " abc\n def\n 012\n" keydown 'u' expect(editor.getText()).toBe " abc\n 012\n" describe "the o keybinding", -> beforeEach -> spyOn(editor, 'shouldAutoIndent').andReturn(true) spyOn(editor, 'autoIndentBufferRow').andCallFake (line) -> editor.indent() editor.getBuffer().setText("abc\n 012\n") editor.setCursorScreenPosition([1, 2]) it "switches to insert and adds a newline above the current one", -> keydown('o') expect(editor.getText()).toBe "abc\n 012\n \n" expect(editorView).toHaveClass 'insert-mode' expect(editor.getCursorScreenPosition()).toEqual [2, 2] # This works in practice, but the editor doesn't respect the indentation # rules without a syntax grammar. Need to set the editor's grammar # to fix it. xit "is repeatable", -> editor.getBuffer().setText(" abc\n 012\n 4spaces\n") editor.setCursorScreenPosition([1, 1]) keydown('o') editor.insertText "def" keydown 'escape' expect(editor.getText()).toBe " abc\n 012\n def\n 4spaces\n" keydown '.' expect(editor.getText()).toBe " abc\n 012\n def\n def\n 4spaces\n" editor.setCursorScreenPosition([4, 1]) keydown '.' expect(editor.getText()).toBe " abc\n def\n def\n 012\n 4spaces\n def\n" it "is undoable", -> keydown('o') editor.insertText "def" keydown 'escape' expect(editor.getText()).toBe "abc\n 012\n def\n" keydown 'u' expect(editor.getText()).toBe "abc\n 012\n" describe "the a keybinding", -> beforeEach -> editor.getBuffer().setText("012\n") describe "at the beginning of the line", -> beforeEach -> editor.setCursorScreenPosition([0, 0]) keydown('a') it "switches to insert mode and shifts to the right", -> expect(editor.getCursorScreenPosition()).toEqual [0, 1] expect(editorView).toHaveClass 'insert-mode' describe "at the end of the line", -> beforeEach -> editor.setCursorScreenPosition([0, 3]) keydown('a') it "doesn't linewrap", -> expect(editor.getCursorScreenPosition()).toEqual [0, 3] describe "the A keybinding", -> beforeEach -> editor.getBuffer().setText("11\n22\n") describe "at the beginning of a line", -> it "switches to insert mode at the end of the line", -> editor.setCursorScreenPosition([0,0]) keydown('A', shift: true) expect(editorView).toHaveClass 'insert-mode' expect(editor.getCursorScreenPosition()).toEqual [0, 2] describe "the I keybinding", -> beforeEach -> editor.getBuffer().setText("11\n 22\n") describe "at the end of a line", -> it "switches to insert mode at the beginning of the line", -> editor.setCursorScreenPosition([0,2]) keydown('I', shift: true) expect(editorView).toHaveClass 'insert-mode' expect(editor.getCursorScreenPosition()).toEqual [0, 0] it "switches to insert mode after leading whitespace", -> editor.setCursorScreenPosition([1,4]) keydown('I', shift: true) expect(editorView).toHaveClass 'insert-mode' expect(editor.getCursorScreenPosition()).toEqual [1, 2] describe "the J keybinding", -> beforeEach -> editor.getBuffer().setText("012\n 456\n") editor.setCursorScreenPosition([0, 1]) describe "without repeating", -> beforeEach -> keydown('J', shift: true) it "joins the contents of the current line with the one below it", -> expect(editor.getText()).toBe "012 456\n" describe "with repeating", -> beforeEach -> editor.setText("12345\nabcde\nABCDE\nQWERT") editor.setCursorScreenPosition([1, 1]) keydown('2') keydown('J', shift: true) describe "undo behavior", -> beforeEach -> keydown('u') it "handles repeats", -> expect(editor.getText()).toBe "12345\nabcde\nABCDE\nQWERT" describe "the > keybinding", -> beforeEach -> editor.setText("12345\nabcde\nABCDE") describe "on the last line", -> beforeEach -> editor.setCursorScreenPosition([2, 0]) describe "when followed by a >", -> beforeEach -> keydown('>') keydown('>') it "indents the current line", -> expect(editor.getText()).toBe "12345\nabcde\n ABCDE" expect(editor.getCursorScreenPosition()).toEqual [2, 2] describe "on the first line", -> beforeEach -> editor.setCursorScreenPosition([0, 0]) describe "when followed by a >", -> beforeEach -> keydown('>') keydown('>') it "indents the current line", -> expect(editor.getText()).toBe " 12345\nabcde\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [0, 2] describe "when followed by a repeating >", -> beforeEach -> keydown('3') keydown('>') keydown('>') it "indents multiple lines at once", -> expect(editor.getText()).toBe " 12345\n abcde\n ABCDE" expect(editor.getCursorScreenPosition()).toEqual [0, 2] describe "undo behavior", -> beforeEach -> keydown('u') it "outdents all three lines", -> expect(editor.getText()).toBe "12345\nabcde\nABCDE" describe "the < keybinding", -> beforeEach -> editor.setText(" 12345\n abcde\nABCDE") editor.setCursorScreenPosition([0, 0]) describe "when followed by a <", -> beforeEach -> keydown('<') keydown('<') it "indents the current line", -> expect(editor.getText()).toBe "12345\n abcde\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [0, 0] describe "when followed by a repeating <", -> beforeEach -> keydown('2') keydown('<') keydown('<') it "indents multiple lines at once", -> expect(editor.getText()).toBe "12345\nabcde\nABCDE" expect(editor.getCursorScreenPosition()).toEqual [0, 0] describe "undo behavior", -> beforeEach -> keydown('u') it "indents both lines", -> expect(editor.getText()).toBe " 12345\n abcde\nABCDE" describe "the = keybinding", -> oldGrammar = [] beforeEach -> waitsForPromise -> atom.packages.activatePackage('language-javascript') oldGrammar = editor.getGrammar() editor.setText("foo\n bar\n baz") editor.setCursorScreenPosition([1, 0]) describe "when used in a scope that supports auto-indent", -> beforeEach -> jsGrammar = atom.syntax.grammarForScopeName('source.js') editor.setGrammar(jsGrammar) afterEach -> editor.setGrammar(oldGrammar) describe "when followed by a =", -> beforeEach -> keydown('=') keydown('=') it "indents the current line", -> expect(editor.indentationForBufferRow(1)).toBe 0 describe "when followed by a repeating =", -> beforeEach -> keydown('2') keydown('=') keydown('=') it "autoindents multiple lines at once", -> expect(editor.getText()).toBe "foo\nbar\nbaz" expect(editor.getCursorScreenPosition()).toEqual [1, 0] describe "undo behavior", -> beforeEach -> keydown('u') it "indents both lines", -> expect(editor.getText()).toBe "foo\n bar\n baz" describe "the . keybinding", -> beforeEach -> editor.setText("12\n34\n56\n78") editor.setCursorScreenPosition([0,0]) it "repeats the last operation", -> keydown '2' keydown 'd' keydown 'd' keydown '.' expect(editor.getText()).toBe "" it "composes with motions", -> keydown 'd' keydown 'd' keydown '2' keydown '.' expect(editor.getText()).toBe "78" describe "the r keybinding", -> beforeEach -> editor.setText("12\n34\n\n") editor.setCursorBufferPosition([0,0]) it "replaces a single character", -> keydown('r') commandModeInputKeydown('x') expect(editor.getText()).toBe 'x2\n34\n\n' it "composes properly with motions", -> keydown('2') keydown('r') commandModeInputKeydown('x') expect(editor.getText()).toBe 'xx\n34\n\n' it "does nothing on an empty line", -> editor.setCursorBufferPosition([2, 0]) keydown('r') commandModeInputKeydown('x') expect(editor.getText()).toBe '12\n34\n\n' it "does nothing if asked to replace more characters than there are on a line", -> keydown('3') keydown('r') commandModeInputKeydown('x') expect(editor.getText()).toBe '12\n34\n\n' describe 'the m keybinding', -> beforeEach -> editor.setText('12\n34\n56\n') editor.setCursorBufferPosition([0,1]) it 'marks a position', -> keydown('m') commandModeInputKeydown('a') expect(vimState.getMark('a')).toEqual [0,1] describe 'the ~ keybinding', -> beforeEach -> editor.setText('aBc') editor.setCursorBufferPosition([0, 0]) it 'toggles the case and moves right', -> keydown('~') expect(editor.getText()).toBe 'ABc' expect(editor.getCursorScreenPosition()).toEqual [0, 1] keydown('~') expect(editor.getText()).toBe 'Abc' expect(editor.getCursorScreenPosition()).toEqual [0, 2] keydown('~') expect(editor.getText()).toBe 'AbC' expect(editor.getCursorScreenPosition()).toEqual [0, 2] it 'can be repeated', -> keydown('4') keydown('~') expect(editor.getText()).toBe 'AbC' expect(editor.getCursorScreenPosition()).toEqual [0, 2] describe "the i keybinding", -> beforeEach -> editor.setText('') editor.setCursorBufferPosition([0, 0]) it "allows undoing an entire batch of typing", -> keydown 'i' editor.insertText("abc") keydown 'escape' keydown 'i' editor.insertText("def") keydown 'escape' expect(editor.getText()).toBe "abdefc" keydown 'u' expect(editor.getText()).toBe "abc" keydown 'u' expect(editor.getText()).toBe "" it "allows repeating typing", -> keydown 'i' editor.insertText("abc") keydown 'escape' keydown '.' editor.insertText("ababcc") # This one doesn't work because we can't simulate typing correctly, # and VimState#resetInputTransactions actually inspects buffer patches to # build patches for repeating xit "resets transactions for repeats after movement", -> editor.setCursorBufferPosition([0, 0]) editor.insertText("abc\n123") keydown 'i' editor.insertText("def") editorView.trigger 'core:move-down' expect(editor.getCursorBufferPosition()).toEqual [1, 3] editor.insertText("456") keydown 'escape' editor.setCursorBufferPosition([0, 0]) keydown '.' expect(editor.getText()).toEqual "456defabc\n456123" describe 'the a keybinding', -> beforeEach -> editor.setText('') editor.setCursorBufferPosition([0, 0]) it "can be undone in one go", -> keydown 'a' editor.insertText("abc") keydown 'escape' expect(editor.getText()).toBe "abc" keydown 'u' expect(editor.getText()).toBe "" it "repeats correctly", -> keydown 'a' editor.insertText("abc") keydown 'escape' expect(editor.getText()).toBe "abc" keydown '.' expect(editor.getText()).toBe "abcabc"