How do I map a keybinding to a command? - vim

I am currently trying out Clion from intellij but I am not a big fan of keybindings but it offers vim support. For example Clion has a keybinding ctrl+shift+n to open a fuzzy search.
Is it possible to bind a keybinding to a custom command in vim?
Something like
command :fuzzy <C-N>

IdeaVim is not Vim. There is no reason whatsoever to expect anything to work in IdeaVim like in Vim or vice-versa so… do you want that mapping to work in Vim or in IdeaVim? If your question is about Vim, your CLion explanation and tags are totally irrelevant.
In Vim, you would put this line in ~/.vimrc:
nnoremap <key> :Command<CR>
See :help key-notation for <key> and note that Vim doesn't make a difference between <C-N> and <C-n>.
Now, Vim has no "fuzzy" capability on its own, so you will need a third party plugin for that.

I don't see how you'll enjoy Vim without a preference for (fast and efficient) keybindings, but this is certainly possible, if somewhat odd. Usually, one defines keybindings for custom commands (so the other way around), in order to speed up frequently used commands.
To do the opposite, you have to consider the modes: (Custom) commands take Ex commands, whereas keybindings usually are in normal mode. Fortunately, there's the built-in :normal command to bridge between the two of them. And to use the special keycodes (like <C-N>), you need :execute:
:command FuzzySearch execute "normal \<C-N>"
Note that this probably only works in Vim itself, not in emulations (like in Eclipse or IntelliJ IDEA), as those typically only offer a subset of the full Vim functionality.

Related

Can't map function keys with shift in Vim [duplicate]

