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

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)?

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:
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)
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)

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.

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

Related

Figuring out why keybinding is not working in vim

I installed SpaceVim to test it out and ; (semicolon) is not working. :nmap ; says "No mapping found". The thing is I could not find where it is unmapped in the source. Are there different ways to re/un-map a key in vim and how should I go about finding those in general?
There seems to be some confusion here about the difference between the « standard » vim functionality and the effects of a mapping.
Note: One of the reasons I prefer a customized regular vim is that it forced me to learn real vim and its philosophy, then to build tools on top of that. This may be the purist in me, but distros like SpaceVim make it remarkably hard to see what’s going on under the hood when you need them to do something different, whereas vim is ready-made for that. I write this because I suspect those who start with SpaceVim do not read :help and therefore lack a complete grasp of the fundamentals.
Standard vim keys are not mappings. n to jump to next search match, J to join, q to record a macro, ; to repeat the last fFtT—all are implemented in the source. Changing their default behavior would require an edit and recompile. This is why :normal! ; works no matter what—it ignores mappings and uses the source definition.
So, to answer your question, :map ; says there is no mapping because there is no mapping.
Note: I assume SpaceVim does not map ; because I could not find documentation that it did.
Of course, one can always create mappings shadowing this behavior, but it’s considered an anti-pattern to do so (esp. without at least having another sequence to do the old behavior). The reasoning goes that the original is actually considered useful, so why override it?
Note: from my glance at SpaceVim’s keybindings, SV does this a lot. They remapped q, which created macros, requiring me to type 2 extra characters to access one of my favorite—and one of the most awesome—features!

How to can I make a title shortcut

I use vim and I want that in every file I will have a title like
**year=
**author=
**
**
..
I want to map a key for past it in the head of a file.
Their is any plugin for this?
Thanks.
Well, you don't need a plugin just to map a key to insert some text at the beginning of the current buffer:
:nno \h ggO**year=<cr>**author=<cr>**<cr>**<esc>
Just change \h to your
preferred key sequence.
snippets are like the built-in :abbreviate on steroids, usually with parameter insertions, mirroring, and multiple stops inside them. One of the first, very famous (and still widely used) Vim plugins is snipMate (inspired by the TextMate editor); unfortunately, it's not maintained any more; though there is a fork. A modern alternative (that requires Python though) is UltiSnips. There are more, see this list on the Vim Tips Wiki.
There are three things to evaluate: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.

Calling a function upon set command

I'm swapping some mappings on my keyboard to make it easier on my wrist, but I wouldn't want others to be surprised if they open vim on a computer I had been working on.
So I put these mappings inside a function in my .vimrc so I can selectively enable the mappings.
My question is, how can I tell vim (in the .vimrc file) to call a function if I :set a variable?
Something like :set wrist and it would call SwapKeysForWrist.
Note: I know I can give the function a simpler name and call it, for example :call Shahbaz(), but that requires me to use shift three times (besides :) which is what I'm trying to avoid. In fact, the function swaps the digits with their alternative keys (since I use those symbols much more often than actual numbers during programming), and typing parentheses (added that I'd be holding shift) does strain my wrist.
You cannot define your own :set names, you can only use mappings or custom commands.
I would suggest using a custom :Wrist command; it's short to type and should be easy for you to remember. If you want to get around the uppercase W, you need to use a :cabbrev or the cmdalias plugin.

how to add vim keymap

