mirror of
https://github.com/atom/atom.git
synced 2026-02-09 06:05:11 -05:00
Single-digit numeric prefixes can repeat commands in vim-mode
Vim mode has an operator stack. Every time an operator is pushed to the stack, we ask if it is complete. If it's complete, we compose it with the operator below it, then pop that operator if its complete. When no operators remain on the stack, we call execute the final composed operator. So far we only have DeleteChar (x) and NumericPrefix operators.
This commit is contained in:
@@ -61,7 +61,7 @@ class Editor extends Template
|
||||
getCursor: ->
|
||||
@getAceSession().getSelection().getCursor()
|
||||
|
||||
delete: ->
|
||||
deleteChar: ->
|
||||
@aceEditor.remove 'right'
|
||||
|
||||
|
||||
|
||||
@@ -19,10 +19,20 @@ class GlobalKeymap
|
||||
candidateBindingSets.sort (a, b) -> b.specificity - a.specificity
|
||||
for bindingSet in candidateBindingSets
|
||||
if command = bindingSet.commandForEvent(event)
|
||||
$(event.target).trigger(command)
|
||||
@triggerCommandEvent(event, command)
|
||||
return false
|
||||
currentNode = currentNode.parent()
|
||||
true
|
||||
|
||||
reset: ->
|
||||
@BindingSets = []
|
||||
|
||||
triggerCommandEvent: (keyEvent, commandName) ->
|
||||
commandEvent = $.Event(commandName)
|
||||
keyEvent.char = @charForKeyEvent(keyEvent)
|
||||
commandEvent.keyEvent = keyEvent
|
||||
$(keyEvent.target).trigger(commandEvent)
|
||||
|
||||
charForKeyEvent: (keyEvent) ->
|
||||
String.fromCharCode(keyEvent.which).toLowerCase()
|
||||
|
||||
|
||||
25
src/atom/vim-mode-operators.coffee
Normal file
25
src/atom/vim-mode-operators.coffee
Normal file
@@ -0,0 +1,25 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
NumericPrefix: class
|
||||
count: null
|
||||
operatorToRepeat: null
|
||||
complete: null
|
||||
|
||||
constructor: (@count) ->
|
||||
@complete = false
|
||||
|
||||
compose: (@operatorToRepeat) ->
|
||||
@complete = true
|
||||
|
||||
isComplete: -> @complete
|
||||
|
||||
execute: (editor) ->
|
||||
_.times @count, => @operatorToRepeat.execute(editor)
|
||||
|
||||
DeleteChar: class
|
||||
execute: (editor) ->
|
||||
editor.deleteChar()
|
||||
|
||||
isComplete: -> true
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
_ = require 'underscore'
|
||||
$ = require 'jquery'
|
||||
{ NumericPrefix, DeleteChar } = require 'vim-mode-operators'
|
||||
|
||||
module.exports =
|
||||
class VimMode
|
||||
editor: null
|
||||
opStack: null
|
||||
|
||||
constructor: (@editor) ->
|
||||
atom.bindKeys '.command-mode'
|
||||
'i': 'insert-mode:activate'
|
||||
'x': 'command-mode:delete'
|
||||
|
||||
atom.bindKeys '.insert-mode'
|
||||
'<esc>': 'command-mode:activate'
|
||||
@opStack = []
|
||||
atom.bindKeys '.command-mode', @commandModeBindings()
|
||||
atom.bindKeys '.insert-mode', '<esc>': 'command-mode:activate'
|
||||
|
||||
@editor.addClass('command-mode')
|
||||
|
||||
@editor.on 'insert-mode:activate', => @activateInsertMode()
|
||||
@editor.on 'command-mode:activate', => @activateCommandMode()
|
||||
@editor.on 'command-mode:delete', => @delete()
|
||||
@editor.on 'command-mode:delete-char', => @deleteChar()
|
||||
@editor.on 'command-mode:numeric-prefix', (e) => @numericPrefix(e)
|
||||
|
||||
activateInsertMode: ->
|
||||
@editor.removeClass('command-mode')
|
||||
@@ -24,5 +27,33 @@ class VimMode
|
||||
@editor.removeClass('insert-mode')
|
||||
@editor.addClass('command-mode')
|
||||
|
||||
delete: ->
|
||||
@editor.delete()
|
||||
deleteChar: ->
|
||||
@pushOperator(new DeleteChar)
|
||||
|
||||
numericPrefix: (e) ->
|
||||
@pushOperator(new NumericPrefix(e.keyEvent.char))
|
||||
|
||||
commandModeBindings: ->
|
||||
bindings =
|
||||
'i': 'insert-mode:activate'
|
||||
'x': 'command-mode:delete-char'
|
||||
for i in [0..9]
|
||||
bindings[i] = 'command-mode:numeric-prefix'
|
||||
bindings
|
||||
|
||||
pushOperator: (op) ->
|
||||
@opStack.push(op)
|
||||
@processOpStack()
|
||||
|
||||
processOpStack: ->
|
||||
return unless @topOperator().isComplete()
|
||||
poppedOperator = @opStack.pop()
|
||||
if @opStack.length
|
||||
@topOperator().compose(poppedOperator)
|
||||
@processOpStack()
|
||||
else
|
||||
poppedOperator.execute(@editor)
|
||||
|
||||
topOperator: ->
|
||||
_.last @opStack
|
||||
|
||||
|
||||
Reference in New Issue
Block a user