Skip to content

ExtendVimModePlusInInitFile

t9md edited this page Oct 5, 2017 · 17 revisions

Overview

🚨 🚨 🚨 🚨 🚨 🚨
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)
      }
    })
  }
}

Examples

[Simple] moveUp/moveDown motion

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.

Directly define in init.js
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()
})
Load external file from init.cofee
  • 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}
}

[Basic] InsertSpaces operator which insert specified count of spaces

  • 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 `.`

[Basic] 5 lines moveUp/moveDown motion

  • 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'

[Advanced] move-up(down)-to-same-indent

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'

[Advanced] TransformString by external command

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()
}

[Advanced] DeleteWithBackholeRegister

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`.
Clone this wiki locally