Vim-mode is dead code

This commit is contained in:
Corey Johnson
2012-10-25 11:46:29 -07:00
parent 2af29c9934
commit d60bddf290
5 changed files with 0 additions and 610 deletions

View File

@@ -1,130 +0,0 @@
_ = require 'underscore'
$ = require 'jquery'
operators = require 'vim-mode/src/operators'
commands = require 'vim-mode/src/commands'
motions = require 'vim-mode/src/motions'
module.exports =
class VimMode
editor: null
opStack: null
constructor: (@editor) ->
requireStylesheet 'vim-mode.css'
@opStack = []
@activateCommandMode()
window.keymap.bindKeys '.editor', 'escape': 'activate-command-mode'
@editor.on 'activate-command-mode', => @activateCommandMode()
@setupCommandMode()
setupCommandMode: ->
window.keymap.bindKeys '.command-mode', (e) =>
if e.keystroke.match /^\d$/
return 'command-mode:numeric-prefix'
if e.keystroke.match /^.$/
@resetCommandMode()
return false
@bindCommandModeKeys
'i': 'insert'
'd': 'delete'
'x': 'delete-right'
'h': 'core:move-left'
'j': 'core:move-down'
'k': 'core:move-up'
'l': 'core:move-right'
'w': 'move-to-next-word'
'b': 'move-to-previous-word'
'}': 'move-to-next-paragraph'
'escape': 'reset-command-mode'
'left': 'move-left'
'right': 'move-right'
@handleCommands
'insert': => @activateInsertMode()
'delete': => @delete()
'delete-right': => new commands.DeleteRight(@editor)
'core:move-left': => new motions.MoveLeft(@editor)
'core:move-up': => new motions.MoveUp(@editor)
'core:move-down': => new motions.MoveDown @editor
'core:move-right': => new motions.MoveRight @editor
'move-to-next-word': => new motions.MoveToNextWord(@editor)
'move-to-previous-word': => new motions.MoveToPreviousWord(@editor)
'move-to-next-paragraph': => new motions.MoveToNextParagraph(@editor)
'numeric-prefix': (e) => @numericPrefix(e)
'reset-command-mode': => @resetCommandMode()
bindCommandModeKeys: (bindings) ->
prefixedBindings = {}
for pattern, commandName of bindings
prefixedBindings[pattern] = "command-mode:#{commandName}"
window.keymap.bindKeys ".command-mode", prefixedBindings
handleCommands: (commands) ->
_.each commands, (fn, commandName) =>
eventName = "command-mode:#{commandName}"
@editor.on eventName, (e) =>
possibleOperator = fn(e)
@pushOperator(possibleOperator) if possibleOperator?.execute
activateInsertMode: ->
@editor.removeClass('command-mode')
@editor.addClass('insert-mode')
@editor.off 'cursor:position-changed', @moveCursorBeforeNewline
activateCommandMode: ->
@editor.removeClass('insert-mode')
@editor.addClass('command-mode')
@editor.on 'cursor:position-changed', @moveCursorBeforeNewline
resetCommandMode: ->
@opStack = []
moveCursorBeforeNewline: =>
if not @editor.getSelection().modifyingSelection and @editor.cursor.isOnEOL() and @editor.getCurrentBufferLine().length > 0
@editor.setCursorBufferColumn(@editor.getCurrentBufferLine().length - 1)
numericPrefix: (e) ->
num = parseInt(e.keyEvent.keystroke)
if @topOperator() instanceof operators.NumericPrefix
@topOperator().addDigit(num)
else
@pushOperator(new operators.NumericPrefix(num))
delete: () ->
if deleteOperation = @isDeletePending()
deleteOperation.complete = true
@processOpStack()
else
@pushOperator(new operators.Delete(@editor))
isDeletePending: () ->
for op in @opStack
return op if op instanceof operators.Delete
false
pushOperator: (op) ->
@opStack.push(op)
@processOpStack()
processOpStack: ->
return unless @topOperator().isComplete()
poppedOperator = @opStack.pop()
if @opStack.length
try
@topOperator().compose(poppedOperator)
@processOpStack()
catch e
(e instanceof operators.OperatorError) and @resetCommandMode() or throw e
else
poppedOperator.execute()
topOperator: ->
_.last @opStack

View File

