diff --git a/spec/atom/vim-mode-spec.coffee b/spec/atom/vim-mode-spec.coffee index cd5067941..49872dc88 100644 --- a/spec/atom/vim-mode-spec.coffee +++ b/spec/atom/vim-mode-spec.coffee @@ -192,10 +192,41 @@ describe "VimMode", -> editor.trigger keydownEvent('w') expect(editor.getCursorPosition()).toEqual([3,0]) - editor.setCursorPosition [3,0] editor.trigger keydownEvent('w') expect(editor.getCursorPosition()).toEqual([3,2]) + describe "the b keybinding", -> + it "moves the cursor to the beginning of the previous word", -> + editor.buffer.setText(" ab cde1+- \n xyz\n\nzip }\n last") + editor.setCursorPosition [4,1] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [3,4] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [3,0] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [2,0] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [1,1] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [0,8] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [0,4] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [0,1] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [0,0] + + editor.trigger keydownEvent('b') + expect(editor.getCursorPosition()).toEqual [0,0] + describe "numeric prefix bindings", -> it "repeats the following operation N times", -> editor.buffer.setText("12345") diff --git a/src/atom/cursor.coffee b/src/atom/cursor.coffee index 898e1f52e..34db44eec 100644 --- a/src/atom/cursor.coffee +++ b/src/atom/cursor.coffee @@ -88,6 +88,28 @@ class Cursor extends View @setPosition({row, column}) + moveLeftWhile: (regex) -> + row = @getRow() + column = @getColumn() + offset = 0 + + matchBackwards = => + line = @editor.buffer.getLine(row) + reversedLine = line[0...column].split('').reverse().join('') + regex.exec reversedLine + + if not match = matchBackwards() + if row > 0 + row-- + column = @editor.buffer.getLineLength(row) + match = matchBackwards() + else + column = 0 + + offset = match and -match[0].length or 0 + + @setPosition [row, column + offset] + updateAppearance: -> position = @editor.pixelPositionFromPoint(@point) @css(position) diff --git a/src/atom/vim-mode.coffee b/src/atom/vim-mode.coffee index 5728fc30a..be23eccce 100644 --- a/src/atom/vim-mode.coffee +++ b/src/atom/vim-mode.coffee @@ -36,6 +36,7 @@ class VimMode 'k': 'move-up' 'l': 'move-right' 'w': 'move-to-next-word' + 'b': 'move-to-previous-word' @handleCommands 'insert': => @activateInsertMode() @@ -46,6 +47,7 @@ class VimMode 'move-down': => new motions.MoveDown @editor 'move-right': => new motions.MoveRight @editor 'move-to-next-word': => new motions.MoveToNextWord(@editor) + 'move-to-previous-word': => new motions.MoveToPreviousWord(@editor) 'numeric-prefix': (e) => @numericPrefix(e) bindCommandModeKeys: (bindings) -> diff --git a/src/atom/vim-mode/motions.coffee b/src/atom/vim-mode/motions.coffee index d317b6c12..d3e9806ae 100644 --- a/src/atom/vim-mode/motions.coffee +++ b/src/atom/vim-mode/motions.coffee @@ -29,6 +29,10 @@ class MoveDown extends Motion {column, row} = @editor.getCursorPosition() @editor.moveCursorDown() if row < (@editor.buffer.numLines() - 1) +class MoveToPreviousWord extends Motion + execute: -> + @editor.cursor.moveLeftWhile /^\s*(\w+|[^A-Za-z0-9_ ]+)/g + class MoveToNextWord extends Motion execute: -> @editor.setCursorPosition(@nextWordPosition()) @@ -54,4 +58,4 @@ class MoveToNextWord extends Motion column = nextLineMatch?.index or 0 { row, column } -module.exports = { MoveLeft, MoveRight, MoveUp, MoveDown, MoveToNextWord } +module.exports = { MoveLeft, MoveRight, MoveUp, MoveDown, MoveToNextWord, MoveToPreviousWord }