Skip to content

ExtendVimModePlusInInitFile

t9md edited this page Nov 3, 2016 · 17 revisions

Overview

You can extends vim-mode-plus by adding your original Motion/Operator/TextObject.
You don't even create Atom package, just adding small code in your init.coffee is enough.
I'll explain here HOW-TO.

First define following function in your init.coffee

# init.coffee
# -------------------------
# General service consumer function
consumeService = (packageName, providerName, fn) ->
  disposable = atom.packages.onDidActivatePackage (pack) ->
    if pack.name is packageName
      service = pack.mainModule[providerName]()
      fn(service)
      disposable.dispose()

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 function.
When you call registerCommand your class name(MoveUp or MoveDown here) is transformed to dash-case string by prefixing @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'
  • init.coffee
consumeService 'vim-mode-plus', 'provideVimModePlus', ({Base}) ->
  Motion = Base.getClass('Motion')
  class MoveUp extends Motion
    @commandPrefix: 'vim-mode-plus-user'
    moveCursor: (cursor) ->
      cursor.moveUp()

  class MoveDown extends Motion
    @commandPrefix: 'vim-mode-plus-user'
    moveCursor: (cursor) ->
      cursor.moveDown()

  MoveUp.registerCommand() # `vim-mode-plus-user:move-up`
  MoveDown.registerCommand() # `vim-mode-plus-user:move-up`

[Basic] InsertSpaces operator which insert specified count of spaces

class InsertSpaces extends Base.getClass('Operator')
  @commandPrefix: 'vim-mode-plus-user'
  @registerCommand()
  requireTarget: false
  execute: ->
    @editor.insertText(" ".repeat(@getCount()))

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

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

MoveUp/MoveDown to row which have same level of indentation.

  • 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'
  • init.coffee
consumeVimModePlus = getConsumer 'vim-mode-plus', 'provideVimModePlus'
requireVimModePlus = (path) ->
  packPath = atom.packages.resolvePackagePath('vim-mode-plus')
  require "#{packPath}/lib/#{path}"

consumeService 'vim-mode-plus', 'provideVimModePlus', ({Base}) ->
  _ = require 'underscore-plus'
  {getIndentLevelForBufferRow} = requireVimModePlus './utils'

  class MoveUpToSameIndent extends Base.getClass('MoveUpToNonBlank')
    @commandPrefix: 'vim-mode-plus-user'
    moveCursor: (cursor) ->
      cursorRow = cursor.getBufferRow()
      baseIndentLevel = getIndentLevelForBufferRow(@editor, cursorRow)
      column = cursor.getBufferColumn()
      @countTimes =>
        newRow = _.detect @getScanRows(cursor), (row) =>
          not @editor.isBufferRowBlank(row) and
            getIndentLevelForBufferRow(@editor, row) is baseIndentLevel
        if newRow?
          cursor.setBufferPosition([newRow, column])

  class MoveDownToSameIndent extends MoveUpToSameIndent
    @extend()
    direction: 'down'

  MoveUpToSameIndent.registerCommand()
  MoveDownToSameIndent.registerCommand()

[Advanced] TransformString by external command

By extending TransformStringByExternalCommand, user can add string transformer via external command(e.g. sort, wc).

consumeService 'vim-mode-plus', 'provideVimModePlus', ({Base}) ->
  TransformStringByExternalCommand = Base.getClass('TransformStringByExternalCommand')

  class Sort extends TransformStringByExternalCommand
    command: 'sort'

  class SortNumerical extends Sort
    command: 'sort'
    args: ['-n']

  class ReverseSort extends SortNumerical
    args: ['-r']

  class ReverseSortNumerical extends ReverseSort
    args: ['-rn']

  class CoffeeCompile extends TransformStringByExternalCommand
    command: 'coffee'
    args: ['-csb', '--no-header']
    getNewText: (text) ->
      @input.shift().replace(/\n$/, '')

  userTransformers = [
    Sort, SortNumerical, ReverseSort, ReverseSortNumerical, CoffeeCompile
  ]
  TransformStringBySelectList = Base.getClass('TransformStringBySelectList')
  for transformer in userTransformers
    transformer.commandPrefix = 'vim-mode-plus-user'
    transformer.registerCommand()
    # Push user transformer to transformers so that I can choose my transformers
    # via transform-string-by-select-list command.
    TransformStringBySelectList::transformers.push(transformer)

  # Just for demonstration, Simplify IncrementNumber and DecrementNumber
  Base.getClass('IncrementNumber')::displayName = '++'
  Base.getClass('DecrementNumber')::displayName = '--'

[Advanced] Modifying existing motion

In this example, directly modify existing motion to prevent cursor position change as a result of scrolling. Thus, making ctrl-f, ctrl-b, ctrl-u and ctrl-d to do only scroll without changing cursor position. You can go back to cursor position by escape.

consumeService 'vim-mode-plus', 'provideVimModePlus', ({Base}) ->
   # Override prototype function to do nothing(to prevent cursor position change.).
   # This require understanding existing implementation and not recommended since it affects
   # all the motions which inherits this class(in this case ctrl-b, ctrl-u, ctrl-d).
  Base.getClass('ScrollFullScreenDown')::moveCursor = ->

[Advanced] DeleteWithBackholeRegister

  • init.coffee
consumeService 'vim-mode-plus', 'provideVimModePlus', (service) ->
  {Base, getEditorState, observeVimStates} = service

  Delete = Base.getClass('Delete')
  class DeleteWithBackholeRegister extends Delete
    @commandPrefix: 'vim-mode-plus-user'
    @registerCommand()
    execute: ->
      @vimState.register.name = "_"
      super
  • 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'
Clone this wiki locally