@@ -1,324 +0,0 @@
Editor = require 'editor'
VimMode = require 'vim-mode'
xdescribe "VimMode", ->
[editor, vimMode] = []
beforeEach ->
editor = new Editor
editor.enableKeymap()
editor.isFocused = true
vimMode = new VimMode(editor)
describe "initialize", ->
it "puts the editor in command-mode initially", ->
expect(editor).toHaveClass 'command-mode'
describe "command-mode", ->
it "stops propagation on key events would otherwise insert a character, but allows unhandled non-insertions through", ->
event = keydownEvent('\\')
spyOn(event, 'stopPropagation')
editor.trigger event
expect(event.stopPropagation).toHaveBeenCalled()
event = keydownEvent('/', metaKey: true)
spyOn(event, 'stopPropagation')
editor.trigger event
expect(event.stopPropagation).not.toHaveBeenCalled()
it "does not allow the cursor to be placed on the \n character, unless the line is empty", ->
editor.setText("012345\n\nabcdef")
editor.setCursorScreenPosition([0, 5])
expect(editor.getCursorScreenPosition()).toEqual [0,5]
editor.setCursorScreenPosition([0, 6])
expect(editor.getCursorScreenPosition()).toEqual [0,5]
editor.setCursorScreenPosition([1, 0])
expect(editor.getCursorScreenPosition()).toEqual [1,0]
it "clears the operator stack when commands can't be composed", ->
editor.trigger keydownEvent('d')
expect(vimMode.opStack.length).toBe 1
editor.trigger keydownEvent('x')
expect(vimMode.opStack.length).toBe 0
editor.trigger keydownEvent('d')
expect(vimMode.opStack.length).toBe 1
editor.trigger keydownEvent('\\') # \ is an unused key in vim
expect(vimMode.opStack.length).toBe 0
describe "the escape keybinding", ->
it "clears the operator stack", ->
editor.trigger keydownEvent('d')
expect(vimMode.opStack.length).toBe 1
editor.trigger keydownEvent('escape')
expect(vimMode.opStack.length).toBe 0
describe "the i keybinding", ->
it "puts the editor into insert mode", ->
expect(editor).not.toHaveClass 'insert-mode'
editor.trigger keydownEvent('i')
expect(editor).toHaveClass 'insert-mode'
expect(editor).not.toHaveClass 'command-mode'
describe "the x keybinding", ->
it "deletes a charachter", ->
editor.setText("012345")
editor.setCursorScreenPosition([0, 4])
editor.trigger keydownEvent('x')
expect(editor.getText()).toBe '01235'
expect(editor.getCursorScreenPosition()).toEqual([0, 4])
editor.trigger keydownEvent('x')
expect(editor.getText()).toBe '0123'
expect(editor.getCursorScreenPosition()).toEqual([0, 3])
editor.trigger keydownEvent('x')
expect(editor.getText()).toBe '012'
expect(editor.getCursorScreenPosition()).toEqual([0, 2])
it "deletes nothing when cursor is on empty line", ->
editor.getBuffer().setText "012345\n\nabcdef"
editor.setCursorScreenPosition [1, 0]
editor.trigger keydownEvent 'x'
expect(editor.getText()).toBe "012345\n\nabcdef"
describe "the d keybinding", ->
describe "when followed by a d", ->
it "deletes the current line", ->
editor.setText("12345\nabcde\nABCDE")
editor.setCursorScreenPosition([1,1])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('d')
expect(editor.getText()).toBe "12345\nABCDE"
expect(editor.getCursorScreenPosition()).toEqual([1,0])
it "deletes the last line", ->
editor.setText("12345\nabcde\nABCDE")
editor.setCursorScreenPosition([2,1])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('d')
expect(editor.getText()).toBe "12345\nabcde"
expect(editor.getCursorScreenPosition()).toEqual([1,0])
xdescribe "when the second d is prefixed by a count", ->
it "deletes n lines, starting from the current", ->
editor.setText("12345\nabcde\nABCDE\nQWERT")
editor.setCursorScreenPosition([1,1])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('2')
editor.trigger keydownEvent('d')
expect(editor.getText()).toBe "12345\nQWERT"
expect(editor.getCursorScreenPosition()).toEqual([1,0])
describe "when followed by an h", ->
it "deletes the previous letter on the current line", ->
editor.setText("abcd\n01234")
editor.setCursorScreenPosition([1,1])
editor.trigger keydownEvent 'd'
editor.trigger keydownEvent 'h'
expect(editor.getText()).toBe "abcd\n1234"
expect(editor.getCursorScreenPosition()).toEqual([1,0])
editor.trigger keydownEvent 'd'
editor.trigger keydownEvent 'h'
expect(editor.getText()).toBe "abcd\n1234"
expect(editor.getCursorScreenPosition()).toEqual([1,0])
describe "when followed by a w", ->
it "deletes to the beginning of the next word", ->
editor.setText("abcd efg")
editor.setCursorScreenPosition([0,2])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('w')
expect(editor.getText()).toBe "abefg"
expect(editor.getCursorScreenPosition()).toEqual([0,2])
editor.setText("one two three four")
editor.setCursorScreenPosition([0,0])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('3')
editor.trigger keydownEvent('w')
expect(editor.getText()).toBe "four"
expect(editor.getCursorScreenPosition()).toEqual([0,0])
describe "when followed by a b", ->
it "deletes to the beginning of the previous word", ->
editor.setText("abcd efg")
editor.setCursorScreenPosition([0,2])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('b')
expect(editor.getText()).toBe "cd efg"
expect(editor.getCursorScreenPosition()).toEqual([0,0])
editor.setText("one two three four")
editor.setCursorScreenPosition([0,11])
editor.trigger keydownEvent('d')
editor.trigger keydownEvent('3')
editor.trigger keydownEvent('b')
expect(editor.getText()).toBe "ee four"
expect(editor.getCursorScreenPosition()).toEqual([0,0])
describe "basic motion bindings", ->
beforeEach ->
editor.setText("12345\nabcde\nABCDE")
editor.setCursorScreenPosition([1,1])
describe "the h keybinding", ->
it "moves the cursor left, but not to the previous line", ->
editor.trigger keydownEvent('h')
expect(editor.getCursorScreenPosition()).toEqual([1,0])
editor.trigger keydownEvent('h')
expect(editor.getCursorScreenPosition()).toEqual([1,0])
describe "the j keybinding", ->
it "moves the cursor down, but not to the end of the last line", ->
editor.trigger keydownEvent 'j'
expect(editor.getCursorScreenPosition()).toEqual([2,1])
editor.trigger keydownEvent 'j'
expect(editor.getCursorScreenPosition()).toEqual([2,1])
describe "the k keybinding", ->
it "moves the cursor up, but not to the beginning of the first line", ->
editor.trigger keydownEvent('k')
expect(editor.getCursorScreenPosition()).toEqual([0,1])
editor.trigger keydownEvent('k')
expect(editor.getCursorScreenPosition()).toEqual([0,1])
describe "the l keybinding", ->
it "moves the cursor right, but not to the next line", ->
editor.setCursorScreenPosition([1,3])
editor.trigger keydownEvent('l')
expect(editor.getCursorScreenPosition()).toEqual([1,4])
editor.trigger keydownEvent('l')
expect(editor.getCursorScreenPosition()).toEqual([1,4])
describe "the w keybinding", ->
it "moves the cursor to the beginning of the next word", ->
editor.setText("ab cde1+- \n xyz\n\nzip")
editor.setCursorScreenPosition([0,0])
editor.trigger keydownEvent('w')
expect(editor.getCursorScreenPosition()).toEqual([0,3])
editor.trigger keydownEvent('w')
expect(editor.getCursorScreenPosition()).toEqual([0,7])
editor.trigger keydownEvent('w')
expect(editor.getCursorScreenPosition()).toEqual([1,1])
editor.trigger keydownEvent('w')
expect(editor.getCursorScreenPosition()).toEqual([2,0])
editor.trigger keydownEvent('w')
expect(editor.getCursorScreenPosition()).toEqual([3,0])
editor.trigger keydownEvent('w')
expect(editor.getCursorScreenPosition()).toEqual([3,2])
describe "the { keybinding", ->
it "moves the cursor to the beginning of the paragraph", ->
editor.setText("abcde\n\nfghij\nhijk\n xyz \n\nzip\n\n \nthe end")
editor.setCursorScreenPosition([0,0])
editor.trigger keydownEvent('}')
expect(editor.getCursorScreenPosition()).toEqual [1,0]
editor.trigger keydownEvent('}')
expect(editor.getCursorScreenPosition()).toEqual [5,0]
editor.trigger keydownEvent('}')
expect(editor.getCursorScreenPosition()).toEqual [7,0]
editor.trigger keydownEvent('}')
expect(editor.getCursorScreenPosition()).toEqual [9,6]
describe "the b keybinding", ->
it "moves the cursor to the beginning of the previous word", ->
editor.setText(" ab cde1+- \n xyz\n\nzip }\n last")
editor.setCursorScreenPosition [4,1]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [3,4]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [3,0]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [2,0]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [1,1]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [0,8]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [0,4]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [0,1]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [0,0]
editor.trigger keydownEvent('b')
expect(editor.getCursorScreenPosition()).toEqual [0,0]
describe "numeric prefix bindings", ->
it "repeats the following operation N times", ->
editor.setText("12345")
editor.setCursorScreenPosition([0,1])
editor.trigger keydownEvent('3')
editor.trigger keydownEvent('x')
expect(editor.getText()).toBe '15'
editor.setText("123456789abc")
editor.setCursorScreenPosition([0,0])
editor.trigger keydownEvent('1')
editor.trigger keydownEvent('0')
editor.trigger keydownEvent('x')
expect(editor.getText()).toBe 'bc'
describe "insert-mode", ->
beforeEach ->
editor.trigger keydownEvent('i')
it "allows the cursor to reach the end of the line", ->
editor.setText("012345\n\nabcdef")
editor.setCursorScreenPosition([0, 5])
expect(editor.getCursorScreenPosition()).toEqual [0,5]
editor.setCursorScreenPosition([0, 6])
expect(editor.getCursorScreenPosition()).toEqual [0,6]
it "puts the editor into command mode when <escape> is pressed", ->
expect(editor).not.toHaveClass 'command-mode'
editor.trigger keydownEvent('escape')
expect(editor).toHaveClass 'command-mode'
expect(editor).not.toHaveClass 'insert-mode'

