Vim: strange escaping to normal mode behaviour - vim

When I'm escaping from insert mode with either <esc> or jj the cursor moves one character backwards, which, I guess, is the typical behavior for Vim or MacVim GUI.
I tried solving the problem by using inoremap jj <esc>l but the problem there is that when I'm at the end of the line the cursor jumps to the next line, which is even stranger.
I know I can go around this issue by getting used to a instead of i to jump back to insert mode, but first I want to be sure there is no other workaround.
Do you have any suggestions?

Sorry because this is not what you would be expecting, but you probably should get used to it instead of remapping it. In Vim, in normal mode, your cursor is not between characters but on characters. Traditional editors do not have a normal mode, you are always inserting and thus you need to see a cursor between characters.
If you still really want to do that, set virtualedit to onemore.

just simply inoremap jj <esc>

Related

Vim map esc key in insert mode without losing undo sequence?

I have one question about Vim. I understood map as just the equal command till now. Here's the thing. I put imap <c-o> <esc>o in my .vimrc file to start a new line. As to the reason why not just map <CR> is that I followed the suggestion by Drew Neil that using esc and o command to replace so that I can use undo command line by line. However, when I use <c-o> to start a line, the undo command doesn't work, which means Vim doesn't switch the mode even I map the <esc> ! I don't know whether is feature or bug of Vim? I will appreciate it if you help me in some ways.
You can use inoremap <c-o> <c-g>u<esc>o to get the desired behaviour you want. <c-g>u breaks the current undo sequence (see :h i_CTRL-G_u).
I actually never thought about why having <esc> in insert mappings doesn't count as breaking the undo sequence. I could certainly theorize why but doing so is dangerous in an SO answer, so I won't :)
Edited to add: Simpler would be: inoremap <c-o> <c-g>u<cr>

How to preserve indent after pressing Esc in Vim

I have set autoindent
I go to a line, press A and <CR> which gets me to the next line and inserts an indent. However if I press Esc the cursor jumps to the beginning of the line and the indent is gone.
I have to go about and press tabs to get to the right place again.
I know the help says:
If you do not type anything on the new line except <BS> or CTRL-D and then type
<Esc>, CTRL-O or <CR>, the indent is deleted again.
Is there a way to disable this, or at least a workaround?
I had this exact problem until two days ago.
There is no way to disable this, but luckily, you don't need to, because instead:
Enter insert mode with S or cc. Entering insert mode again with S will enter insert mode with the proper level of indentation, making the fact that Vim deleted the indents unimportant.
Note: I found that this trick worked for me most places. But for some reason, it did not work with Python files. I'm guessing it's something to do with the Python filetype messing with its own indentation functions, or something along those lines.
Edit:
Another trick, you can define cpoptions in a way that, if you're on a line with an indent and move the cursor, it will preserve the indent. This won't solve your problem of hitting Esc right away, but it's a related issue that might also be bothering you.
A simple way is to press '.' (or any char), escape, then press x to remove the char. The indent should be preserved.
Alright, I figured this out.
Based on Edan Maor's answer, S or cc should enter insert mode with the proper level of indentation.
...except when it doesn't :)
This works under two circumstances.
when cindent is set, it will insert indent based on C formatting rules
This may prove annoying when editing non C-like files.
when indentexpr is set.
I found that the best solution is to have this is my .vimrc
set autoindent
set indentexpr=GetIndent()
function GetIndent()
let lnum = prevnonblank(v:lnum - 1)
let ind = indent(lnum)
return ind
endfunction
Now when I press S or cc, it will insert the same indent as on the previous non-blank line.
consider I use 'o' to start a newline. I add below config in _vimrc(notice I have ':set autoindent')
" ugly hack to start newline and keep indent
nnoremap o ox<BS>
nnoremap O Ox<BS>
type your text then press == in normal mode in that line
It may be worth noting that with proper plugins S and cc seem to work properly again. It is most likely python-mode that is fixing this.
https://github.com/klen/python-mode
I had want to achieve the same effect, but because I want the plugin showing indent to work properly. This is my workaround: I've found that <enter> in normal mode is almost useless. It only moves the cursor one line down, which could be achieved by j.
So I added this in my .vimrc:
nmap <cr> o.<c-h><esc>
Whenever I need a blank line for its indentation, I'd use <enter> instead.

Vim Pre-Exit (Esc Key) Command?

