-
Notifications
You must be signed in to change notification settings - Fork 108
ExtendVimModePlusInInitFile
🚨 🚨 🚨 🚨 🚨 🚨
From vmp v1.9.0, you can not use CoffeeScript to extend vmp.
Why? vmp's operations are implemented as ES6 class which is incompatible with CoffeeScript's class.
🚨 🚨 🚨 🚨 🚨 🚨
You can create original Motion/Operator/TextObject by extending existing operation class defined in vmp-core.
First define following function in your init.js
or init.coffee
- init.coffee
# init.coffee
# -coffeescript----------------------
# General service consumer function
consumeService = (packageName, providerName, fn) ->
if atom.packages.isPackageActive(packageName)
pack = atom.packages.getActivePackage(packageName)
fn(pack.mainModule[providerName]())
else
disposable = atom.packages.onDidActivatePackage (pack) ->
if pack.name is packageName
disposable.dispose()
fn(pack.mainModule[providerName]())
- init.js
function consumeService(packageName, functionName, fn) {
const consume = pack => fn(pack.mainModule[functionName]())
if (atom.packages.isPackageActive(packageName)) {
consume(atom.packages.getActivePackage(packageName))
} else {
const disposable = atom.packages.onDidActivatePackage(pack => {
if (pack.name === packageName) {
disposable.dispose()
consume(pack)
}
})
}
}
All vim-mode-plus's commands must inherit Base
class directly or indirectly.
Above registerCommand()
function is Base class's static function.
When you call registerCommand
your class name(MoveUp
or MoveDown
here) is transformed to dash-case string by prefixing klass.commandPrefix
.
So you get vim-mode-plus-user:move-up
and vim-mode-plus-user:move-down
commands here.
All the rest you have to do is set keymap for those commands.
- 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'
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.
consumeService("vim-mode-plus", "provideVimModePlus", ({Base}) => {
class MoveUp extends Base.getClass("Motion") {
moveCursor(cursor) {
cursor.moveUp()
}
}
MoveUp.commandPrefix = "vim-mode-plus-user"
MoveUp.registerCommand()
class MoveDown extends MoveUp {
moveCursor(cursor) {
cursor.moveDown()
}
}
MoveDown.registerCommand()
})
- init.coffee
consumeService 'vim-mode-plus', 'provideVimModePlus', (service) ->
commands = require('./load-vmp-commands')(service)
for name, klass of commands
klass.commandPrefix = "vim-mode-plus-user"
klass.registerCommand()
- load-vmp-commands.js
module.exports = function loadVmpCommands({Base}) {
class MoveUp extends Base.getClass("Motion") {
moveCursor(cursor) {
cursor.moveUp()
}
}
class MoveDown extends MoveUp {
moveCursor(cursor) {
cursor.moveDown()
}
}
return {MoveUp, MoveDown}
}
- init.js
"use babel"
class InsertSpaces extends Base.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"
class MoveFiveLinesUp extends Base.getClass("MoveUp") {
static commandPrefix = "vim-mode-plus-user"
defaultCount = 5
}
MoveFiveLinesUp.registerCommand()
class MoveFiveLinesDown extends Base.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()
class MoveUpToSameIndent Base.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.
const TransformStringByExternalCommand = Base.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()
}
class DeleteWithBackholeRegister extends Base.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`.