I am trying to customize the behaviour of Enter key in Normal mode in Vim.
Here is my .vimrc:
nmap <CR> o<Esc>
nmap <S-CR> i<CR><Esc>
I am trying to make Enter simply append a newline after the current line when pressed. However, when the Shift-Enter combination is pressed, I want to break the current line at the cursor.
The latter does not work. Whenever I press Shift-Enter it just appends a line without breaking it at the cursor.
I managed to correct my terminal key-code for Shift+Enter
by sending the key-code Vim apparently expects. Depending on your terminal,
(Adding Ctrl+Enter as a bonus!)
iTerm2
For a single Profile open Preferences → Profiles → Keys → [+] (Add)
For all profiles open Preferences →
Keys → [+] (Add)
Keyboard shortcut: (Hit Shift+Enter)
Action: Send Escape Sequence
Esc+ [13;2u
Repeat for Ctrl+Enter, with sequence: [13;5u
urxvt, append to your .Xresources file:
URxvt.keysym.S-Return: \033[13;2u
URxvt.keysym.C-Return: \033[13;5u
Alacritty, under key_bindings, add following to your ~/.config/alacritty/alacritty.yml:
- { key: Return, mods: Shift, chars: "\x1b[13;2u" }
- { key: Return, mods: Control, chars: "\x1b[13;5u" }
Kitty, in ~/.config/kitty/kitty.conf:
map shift+enter send_text all \x1b[13;2u
map ctrl+enter send_text all \x1b[13;5u
Due to the way that the keyboard input is handled internally, this unfortunately isn't generally possible today in the terminal version of Vim (<S-CR> should work in GVIM on all platforms, and in the Windows console Vim). This is a known pain point, and the subject of various discussions on vim_dev and the #vim IRC channel.
Some people (foremost Paul LeoNerd Evans) want to fix that (even for console Vim in terminals that support this), and have floated various proposals, cp. http://groups.google.com/group/vim_dev/browse_thread/thread/626e83fa4588b32a/bfbcb22f37a8a1f8
But as of today, no patches or volunteers have yet come forward, though many have expressed a desire to have this in a future Vim 8 major release.
Note on mapping <CR>:
If you map <CR> in normal mode, it'll interfere with selection of history items in the command-line window and with jumping to error under cursor in quickfix/location list windows! (Unless you add the following:)
:autocmd CmdwinEnter * nnoremap <CR> <CR>
:autocmd BufReadPost quickfix nnoremap <CR> <CR>
Note on :nmap:
You should use :noremap; it makes the mapping immune to remapping and recursion.
I also wanted to map <S-CR> and found that I couldn't get it to work in CLI mode until I added a second mapping using Ctrl+V then <Shift+Enter> for the mapped keystroke. The <S-CR> mapping is still needed for GVIm to work as expected, however. This would render the your .vimrc snippet as follows:
nnoremap <CR> o<Esc>
nnoremap <S-CR> i<CR><Esc> " Needed for GVIm
nnoremap ^[0M i<CR><Esc> " Needed for CLI VIm (Note: ^[0M was created with Ctrl+V Shift+Enter, don't type it directly)
I tested this on Ubuntu 12.04. Happy Vimming!
You can't map <S-CR> in CLI Vim, no matter how hard you try, because Vim can't distinguish <S-CR> from <CR>.
You must find another mapping or stick with GVim/MacVim.
edit
Some terminal emulators, like iTerm.app or Terminal.app on Mac OS X, allow you to set up shortcuts to send specific characters sequences to the shell. If you have that possibility it may be worth a try but you'll quickly get used to a platform-specific gyzmo that can't be ported so, well… I don't really recommend it.
Ingo Karkat and romainl are 100% correct. However what you are asking is common so I want to give you some options.
I personally recommend using Tim Pope's Unimpaired plugin. It provides many mappings but the ones you will looking for are [<space> and ]<space> which create blank lines above and below the current line respectively. Unimpaired also provides nice mappings for moving through the quickfix list, buffer list, option toggling, and many others. See :h unimpaired for more.
If you do not want to use unimpaired plugin but like the mappings below are some quick mappings to put in your ~/.vimrc file:
nnoremap <silent> [<space> :<c-u>put!=repeat([''],v:count)<bar>']+1<cr>
nnoremap <silent> ]<space> :<c-u>put =repeat([''],v:count)<bar>'[-1<cr>

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

How do I prevent snipmate from remapping <S-Tab>?

In my after.vim config I have line:
inoremap <S-Tab> <C-d>
I would like this binding to work. However, after starting VIM I type the first line and get the following output:
:verbose map <S-Tab>
s <S-Tab> * <Esc>i<Right><C-R>=BackwardsSnippet()<CR>
Last set from ~/dotvim/bundle/snipmate.vim/after/plugin/snipMate.vim
So snipmate is overwriting the mapping. I understand I could change it within the /bundle/snipmate.vim/after/plugin/snipMate.vim file, but that seems really ugly because I've got /bundle in my .gitignore, which seems to be standard practice.
Any ideas on how to override this, or prevent snipmate from binding to <S-Tab> ?
To remap the command executed by <S-Tab> to <C-d> add the following line to your .vimrc
imap <C-d> <Plug>snipMateBack
The snipmate documentation states you should remap <Plug>snipMateBack in your ~/.vimrc. See :h SnipMate-mappings.
Generally using a vim distribution (which you are) is considered bad for new vimmers because it disrupts learning Vim and puts up barriers when a user decides to customize (as you see here). Personally I would suggest you lose the distribution. Go find a nice plugin manager like pathogen and install plugins when you need them. Doing this means you grow your understanding of Vim as you customize it.
If really do want to use a distribution then you should first try submitting an issue to your distributions issue tracker.

how to remap "q!" and "q" in vim

I'm trying to remap q and q!. Here's what I'm trying:
cnoremap q :call TabCloseLeft('q')
cnoremap q! :call TabCloseLeft('q!')
That properly remaps :q but doesn't capture :q!. I've read various help sections, but I'm obviously overlooking something.
I see some problems:
You are using a cnoremap dangerously e.g. /q
You are using trying to override vim's native :quit function
Looks like you are trying to force vim into a tab behavior
cnoremap
Do not use cnoremap to try and create commands, use :command. If you want to override a command then use a clever cabbrev expression or plugin. See vim change :x function to delete buffer instead of save & quit
Native quit
There are many ways for quiting a buffer in vim. Some do slightly different things. As vimmers learn more commands they integrate them into their workflow. e.g. <c-w>c to close a split/window and ZZ to update and quite the current buffer. If you go down this path you will be overriding many command or you will be disregarding useful commands.
Tabs
Learn to use buffers effectively. Using tabs in Vim is great however they are not the only way and will certainly cause you pain down the road. IMHO it is best to curtail these behaviors and encourage better habits.

How to map Shift-Enter

I am trying to customize the behaviour of Enter key in Normal mode in Vim.
Here is my .vimrc:
nmap <CR> o<Esc>
nmap <S-CR> i<CR><Esc>
I am trying to make Enter simply append a newline after the current line when pressed. However, when the Shift-Enter combination is pressed, I want to break the current line at the cursor.
The latter does not work. Whenever I press Shift-Enter it just appends a line without breaking it at the cursor.
I managed to correct my terminal key-code for Shift+Enter
by sending the key-code Vim apparently expects. Depending on your terminal,
(Adding Ctrl+Enter as a bonus!)
iTerm2
For a single Profile open Preferences → Profiles → Keys → [+] (Add)
For all profiles open Preferences →
Keys → [+] (Add)
Keyboard shortcut: (Hit Shift+Enter)
Action: Send Escape Sequence
Esc+ [13;2u
Repeat for Ctrl+Enter, with sequence: [13;5u
urxvt, append to your .Xresources file:
URxvt.keysym.S-Return: \033[13;2u
URxvt.keysym.C-Return: \033[13;5u
Alacritty, under key_bindings, add following to your ~/.config/alacritty/alacritty.yml:
- { key: Return, mods: Shift, chars: "\x1b[13;2u" }
- { key: Return, mods: Control, chars: "\x1b[13;5u" }
Kitty, in ~/.config/kitty/kitty.conf:
map shift+enter send_text all \x1b[13;2u
map ctrl+enter send_text all \x1b[13;5u
Due to the way that the keyboard input is handled internally, this unfortunately isn't generally possible today in the terminal version of Vim (<S-CR> should work in GVIM on all platforms, and in the Windows console Vim). This is a known pain point, and the subject of various discussions on vim_dev and the #vim IRC channel.
Some people (foremost Paul LeoNerd Evans) want to fix that (even for console Vim in terminals that support this), and have floated various proposals, cp. http://groups.google.com/group/vim_dev/browse_thread/thread/626e83fa4588b32a/bfbcb22f37a8a1f8
But as of today, no patches or volunteers have yet come forward, though many have expressed a desire to have this in a future Vim 8 major release.
Note on mapping <CR>:
If you map <CR> in normal mode, it'll interfere with selection of history items in the command-line window and with jumping to error under cursor in quickfix/location list windows! (Unless you add the following:)
:autocmd CmdwinEnter * nnoremap <CR> <CR>
:autocmd BufReadPost quickfix nnoremap <CR> <CR>
Note on :nmap:
You should use :noremap; it makes the mapping immune to remapping and recursion.
I also wanted to map <S-CR> and found that I couldn't get it to work in CLI mode until I added a second mapping using Ctrl+V then <Shift+Enter> for the mapped keystroke. The <S-CR> mapping is still needed for GVIm to work as expected, however. This would render the your .vimrc snippet as follows:
nnoremap <CR> o<Esc>
nnoremap <S-CR> i<CR><Esc> " Needed for GVIm
nnoremap ^[0M i<CR><Esc> " Needed for CLI VIm (Note: ^[0M was created with Ctrl+V Shift+Enter, don't type it directly)
I tested this on Ubuntu 12.04. Happy Vimming!
You can't map <S-CR> in CLI Vim, no matter how hard you try, because Vim can't distinguish <S-CR> from <CR>.
You must find another mapping or stick with GVim/MacVim.
edit
Some terminal emulators, like iTerm.app or Terminal.app on Mac OS X, allow you to set up shortcuts to send specific characters sequences to the shell. If you have that possibility it may be worth a try but you'll quickly get used to a platform-specific gyzmo that can't be ported so, well… I don't really recommend it.
Ingo Karkat and romainl are 100% correct. However what you are asking is common so I want to give you some options.
I personally recommend using Tim Pope's Unimpaired plugin. It provides many mappings but the ones you will looking for are [<space> and ]<space> which create blank lines above and below the current line respectively. Unimpaired also provides nice mappings for moving through the quickfix list, buffer list, option toggling, and many others. See :h unimpaired for more.
If you do not want to use unimpaired plugin but like the mappings below are some quick mappings to put in your ~/.vimrc file:
nnoremap <silent> [<space> :<c-u>put!=repeat([''],v:count)<bar>']+1<cr>
nnoremap <silent> ]<space> :<c-u>put =repeat([''],v:count)<bar>'[-1<cr>

Resources