Right now in Vim when I go to a new line (or press 'p' or 'o' in normal mode) I get a lovely automatic indent, that also disappears if I exit insert mode without adding anything to it.
Is there a way to bind something to before I exit insert mode, such as inserting a phantom character then removing it?
Argh, I just read about this exact thing like two days ago but I can't remember where.
Anyway, the trick is to input a character right after <CR> and delete it immediately. There are a bunch of ways to do it:
<CR>a<Esc>x
<CR>a<C-w>
<CR>a<BS>
--EDIT--
Vim being Vim there are probably many other ways.
To automate these, you need to add a mapping to your .vimrc:
inoremap <CR> <CR>a<BS> " insert mode mapping for <CR>
nnoremap o oa<BS> " normal mode mapping for o
But I'm not sure you should overwrite defaults like that.
--EDIT--
However, what is annoying with Vim's default behaviour is that you may need to do some <Tab><Tab><Tab><Tab> before actually inputing some text on non-indented line or do == when you are done or rely on the automatic indentation rules for your language at the next <CR>.
All that can be skipped by using <S-S> which puts you in INSERT mode right at the correct indentation level.
Try either cc or S in normal mode to change a line with respect to indention. No need for phantom characters.
:h cc
:h S
A mapping like the following should do the trick:
imap <esc> <esc>:s/\s\+$//<CR>
This one deletes trailing characters when you press esc in insert mode.

Yank a region in VIM without the cursor moving to the top of the block?

Is there a simple way (i.e. without writing a script or elaborate keymap sequence) to Yank a group of lines and leave the cursor wherever the Yank was performed, as opposed to at the start of the block?
According to VIM's help: "Note that after a characterwise yank command, Vim leaves the cursor on the first yanked character that is closest to the start of the buffer." Line-wise seems to behave similarly.
This is a bit annoying for me since I tend to select a large region from top to bottom, Yank, and then paste near or below the bottom of the selected region. Today I'm setting a mark (m-x) just before Yank and then jumping back, but I suspect there may be a different Yank sequence that will do what I need.
I've searched SO and the web for this numerous times. There is so much existing "VIM shortcuts" material to wade through yet I've not found a solution to this one yet.
Thanks in advance.
Not quite answering your question, but perhaps '] would solve your problem?
'] `] To the last character of the previously changed or
yanked text. {not in Vi}
If you're using visual blocks (v), then after yanking the block you can use gv to re-select the same block (which also moves your cursor position back to where it was before yanking). If you then press Esc, the block is un-selected without moving the cursor.
Also of interest might be the ctrl-o command in visual block mode, which jumps between the start and end of the selected block.
If yanking in visual mode, you could also use '> or `> to go to the last line/character of the just yanked visual selection. In this context this is essentially the same as '] and `] which is apparently not supported e.g. in VsVim.
:y3 will yank three whole lines from current current line, If you know exactly how many line to yank, this command is very handy. :help :yank for details.
:%y will select the whole buffer without moving the cursor,
like ggvG$y, without the flash of selection highlight and modifying the "* register.
I use this insert mode map:
function! SelectAll()
%y*
endfun
imap <expr> <F3> SelectAll()
ps: if you prefer <C-V> to paste(outside vim), use %y+
check https://stackoverflow.com/a/1620030/2247746
I'm not sure sure if YankRing has changed since the vmap ygv<Esc> solution was posted but that didn't persist for me after adding it to my .vimrc. YankRing actually overwrote it.
Here's my solution in .vimrc.
function! YRRunAfterMaps()
vmap y ygv<Esc>
endfunction
I don't know what happened in the meantime but in IdeaVim the accepted answers don't work as I'd like them to. (Don't move the cursor on yank)
For me what did the trick was just setting a mark before yank and go to that afterwards.
vmap y mxy`x

Mapping :nohlsearch to escape key

I like to use hlsearch but I hate to keep everything highlighted after searching, to solve this problem I could simply use :nohlsearch or an abbreviation of it but that is still to much effort so I decided to try to do that on pressing escape. What I came up with is:
nnoremap <ESC> :nohlsearch<CR>
This works exactly as I want it to in GVim which I usually use for development but it does not work in vim.
If I search something in vim, press escape to deactivate the highlighting and use one of the arrow keys to navigate vim goes directly into insert mode and inserts a character on a new line.
As I never really came around to using h, j, k and l for navigation this is really annoying and I would like to know how I can make vim behave like gvim.
If you need more information you can find my entire vim configuration here.
Your problem is that when you press <Up> terminal sends something like <Esc>OA (you will see it if you type <C-v><Up> in insert mode) which is remapped to :nohlsearch<CR>OA. I do not know any solution except not mapping a single <Esc>, try either mapping to double <Esc>.
I created this map to disable search when press double <Esc>
nnoremap <silent> <Esc><Esc> :let #/ = ""<CR>
is :noh still too much work?
EDIT: I don't know about you, but I personally think :noh is easier than pressing Esc key, since I can press all the buttons without stretching my pinky too far (which is why I think the default mapping of Esc for going back to Command Mode from Insert Mode is a bit unfortunate). If you really use the :nohlsearch that much, you probably should remap it to something you can reach from the Home Area (i.e. regular letters, or numbers, or perhaps Ctrl-letters).
Anyway, typing the exact command you give works in my vim (on gnome-terminal). Are you sure you put the rule in .vimrc file, instead of .gvimrc? No luck after restarting vim? Try :source /path/to/config/file and see if that makes it to work.

Resources