-
Notifications
You must be signed in to change notification settings - Fork 112
ExtendVimModePlusInInitFile
You can create original Motion/Operator/TextObject by extending existing operation class defined in vmp-core.
🚨 🚨 🚨 🚨 🚨 🚨
From vmp v1.9.0, you must use JavaScript(ES6 class) to extend vmp, CoffeeScript-v1 is no longer supported to extend vmp.
Why? vmp's operations are implemented as ES6 class which is incompatible with CoffeeScript's class.
🚨 🚨 🚨 🚨 🚨 🚨
Here is the steps.
- Define your own operation in your
init.js
- Configure keymap if necessary
See this template
function consumeVimModePlusService(callback) {
const consume = (pack) => callback(pack.mainModule.provideVimModePlus())
const pack = atom.packages.getActivePackage('vim-mode-plus')
if (pack) {
consume(pack)
} else {
const disposable = atom.packages.onDidActivatePackage(pack => {
if (pack.name === 'vim-mode-plus') {
disposable.dispose()
consume(pack)
}
})
}
}
consumeVimModePlusService(service => {
// Define your own operation FROM HERE
class MyMotion extends service.getClass("Motion") {
execute() {
console.log("my motion!");
}
}
MyMotion.commandPrefix = "vim-mode-plus-user"
// `registerCommand()` here register "vim-mode-plus-user:my-motion" command
// Which log "my motion" to console when invoked.
MyMotion.registerCommand()
// Define your own operation TO HERE
})
As simple example we will define our own version of move-up
/move-down
motion.
- All vmp command class must inherit
Base
class directly or indirectly. - You can register command by calling
Base.registerCommand()
static fucntion. - Command name is derived from class name by
klass.commandPrefix + ':' + _.dasherize(klass.name)
.- When
klass.commandPrefix
isvim-mode-plus-user
-
MoveUp.registerCommand()
registervim-mode-plus-user:move-up
-
MoveDown.registerCommand()
registervim-mode-plus-user:move-down
-
- When
You must define vmp operation in ES6 class, you cannot use CoffeeScript, since vmp-core class is defined in ES6 class which is incompatible with CoffeScript-v1 used in Atom.
init.js
consumeVimModePlusService(service => {
class MoveUp extends service.getClass("Motion") {
moveCursor(cursor) {
cursor.moveUp()
}
}
MoveUp.commandPrefix = "vim-mode-plus-user"
MoveUp.registerCommand()
class MoveDown extends MoveUp {
moveCursor(cursor) {
cursor.moveDown()
}
}
MoveDown.registerCommand()
})
- keymap.cson
'atom-text-editor.vim-mode-plus:not(.insert-mode)':
'j': 'vim-mode-plus-user:move-down'
'k': 'vim-mode-plus-user:move-up'
- init.js
"use babel"
consumeVimModePlusService(service => {
class InsertSpaces extends service.getClass('Operator') {
static commandPrefix = 'vim-mode-plus-user'
requireTarget = false
execute() {
this.editor.insertText(" ".repeat(this.getCount()))
}
}
InsertSpaces.registerCommand()
})
// keymap.cson
// 'atom-text-editor.vim-mode-plus.normal-mode':
// 'g space': 'vim-mode-plus-user:insert-spaces'
//
// Description
// keystroke '3 g space' insert three spaces at cursor position
// multi-selection support, can repeat by `.`
- init.js
"use babel"
consumeVimModePlusService(service => {
class MoveFiveLinesUp extends service.getClass("MoveUp") {
static commandPrefix = "vim-mode-plus-user"
defaultCount = 5
}
MoveFiveLinesUp.registerCommand()
class MoveFiveLinesDown extends service.getClass("MoveDown") {
static commandPrefix = "vim-mode-plus-user"
defaultCount = 5
}
MoveFiveLinesDown.registerCommand()
})
- keymap.cson
'atom-text-editor.vim-mode-plus:not(.insert-mode)':
'J': 'vim-mode-plus-user:move-five-lines-down'
'K': 'vim-mode-plus-user:move-five-lines-up'
MoveUp/MoveDown to row which have same level of indentation.
- init.js
"use babel"
// borrow MoveUpToEdge.prototype.getScanRows()
consumeVimModePlusService(service => {
class MoveUpToSameIndent service.getClass("MoveUpToEdge") {
static commandPrefix = "vim-mode-plus-user"
moveCursor(cursor) {
const cursorRow = cursor.getBufferRow()
const baseIndentLevel = this.utils.getIndentLevelForBufferRow(this.editor, cursorRow)
const column = cursor.getBufferColumn()
this.countTimes(() => {
const newRow = this.getScanRows(cursor).find(
row => this.utils.getIndentLevelForBufferRow(this.editor, row) === baseIndentLevel
)
if (newRow != null) cursor.setBufferPosition([newRow, column])
})
}
}
MoveUpToSameIndent.registerCommand()
class MoveDownToSameIndent extends MoveUpToSameIndent {
direction = "down"
}
MoveDownToSameIndent.registerCommand()
})
- keymap.cson
'atom-text-editor.vim-mode-plus:not(.insert-mode)':
'(': 'vim-mode-plus-user:move-up-to-same-indent'
')': 'vim-mode-plus-user:move-down-to-same-indent'
By extending TransformStringByExternalCommand, user can add string transformer via external command.
consumeVimModePlusService(service => {
const TransformStringByExternalCommand = service.getClass("TransformStringByExternalCommand")
class CoffeeCompile extends TransformStringByExternalCommand {
command = "coffee"
args = ["-csb", "--no-header"]
}
class CoffeeEval extends TransformStringByExternalCommand {
command = "coffee"
args = ["-se"]
getStdin(selection) {
return `console.log ${selection.getText()}`
}
}
class CoffeeInspect extends TransformStringByExternalCommand {
command = "coffee"
args = ["-se"]
getStdin(selection) {
return `{inspect} = require 'util';console.log ${selection.getText()}`
}
}
for (const klass of [CoffeeCompile, CoffeeEval, CoffeeInspect]) {
klass.commandPrefix = "vim-mode-plus-user"
klass.registerCommand()
}
})
consumeVimModePlusService(service => {
class DeleteWithBackholeRegister extends service.getClass("Delete") {
execute() {
this.vimState.register.name = "_"
super.execute()
}
}
DeleteWithBackholeRegister.commandPrefix = "vim-mode-plus-user"
DeleteWithBackholeRegister.registerCommand()
})
- keymap.cson
'atom-text-editor.vim-mode-plus:not(.insert-mode)':
'\\ d': 'vim-mode-plus-user:delete-with-backhole-register'
'atom-text-editor.vim-mode-plus.delete-with-backhole-register-pending':
'd': 'vim-mode-plus-user:delete-with-backhole-register' # to support `\ d d`.
"use babel" // This must be at top of file
consumeVimModePlusService(service => {
class InsertCharacter extends service.getClass("Operator") {
static commandPrefix = "vim-mode-plus-user"
target = "Empty"
readInputAfterSelect = true
mutateSelection(selection) {
const point = selection.getHeadBufferPosition()
this.editor.setTextInBufferRange([point, point], this.input.repeat(this.getCount()))
}
}
InsertCharacter.registerCommand()
})