Execute <Plug> commands in vim - vim

I've recently found a vim plugin using something called <Plug>. For example there is a command <Plug>abc_def which I would like to execute.
I've tried everything like :<Plug>abc_def and similar. Nothing worked. And :help <Plug> gave no information.
However, I've been able to execute it by creating a mapping :map x <Plug>(unite_redraw). Then I can execute it by pressing x.
Now, is there any way to execute :<Plug>abc_def without creating a dummy mapping just to run it? The actual plugin I use is Unite.

<Plug> mappings are meant to be mapped and called via the map. A <Plug> map is a device to expose a clean interface of plugin actions to the user.
Example: Instead of mapping some key to some plugin function in the plugin's hard code, such as "map zz to the action 'center cursor aesthetically'":
nnoremap <expr> zz 'zz'.float2nr(winheight(0)*0.1).'<C-E>'
it is better to expose only a named <Plug> mapping from the plugin:
nnoremap <expr> <Plug>NiceCenterCursor 'zz'.float2nr(winheight(0)*0.1).'<C-E>'
that the user can then remap in their config, without having to copy and paste the "action":
nmap zz <Plug>NiceCenterCursor
This is then easy to override, reuse, plug into by the user.
<Plug> mappings are active only in the modes they have been defined for. To execute a <Plug> mapping that is defined for normal mode, you can do as with any normal command: use :normal (without the exclamation mark).
:execute "normal \<Plug>NiceCenterCursor"
Since <Plug> actually represents a special magic key, we need to use :normal together with :execute and escape the <Plug>.
The <Plug> mechanism is described in depth at :h 41.11. See also this article about this topic by a Vim master.

Related

What do all the markings in vim `:imap` outputs mean?

e.g. if I type :im it outputs a long list of messages of the insert mode mappings.
i <Plug>(fzf-maps-i) * <C-O>:call fzf#vim#maps('i', 0)<CR>
The i is for insert mode.
:help <Plug> says that you use it for "internal mappings which is not to be matched with any key sequence". What is this good for? If you manage to press an unpressable key combination it will open the :Maps terminal buffer? Aside from this specific situation, why would you want to bind an unpressable binding?
Next, we have the *. What does it refer to? :helpgrep star or :helpgrep * fail me.
Next we have this line:
i <Plug>(fzf-complete-file-ag) * fzf#vim#complete#path('ag -l -g ""')
Why does the first line above use * and then still use <C-O>:call ... <CR> while this one just mentions the function name?
<Plug> [...] What is this good for? If you manage to press an unpressable key combination it will open the :Maps terminal buffer?
It is an unpressable key combination. It doesn't mean it cannot be generated. If you look at the docs of fzf.vim, you will see an example of a related mapping that user can insert into their .vimrc:
nmap <leader><tab> <plug>(fzf-maps-n)
If the user then presses LeaderTab, it will generate <plug>(fzf-maps-n). This mapping is not noremap, so it will trigger the map <plug>(fzf-maps-n) mapping defined by the plugin. This way the plugin exposes a mappable key sequence, but without any side-effects for the users where they might accidentally trigger it; though they can still map to it if they wish to.
Next, we have the *
:help map-listing will tell you * means it is not remappable (i.e. created by inoremap instead of imap).
Why does the first line above use * and then still use <C-O>:call ... <CR> while this one just mentions the function name?
It is not visible from the listing, but the command that created it was:
inoremap <expr> <plug>(fzf-complete-file-ag) fzf#vim#complete#path('ag -l -g ""')
Note the <expr> modifier. :help :map-<expr>

Vim simple mapping

I started using Vim recently, just installed NERDTree (a plugin to navigate files).
The command to access that plugin is :NERDTree so I though it's a good idea to start learning mappings by assigning one to that command.
So I added to my .vimrc file the following line: map :nt :NERDTree - but when I type :nt in a vim file (even after restarting) I receive the following error message: not an editor command: nt
I also tried to add the mapping directly while editing a file by typing :map :nt :NERDTree but it returned the same error when I tried to use the command.
I checked that answer:What is the difference between the remap, noremap, nnoremap and vnoremap mapping commands in vim?, so it seems to me that :map (opposed to noremap etc.) is the good command for that.
The plugin works fine when typing the original command.
What am I doing wrong? (sorry for the noob question)
:NERDTree is a command, not a mapping, so there's no reason for creating a recursive mapping, here.
:map is too overreaching. You should use :<mode>map (for recursive mappings) or :<mode>noremap (for nn-recursive mappings).
You are missing a <CR> at the end of your mapping to tell Vim to actually execute the :NERDTree command.
In this specific case, the right mapping would be:
nnoremap :tn :NERDTree<CR>
But mapping something to :<anything> is not a good idea because it will introduce a timeout whenever you try to execute an Ex command. This means that you need to find another combo. Why not <Space>n?
nnoremap <Space>n :NERDTree<CR>
With the mapping that you have, it will be require multiple keystroke. Will it be okay for you to use a single key like F2?
nnoremap <F2> :NERDTreeToggle<CR>
This will toggle open/close NERDTree upon pressing F2 and save you some key stroke.
Here
you can figure out, how vim's mapping work and look like ;). Don't forget to source your new .vimrc before using.

Vim - make comment shortcut

