Map :w to Escape in insert mode and normal mode - vim

In order to save time in Vim, I came up with an idea. To map :w key binding to Esc in both normal mode and insert mode. However it only works in insert mode whereas in normal mode things are getting messy when I open a new file. This is what I added in .vimrc:
:inoremap <Esc> <Esc>:w<CR>
:nnoremap <Esc> :w<CR>
As I said the first command alone, works fine. But adding the second command, keys are messed up ESPECIALLY when I open a new file. For instance, although I have explicitly added in .vimrc:
map <up> <nop>
map <down> <nop>
map <left> <nop>
map <right> <nop>
by adding the second command for the normal mode, pressing up down left or right keys cause to enter in insert mode and add A B C D.
Could you help me to achieve my idea?

Information on Vim FAQ 10.9 may be useful:
10.9. When I use my arrow keys, Vim changes modes, inserts weird characters
in my document but doesn't move the cursor properly. What's going on?
There are a couple of things that could be going on: either you are using
Vim over a slow connection or Vim doesn't understand the key sequence that
your keyboard is generating.
If you are working over a slow connection (such as a 2400 bps modem), you
can try to set the 'timeout' or 'ttimeout' option. These options, combined
with the 'timeoutlen' and 'ttimeoutlen' options, may fix the problem.
The preceding procedure will not work correctly if your terminal sends key
codes that Vim does not understand. In this situation, your best option is
to map your key sequence to a matching cursor movement command and save
these mappings in a file. You can then ":source" the file whenever you work
from that terminal.
For more information, read
|'timeout'|
|'ttimeout'|
|'timeoutlen'|
|'ttimeoutlen'|
|:map|
|vt100-cursor-keys|
From :h vt100-cursor-keys:
Other terminals (e.g., vt100 and xterm) have cursor keys that send <Esc>OA,
<Esc>OB, etc. ...
So probably your nnoremap is causing the Esc on the arrow's key sequence to save the file, and the remaining characters are being interpreted alone, so the A is entering insert mode.
You could consider using option 'autowriteall', or using a different mapping to save your file; these are defined in $VIMRUNTIME\mswin.vim:
" Use CTRL-S for saving, also in Insert mode
noremap <C-S> :update<CR>
vnoremap <C-S> <C-C>:update<CR>
inoremap <C-S> <C-O>:update<CR>
The :update command is similar to :w, but only writes only if the file has been modified.

Also, you can use
autocmd InsertLeave * write

Related

How to exit vim after change command on movement