While programming I am regulary using the following two lines:
sprintf(buff,"%s", __func__);
putrsUART(buff);
Is it possible to set any keyboard shortcut to insert these two lines?
E.g. when I type \sp in command mode, these functions get added at the cursor position in my file. Is this possible? And if so, how do I map my keys?
Thanks in Advance.
You can use abbreviations, which are designed for this.
:abbr spb sprintf(buff,"%s", __func__);
:abbr uart putrsUART(buff);
Use :help abbr for the gory details. Note that you need to type another character after the abbreviated form for vim to recognize them. This comes naturally for these as you will type ENTER as the next character. It is also possible to enter more than one line with abbreviations. Simply use <CR> where you want a new line.
Here's an easy mapping for normal mode that lets you hit \sp (unless you've remapped leader, in which case use that instead of \) in order to insert the sprintf statement.
map <Leader>sp isprintf(buff,"%s", __func__);<Esc>
That being said I think abbreviations are the way to go here
As already mentioned, abbreviations (which I would limit to insert mode (:iabbr), because you probably won't need them in the command-line) are best for simple expansions; you can also define them only for certain filetypes only (via :iabbr <buffer> ...).
Your __func__ looks like a template parameter that you need to adapt each time. You cannot do this via abbreviations, but there are various plugins (many inspired from functionality in the TextMate editor) that offer template insertion with parameter expansion and several advanced features. Check out one of snipMate, xptemplate, or UltiSnips.
Try snip-Mate for inserting regularly used codesnippets. http://www.vim.org/scripts/script.php?script_id=2540
Wrong answer, Sorry:
Try this in your vimrc:
map <c-w> :sprintf(buff,"%s",func)<cr>
This means mapping to Ctrl-W.

How to create short snippets in Vim?

I have recently started using Vim as my text editor and am currently working on my own customizations.
I suppose keyboard mappings can do pretty much anything, but for the time being I'm using them as a sort of snippets facility almost exclusively.
So, for example, if I type def{TAB} (:imap def{TAB} def ():<ESC>3ha), it expands to:
def |(): # '|' represents the caret
This works as expected, but I find it annoying when Vim waits for a full command while I'm typing a word containing "def" and am not interested in expanding it.
Is there a way to avoid this or use this function more effectively to this end?
Is any other Vim feature better suited for this?
After taking a quick look at SnippetsEmu, it looks like it's the best option and much easier to customize than I first thought.
To continue with the previous example:
:Snippet def <{}>():
Once defined, you can expand your snippet by typing def{TAB}.
Snipmate - like texmate :)
http://www.vim.org/scripts/script.php?script_id=2540
video:
http://vimeo.com/3535418
snippet def
""" ${1:docstring} """
def ${2:name}:
return ${3:value}
As another suggestion (although slightly different) using vim's built in functionality:
:iabbrev def def(): #<LEFT><LEFT><LEFT><LEFT><LEFT>
Now whenever you type def followed by a space or other non-word character, it will expand to the same as what you've given as the output of SnippetsEmu (the space comes from the space you entered to trigger the completion).
This approach doesn't suffer the "lag" issue you encountered using :inoremap, and is built-into vim. For more information on this feature, look at :help abbrev.
You may be concerned that being triggered by space not tab it will trigger unnecessarily, but in general vim is pretty smart about when to trigger it. The issue can be additionally mitigated by enabling the abbreviation only for certain file-types (eg, python):
au filetype python :iabbrev ... etc
Snip[ets] (Manager|Emu|Mate|.vim) is of course also a perfect solution, but it's nice to be aware of the alternatives (especially when they are built in).
If SnippetsEmu is too heavy or ambitious for what you need (it was for me), I wrote a plugin that manages snippets based on filetype. It even has tab completion when picking the snippet! :)
Get it here: snippets.vim
I just installed UltiSnips. There’s a good article that explains why you might choose UltiSnips: Why UltiSnips?
I haven’t used any of the other snippet plugins; I decided to take the plunge with one that seemed full-featured and would be able to accommodate me as I gain more Vim skills and want to do more sophisticated things.
SnippetsEmu is a useful snippets plugin.
As noted by MDCore, SnippetsEmu is a popular Vim script that does just that and more. If you need only expanding (without moving back the caret), you can use the standard :ab[breviate] command.
:ab[breviate] [<expr>] {lhs} {rhs}
add abbreviation for {lhs} to {rhs}. If {lhs} already
existed it is replaced with the new {rhs}. {rhs} may
contain spaces.
See |:map-<expr>| for the optional <expr> argument.

Resources