I often write LaTeX using Vim. And I have been taught that one can comment a number of selected lines (in visual mode) using the following command:
:'<,'>s!^!%!
And similarly, one may uncomment lines in visual mode by using this command:
:'<,'>s!^%!!
Here, '%' denotes the commenting symbol for LaTeX. But I would very much like to make a shortcut to make it easier for myself to use these commands. For instance a keybinding or some sort of function so that I do not have to remember this syntax. How does one do that?
First, there are several commenter plugins, that do this very well, and those are generic (and often extensible) so that they work for any filetype, not just Latex:
NERD Commenter plugin
tComment plugin
commentary.vim plugin
are just a few popular plugins.
Custom mapping
That said, it's a good learning experience to develop a mapping on your own. Here's how:
First, mappings are just instructions that when certain key(s) are pressed, Vim translates them into other keys (on the right-hand side). Your mapping is for visual mode, so the command is :vmap. What do you normally do? You select the lines to be commented, and press :; Vim automatically inserts the '<,'> for you. You write the :s command, and conclude by pressing Enter.
Translation:
vmap <Leader>c :s!^!%!<CR>
The <Leader> is a configurable, unused key, defaulting to backslash. So, your mapping is invoked by pressing \ and then C. Put that into your ~/.vimrc to make it permanent, and you're done. Wait! There's more.
Advanced mappings
First, you should use :vnoremap; it makes the mapping immune to remapping and recursion.
Second, that mapping is global, but it applies only to the Latex filetype. So, it should apply only to Latex buffers; there's the <buffer> modifier for that.
You can define that for certain filetypes by prepending :autocmd Filetype tex ..., and put that into your ~/.vimrc. But that gets unwieldy as you add mappings and other settings for various filetypes. Better put the commands into ~/.vim/ftplugin/tex_mappings.vim. (This requires that you have :filetype plugin on.)
vnoremap <buffer> <Leader>c :s!^!%!<CR>
Technically, you should use <LocalLeader> instead of <Leader>. They default to the same key, but the distinction allows to use a different prefix key for buffer-local mappings (only if you need / like).
Let's add the alternative mapping for uncommenting, triggered via \ and Shift + C:
vnoremap <buffer> <LocalLeader>c :s!^!%!<CR>
vnoremap <buffer> <LocalLeader>C :s!^%!!<CR>
Note that you could combine both into one, using :help sub-replace-expression with a conditional expression. If anything here is over your head, don't worry. You should be using one of the mentioned plugins, anyway :-)

VIM Disable insert mappings of plugins

A plugin adds to my insert mappings a mapping for <leader>is. I have some ideas which one it can be. But it does not matter I don't want to change anything in foreign plugins. So I want to disable this mapping. I tried this:
imap <leader>is <nop>
I did not help.
What is your suggestions?
BTW, I want to ask how disable in vimrc all insert mapping of plugins?
To remove an insert mode mapping, use the :iunmap command:
:iunmap <Leader>is
I don't know whether it is possible to do "bulk unmapping", but at least you can list all active insert mode mappings with
:imap
or, even better, with
:verbose imap
which will also tell you where the mapping has been defined in the first place.
Edit: To clarify, the unmapping needs to be done after the plugin has been loaded. To do so, create a file with the following contents in ~/.vim/after/plugin/ (see #ZyX's answer):
" myafter.vim: will be executed after plugins have been loaded
iunmap <Leader>is
Your command if inserted in the vimrc is executed before plugin defines the intrusive mapping and this is why it has no effect. To make it have effect you should make it run after that plugin which is normally achieved either by putting it into ~/.vim/after/plugin/disable_mappings.vim (any name instead of disable_mappings works). Second is using VimEnter event:
augroup DisableMappings
autocmd! VimEnter * :inoremap <leader>ic <Nop>
augroup END
. To disable all mappings see :h 'paste' and :h 'pastetoggle', also :h :imapclear (though the latter will remove mappings instead of temporary disabling them).
Of course, you may also use iunmap just where I suggested to use inoremap … <Nop>. How did I came to forget this command?

What is the best way to add a custom key mapping in vim/vi? (Does there exist a unbound keyspace for customization?)

I know you can add custom keymappings to vim with imap in the .vimrc file. My question is, if one is to create additional custom operators, motions, commands and map them to keys, what is the best way to add them in so they don't conflict with existing bindings?
An analogy, in emacs, a lot of custom key commands are added via the C-c sequence. To be more technical, are there unbound keys in vim that allow for user customization? In other words, is there a free keyspace available to users?
:imapEnter will show a list of your insert mode mappings.
My question is, if one is to create additional custom operators,
motions, commands and map them to keys, what is the best way to add
them in so they don't conflict with existing bindings?
In my opinion the best way is creating custom command, they start with uppercase, native ones with lowercase.
Additionally, you can use a <leader> I use , some use \.
e.g. :let mapleader = ","
then, you can use the leader to combine it with other keys, like ,p to call a command, native or custom, see below:
:map <leader>p :MyCustomCommand<CR>
A custom motion example. Delete the third word after the cursor.
nnoremap <leader>x :normal 2wdw<CR>
Several commands can be used to create new, remove and list the mappings, here is a list of working modes, from :help map-overview
Normal Visual+Select Operator-pending ~
:map :noremap :unmap :mapclear yes yes yes
:nmap :nnoremap :nunmap :nmapclear yes - -
:vmap :vnoremap :vunmap :vmapclear - yes -
:omap :onoremap :ounmap :omapclear - - yes
further info
:help map
Here's an example function, converted to a custom command
function! MoveLastLines(f)
exe '$-9,$w ' . a:f "write last ten lines to the passed filename
$-9,$d "delete last ten lines
endfunction
command! -nargs=1 -range MoveTo :call MoveLastLines(<f-args>)
Now, both lines below are equivalent
:call MoveLastLines('newFile.txt')
:MoveTo newFile.txt

Resources