View File

@@ -1,10 +0,0 @@
class Command
constructor: (@editor) ->
isComplete: -> true
class DeleteRight extends Command
execute: ->
@editor.delete() unless @editor.getCurrentBufferLine().length == 0
module.exports = { DeleteRight }

View File

@@ -1,89 +0,0 @@
Point = require 'point'
getWordRegex = -> /(\w+)|([^\w\s]+)/g
class Motion
constructor: (@editor) ->
isComplete: -> true
class MoveLeft extends Motion
execute: ->
{column, row} = @editor.getCursorScreenPosition()
@editor.moveCursorLeft() if column > 0
select: ->
position = @editor.getCursorScreenPosition().copy()
position.column-- if position.column > 0
@editor.selectToBufferPosition(position)
class MoveRight extends Motion
execute: ->
{column, row} = @editor.getCursorScreenPosition()
@editor.moveCursorRight()
class MoveUp extends Motion
execute: ->
{column, row} = @editor.getCursorScreenPosition()
@editor.moveCursorUp() if row > 0
class MoveDown extends Motion
execute: ->
{column, row} = @editor.getCursorScreenPosition()
@editor.moveCursorDown() if row < (@editor.getBuffer().getLineCount() - 1)
class MoveToPreviousWord extends Motion
execute: ->
@editor.getCursor().moveToBeginningOfWord()
select: ->
@editor.getSelection().selectToBeginningOfWord()
class MoveToNextWord extends Motion
execute: ->
@editor.setCursorScreenPosition(@nextWordPosition())
select: ->
@editor.selectToBufferPosition(@nextWordPosition())
nextWordPosition: ->
regex = getWordRegex()
{ row, column } = @editor.getCursorScreenPosition()
rightOfCursor = @editor.lineForBufferRow(row).substring(column)
match = regex.exec(rightOfCursor)
# If we're on top of part of a word, match the next one.
match = regex.exec(rightOfCursor) if match?.index is 0
if match
column += match.index
else if row + 1 == @editor.getBuffer().getLineCount()
column = @editor.lineForBufferRow(row).length
else
nextLineMatch = regex.exec(@editor.lineForBufferRow(++row))
column = nextLineMatch?.index or 0
{ row, column }
class MoveToNextParagraph extends Motion
execute: ->
@editor.setCursorScreenPosition(@nextPosition())
select: ->
@editor.selectToPosition(@nextPosition())
nextPosition: ->
regex = /[^\n]\n^$/gm
row = null
column = 0
startRow = @editor.getCursorBufferRow() + 1
for r in [startRow..@editor.getLastBufferRow()]
if @editor.lineForBufferRow(r).length == 0
row = r
break
if not row
row = @editor.getLastBufferRow()
column = @editor.getBuffer().getLastLine().length - 1
new Point(row, column)
module.exports = { Motion, MoveLeft, MoveRight, MoveUp, MoveDown, MoveToNextWord, MoveToPreviousWord, MoveToNextParagraph }

View File

@@ -1,57 +0,0 @@
_ = require 'underscore'
class OperatorError
constructor: (@message) ->
@name = "Operator Error"
class NumericPrefix
count: null
complete: null
operatorToRepeat: null
constructor: (@count) ->
@complete = false
isComplete: -> @complete
compose: (@operatorToRepeat) ->
@complete = true
if @operatorToRepeat.setCount?
@operatorToRepeat.setCount @count
@count = 1
addDigit: (digit) ->
@count = @count * 10 + digit
execute: ->
_.times @count, => @operatorToRepeat.execute()
select: ->
_.times @count, => @operatorToRepeat.select()
class Delete
motion: null
complete: null
constructor: (@editor) ->
@complete = false
isComplete: -> @complete
execute: ->
if @motion
@motion.select()
@editor.getSelection().delete()
else
@editor.getBuffer().deleteRow(@editor.getCursorBufferRow())
@editor.setCursorScreenPosition([@editor.getCursorScreenRow(), 0])
compose: (motion) ->
if not motion.select
throw new OperatorError("Delete must compose with a motion")
@motion = motion
@complete = true
module.exports = { NumericPrefix, Delete, OperatorError }