Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the reason to parenthesize <Plug> map names?

Tags:

vim

vim-plugin

Many plugins make their public mapping interface accessible through <Plug> maps. Users can then use these maps as hooks for their own mappings, e.g. :nmap <Leader>fu <Plug>fooPluginUnlinkRootDir.

Recently I have come across some plugins which put their map names in brackets, e.g.

  • <Plug>(textobj-indent-a) in the textobj-indent plugin,
  • <Plug>(LineJugglerBlankUp) in the LineJuggler plugin.

This syntax is not documented anywhere in the help files nor do any of the bundled Vim runtime files use it. Nevertheless, these plugins do their job just fine.

What is the motivation for the brackets? Is there any advantage in using them? Should plugin authors be encouraged to follow this practice (as a best practice)?

like image 449
glts Avatar asked Dec 03 '12 16:12

glts


3 Answers

Thanks ZyX; your answer already covers the fundamentals, so let me just add why I've adopted the <Plug>(PluginNameAndMore) notation. (I think I saw it first in Kana Natsuno's plugins.)

Two reasons:

  1. When wrapping a mapping with other stuff, it's easier to visually parse the individual mapping targets, like here:

    imap <C-x><C-c> <Plug>(CompleteStart)<Plug>(CamelCaseComplete)<SID>(CamelCaseCompleteModifyUndo)<Plug>(CamelCasePostComplete)<Plug>(CompleteoptLongestSelect)

  2. When defining multiple mappings for a plugin, one must be careful that the LHS of one is not contained in another mapping. Otherwise, there will be a delay when the mapping is triggered, as Vim needs to wait for additional keystrokes before the ambiguity can be resolved. The closing parenthesis prevents any such ambiguity.


BAD                 GOOD
<Plug>MyFunc        <Plug>MyFuncNext, <Plug>(MyFunc)
<Plug>MyFuncReverse <Plug>MyFuncPrev, <Plug>(MyFuncReverse)
like image 124
Ingo Karkat Avatar answered Nov 16 '22 13:11

Ingo Karkat


Both of {lhs} and {rhs} in the mappings command are byte sequences which can contain arbitrary data (except for NUL byte) as long as it has natural number of bytes (for {rhs} having zero number of bytes is also allowed). From this point of view (…) practice has no advantages over another one.

Specifically for (textobj-…) there is one minor advantage: you can select the whole {lhs} without <Plug> part with a) motion and have more readable dashes between words. I have no idea though why would one want to do so as the whole {lhs} can be selected with aW (with <Plug> part).

I do not see any reason for the LineJuggler version.

You should better ask authors about this. @IngoKarkat is here, on stackoverflow and will probably read the question soon. I have no idea how to contact Kana Natsuno.

like image 31
ZyX Avatar answered Nov 16 '22 15:11

ZyX


Parens make it clearer (to humans) when there are other keystrokes in a mapping following the <Plug> invocation. For instance I have this mapping:

nmap ]c <Plug>GitGutterNextHunkzv

That makes ]c jump to the next Git hunk and then do zv to open any folds there. But since <Plug> names are arbitrary, the command could have been called GitGutterNextHunkzv. In general there's no way for somebody reading a file using a <Plug> mapping to know if the whole thing is a name or there are other characters following.

If the GitGutter plug-in had used brackets for in the <Plug> name, it would be far clearer to see what's going on:

nmap ]c <Plug>(GitGutterNextHunk)zv
like image 2
Smylers Avatar answered Nov 16 '22 13:11

Smylers