Let's say I change a word with cw. That leaves me in insert mode.
I find it counter intuitive that if I move to a different line, I'm still in insert mode.
I would like to exit insert mode without pressing ESC, for example when I move to different line with arrow keys.
How could I do this?
You can remap the arrow keys to automatically leave insert mode:
inoremap <Up> <Esc><Up>
inoremap <Right> <Esc><Right>
inoremap <Down> <Esc><Down>
inoremap <Left> <Esc><Left>
You may also want to remap <PageDown> and <PageUp>, <ScrollWheelDown>, and <ScrollWheelDown> if you use those.
One downside of this is that it may not work well with some plugins. That is, the plugin will work fine, but it may move the cursor without leaving insert mode as you expect it to. Plus, if you get used to this you may find using a Vim without these mappings (on a server, or someone else's computer) to be frustrating.

Use <Esc> key to save file with one key press in Insert mode or Normal mode

I try to map my <Esc> key to save file with one key press only.
In Normal Mode, it works so far.
map <Esc> :w <CR>
But I have trouble to map it in Insert mode,
I tried the following command, but it does't work
map <Esc> <Esc>[ :w <CR>
By the way, I only want One Key Press only.
Please give me some suggestions, or if you know any good key to save file with One press in Vim
Note that mapping <Esc>, especially in insert mode, is not recommended. Most special keys (like cursor and function keys) are sent as Escape sequences by the terminal. An alternative would be hooking into the InsertLeave event:
:autocmd InsertLeave * silent! update
:update is better suited than :write, because it only actually saves when there are unpersisted updates. :silent! suppresses errors when the buffer hasn't been named, etc.
You keep emphasizing One press as if it was the most important part of your problem but the important part is Insert mode.
:map is a recursive mapping command for normal, visual and operator-pending modes.
You are supposed to use :imap — or its non-recursive friend :inoremap — for insert mode:
:inoremap <Esc> <Esc>:w<CR>
For what it's worth, I recommend Ingo's solution.
augroup AUTOSAVE
au!
autocmd InsertLeave,TextChanged,FocusLost * silent! update
augroup END
To autosave on InsertLeave, TextChanged and FocusLost events

Adding to mapping rather than completely remapping

I'm working on a plugin to allow bracket completion (I know it's available, it's more of a learning exercise). To properly implement it, I need to add to the backspace mapping. However, as it's an important key, I'd rather keep the existing functionality and just add to it rather than reimplementing the functionality. The steps would basically be when in insert mode and press backspace, execute the original backspace key, then check for some conditions and maybe remove more characters.
I've tried something like imap <backspace> <backspace><call_func_here>, but that doesn't seem to work. Again, I know I could remap backspace to just the function and try to recreate the backspace functionality, but I'd prefer to not do that.
Is this possible in vim?
I think what you are trying to do is the following:
inoremap <silent> <BS> <BS><C-o>:call MyFunction()<CR>
inoremap allows to create a non recurrent mapping in insert mode (it is often a good idea to use nore in your mappings). :h :inoremap
<silent> precise that the mapping will not be echoed on the command line (You will not see :call MyFunction() in the command line) :h :map-silent
<BS> is the reference to the backspace key that you want to remap.
The second <BS> is here to issue a backspace in insert mode
<C-o> switches to normal mode for only a command. :h i_CTRL-O
:call MyFunction() is the call to your function the way you would do it in normal mode.
<CR> correspond to the Enter key which validate the call to your function.

Assigning save (:w<cr>) to <leader>w in vim

I want to be able to save a file in vim while in the insert mode. I thought of using the following shortcut:
inoremap <leader>w <Esc>:w<cr>
While the shortcut saves the file in the insert mode, it leaves the cursor one spot ahead of where the cursor would be if I physically typed out the keys
Esc :w followed by Enter. This is a problem because when I use the shortcut whenever I am at the end of a line, it takes me to the next line, and I have to then come back to the spot where I initiated the save.
Any help would be appreciated on how I can map <leader>w to the exact actions that occur in Vim when I physically type out the Esc :w followed by Enter key sequence.
I should add that if I instead use the following key-mapping, things work exactly as I want:
inoremap <C-s> <esc>:w<CR>
However, I would like to avoid pressing CTRL and s at the same time. It is possible there is some problem with the <leader>, but I cannot figure out what it is (I am using , as my leader key).
Though one could discuss the suitability of your insert-mode mapping, the root cause of your problem is a trailing space in the mapping definition; i.e. Vim reads this as follows:
inoremap <leader>w <Esc>:w<cr><Space>
You'll even see this in the :imap <Leader>w output! <Space> in normal mode advances the cursor one to the right (like l); that explains the unexpected move.
Try this instead:
inoremap <silent> <leader>w <C-o>:w<CR>
The idea is Ctrl-o can be used to run commands directly from insert mode. See :help i_CTRL-O for details.
Why not simply doing
inoremap <leader>w <Esc>h:w<cr>
(not the additional h for going back one character)?

Vim: overloaded mapping for multiple modes

I use mappings to normal mode commands that I'd also like to work in insert mode. This can be done by adding <C-o> to insert mode mapping:
nmap <C-Up> 10<Up>
imap <C-Up> <C-o>10<Up>
But this means repeating each mapping twice.
To avoid repetition, I've tried to "overload" some other key, then use it for mode-specific part:
" F12 selects prefix suitable for current mode
nmap <F12> <Nop>
imap <F12> <C-o>
" single mapping relying on "overloaded" F12
map <C-Up> <F12>10<Up>
For some reason, it doesn't work. F2 in insert mode just inserts <F2> as text.
Any idea what's wrong and how to fix it?
Bonus points if you can extend the solution to visual mode.
As ZyX has already pointed out, there is no single :map command for all modes, because it mostly doesn't make sense. If you really want to define a mapping for all modes, use both :map and :map!; see :help map-modes.
As you typically define mappings only once in your .vimrc, I would not worry too much about the little duplication, but if you do, you can use a wrapper function to avoid this:
function! MapBoth(keys, rhs)
execute 'nmap' a:keys a:rhs
execute 'imap' a:keys '<C-o>' . a:rhs
endfunction
call MapBoth('<C-Up>', '10<Up>')
Original
nnoremap <F2> :w<CR>
inoremap <F2> <Esc>:w<CR>a
map sometimes does not set it for all modes. I don't know the exact reason, so to be sure I like to explicitly set all mapping in my configuration file. I suggest that you do the same as there are cases where you can get something unexpected due to different modes. That's why it is important to consider every remapping that you do for each particular mode with care.
In addition, favor *noremap command instead of just *map everywhere you can as recursive mapping is a known source of errors, especially for beginners.
Lastly, I don't know what are you trying to achieve by binding writing of a file in visual mode. Are you aiming for partial buffer writing (it's when you selected something in visual mode, then hit this file-writing shortcut and only selected text is written)? Or do you want the whole file to be written when you are in visual mode, regardless of whether you selected anything or not when you hit the file-writing shortcut? Provide more information on that. Personally, in either case it is weird mapping for visual mode, as it is really not indented for that. It's rather better to keep such stuff in normal mode.
Update
As others have already given exhaustive answers on your question, I just thought that it would be helpful if add my 2 cents, but in slightly different direction. By looking on what you are trying to do, namely mapping navigation features involving arrow keys in insert mode, I can infer that you are very new to Vim. As you probably already know, the philosophy behind Vim is that you should never ever touch mouse during your work inside Vim - call it a kind of golden rule.
What I want to point out now, is what I call a silver rule, and it basically looks like this:
noremap <Up> <Nop>
noremap <Down> <Nop>
noremap <Left> <Nop>
noremap <Right> <Nop>
inoremap <Up> <Nop>
inoremap <Down> <Nop>
inoremap <Left> <Nop>
inoremap <Right> <Nop>
In other words, prevent yourself from using arrow keys (everywhere except command-line mode). Your fingers should always be only in the region of character keys. Vim is all about modes. Insert mode is not for navigation - it is intended for bursts of typing. When you work with code or just text (doesn't matter) you spend most of your time in normal mode - navigating - looking through the file, seeking where to land next in order to edit something, add something, i.e. to do your next input burst for which you switch to insert mode, and when you are finished you switch back to normal mode to look for some more meat - like a predator. :)
So what is it all about? I just want to head you to the right direction right from the beginning. This way you can become intermediate Vim user very quickly - just a few days. In order to get better feeling of all the aforementioned I suggest that you should definitely watch Vim Novice Video Tutorials by Derek Wyatt where he talks about all that stuff in more detail and shows it in action in the screencasts. There are also Intermediate and Advanced tutorials by him which you might also look when you are comfortable with the basics.
I wish you happy vimming! :)
There are no commands to define mappings for all modes: :map maps for normal, operator-pending and visual modes (really visual and select at once) which is clearly stated in documentation. It does not make any sense to have same mapping for all modes, though unlike movement ones saving may be done in all modes with exactly the same rhs:
function s:Save()
update
return ''
endfunction
noremap <expr> <F2> <SID>Save()
noremap! <expr> <F2> <SID>Save()
. noremap! is another multi-mode mapping command, it covers insert and command mode now. You can’t move the cursor from <SID>Save() function (textlock) thus this method is not applicable for cursor movement commands, but you can use variables in order not to repeat the same thing twice:
let s:tendownlhs='10j'
execute ' noremap <C-Down> '.s:tendownlhs
execute 'inoremap <C-Down> <C-o>'.s:tendownlhs
. Now without command mode as this is tricky and likely useless.
If it is okay for the mapping to end up in normal mode, you could combine a for loop with <C-\><C-n> mappings. <C-\><C-n> switches from any mode to normal mode.
For example, this allows switching panes with Alt-{h,j,k,l} from any mode:
for map_command in ['noremap', 'noremap!', 'tnoremap']
execute map_command . ' <silent> <M-h> <C-\><C-n><C-w>h'
execute map_command . ' <silent> <M-j> <C-\><C-n><C-w>j'
execute map_command . ' <silent> <M-k> <C-\><C-n><C-w>k'
execute map_command . ' <silent> <M-l> <C-\><C-n><C-w>l'
endfor
noremap maps in Normal, Visual, and Operator-pending mode
noremap! maps in Insert and Command mode
tnoremap maps in Neovim's Terminal mode

Resources