Skip to content

CreateVimModePlusPlugin

t9md edited this page Oct 9, 2016 · 4 revisions

Overview

If you think your custom operation is useful for many developer.
Let's release your enhancement as vmp plugin package.
It's not so difficult, vim-mode-plus-move-to-symbols is the 1st package released as example of plugin.

Although its not difficult to create vmp plugin, follow one important rule.

If you create your command as separate file, you must require it in consumeVim function. Don't require it before consumeVim is called.
The reason of this is to delay require after vmp's Base class is initialized.
You can get any of vmp class via Base.getClass, but to being able to do that, Base has to be initialized.
Since Atom's package activation order is not deterministic, if you require Base class before vmp call Base.init in activation phase, you can't get anything via Base.getClass.

Following code is example of consumeVim function in vmp plugin package.

  consumeVim: ({Base}) ->
    {state, MoveToNextSymbol, MoveToPreviousSymbol} = require "./move-to-symbols"
    @subscribe MoveToNextSymbol.registerCommand()
    @subscribe MoveToPreviousSymbol.registerCommand()
    state.cachedTags = cachedTags

Note for plugin author

What function of vmp core you can safely depend on in your plugin?

For very basic feature like Base.registerCommand(), Base.getClass() would be not likely to change. But I'm currently actively developing, refactoring vmp, I basically don't care what feature is used by plugin authors. Please understand until I get finished for refactoring work.
At the timing of this writing 2015.1.13, I believe it still take at least for 3 months from now. Yes till April 2015.

For the library such as utils.coffee or selection-wrapper.coffee.
I may change function name without notification(Of course I will not change without reason, and generally put note for issue or commit msg).
Again these library function is indented to be used within vmp core.
Its OK to use from vmp plugin and of course I did too, but If you make your plugin resilient from change of internal vmp, avoid depending too much of core function, instead copy&paste those function directly to your plugin file.

What's is @extend()? Do I need to call in my plugin class?

No you don't have to call it, and should not call it if you want make your plugin's class available for other class defined in different place(in different plugin).

Let's take following MoveDown motion as example.

class MoveDown extends MoveUp
  @extend()
  linewise: true
  amount: +1

  move: (cursor) ->
    moveCursorDown(cursor)

@extend() for above call is Base.extend() class methods, which is used internally to notify Base class the event of inheritance since CoffeeScript don't have inherited hook like Ruby.

Historically lots of work was done within this @extend() methods, but for now it only register class itself to vmp core registries which is where you can get all classes of vmp operations via Base.getClass(klassName) method.

Within vmp core, this registries is used to share operation class across motion, text-object, operator.

e.g. Get text-object AAnyPair from MoveToPair(% command) motion.

As conclusion, you should not call @extend() in your plugin basically, but If you create general purpose class to be used by many of other plugin authors, you should call @extend() to register your class.

[TODO] When plugin register its class via Base.extend(), how other plugin can know the timing of registration? I'll postpone this question until real situation to being KISS.

General purpose class

Here is the list of classes where lots of operation is derived from it. You can see it by inheritance hierarchy in Operations.

  • TextObject.Pair
  • Operator.TransformString
  • Operator.ActivateInsertMode
  • Motion.MoveToPositionByScope: You can derive new scope based motion only by changing scope field.

When you want to write plugin just adding minimum code, refer how above classes are used in vmp core.

Clone this wiki locally