Vim Pre-Exit (Esc Key) Command? - vim

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.

Related

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 mapping to copy all text in visual mode

I would like to map ctrl+a in visual mode to select and copy all text from the current buffer.
The basic idea is to execute: %y* (copy all buffer to clipboard). So, the mapping should be: xmap :%y* (xmap for visual mode only)
However, whenever I run this mapping, this output is shown:
E492: Not an editor command: '<,'>%y*
And, I think Vim is right :-). When in visual mode, pressing the ":", makes the cmd-line show those surprising characters:
":'<,'>"
The only relevant piece of info where I could find this pattern ('<,'>) is that one: http://vimdoc.sourceforge.net/htmldoc/cmdline.html#v_:
(and it didn't help me).
Question: Am I doing something wrong (configuration...) ? Is there another answer to my need (copy all text to clipboard) ?
I am running Vim 7.3 and I only set nocompatible in my vimrc
Thanks for your help,
Tom
Use:
xnoremap <whatever> :<c-u>%y*<return>
The additional ctrl-u erases the command line till the cursor.
From vim reference:
*c_CTRL-U*
CTRL-U Remove all characters between the cursor position and
the beginning of the line. Previous versions of vim
deleted all characters on the line. If that is the
preferred behavior, add the following to your .vimrc: >
:cnoremap <C-U> <C-E><C-U>
Use the following mapping:
nmap <C-A> ggVGy
It yanks all the current file. By the way, I'm not sure it's exactly what you what. I don't understand why you want a visual mapping.

Vim: strange escaping to normal mode behaviour

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>

Vim Dumb Indenting?

Is there a way to just have Vim copy the indent from the line above, whether it be spaces or tabs, oblivious of the file types?
:set ai
See :help autoindent
I assume you are going to paste something and adjust the indent.
Try ]p
If you are at the beginning of the line and want to copy all the indenting characters above the line that you are currenly on now you can use Ctrl+y. It copies the character from the line above one at a time. Ctrl+e does the same thing but it copies from the line below.
It seems what I've wanted isn't actually possible as Vim automatically removes whitespaces, and uses configuration settings for its indention.
I've avoided this put slapping these in to my vimrc:
:inoremap <CR> x<BS><CR>x<BS>
:inoremap <up> x<BS><up>
:inoremap <down> x<BS><down>
:nnoremap o ox<BS>
:nnoremap O Ox<BS>
It simply puts a character in place and then removes it before I exit the editing mode, so Vim doesn't remove the empty line. If this is the case then it may be simply Vim checking if any editing was done to the line, auto indenting not counted. Maybe someday I'll check out the source and poke around.
I also wanted to use the previous line's indent (so I'd get different indents for different files and not have to tamper with settings each time), but I've managed to compromise and use the lovely Vim plugin.

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