Insert mode Ctrl-O without triggering autocmds - vim

Having gone the full circle from default statusline, to customized, through neatstatus, powerline, airline and back to customized statusline, one of the fancy features was a coloured statusline depending on mode. So, a couple of autocmds to trigger a colour change on InsertEnter and InsertLeave, and all is nice, snappy, with a visual colour cue, and pretty much all in
set statusline=%-22.(%5l\ of\ %5L,%4c:%4v%)\ %P\ %6o\ %03b\ %<%F\ %y\ %h%m%r%=b:%2n\ %{strftime('%a\ %b\ %e\ %I:%M\ %p')}
But, Insert Mode Ctrl-O actually triggers the autocmds, and I like to have Up and Down imapped to gk gj, to move by display line and not entire wrapped lines. This can cause quite a bit of barely noticeable colour change flicker (the worst kind) during those times when quick scrolling through a file while in Insert mode. (This happens quite often when coding COBOL, when you need to scroll back and forth between DATA DIVISION and PROCEDURE DIVISION, but that's beside the point).
Anyway, I'll take the tsk-tsks for using cursor keys while in Insert mode, but I'm wondering if there is a way to
inoremap <Up> <C-O>gk
inoremap <Down> <C-O>gj
without triggering the InsertLeave InsertEnter autocmds, that repaint the statusline just to change the colour, pretty needlessly in this case. Or a different way to use cursor keys in Insert mode that move by display line and not wrapped line.

I thought only about really simple way how to do it
inoremap <Up> <C-c>gka
inoremap <Down> <C-c>gja
i_CTRL-c doesn't trigger InsertLeave autocommand event so I hope in your case it means no flash.
Then I found this excellent Ingo Karkat's answer:
function! IgnoreOn( motion )
set eventignore+=InsertLeave,InsertEnter
return "\<C-o>" . a:motion
endfunction
function! IgnoreOff()
set eventignore-=InsertLeave,InsertEnter
return "\<Left>\<Right>" | " Workaround for missing screen update.
endfunction
inoremap <expr> <SID>IgnoreOff IgnoreOff()
inoremap <expr> <SID>IgnoredDown IgnoreOn('gj')
inoremap <script> <Down> <SID>IgnoredDown<SID>IgnoreOff
inoremap <expr> <SID>IgnoredUp IgnoreOn('gk')
inoremap <script> <Up> <SID>IgnoredUp<SID>IgnoreOff

Related

Navigate in gvim like in most

I'd like to use gvim to view files with long lines. It's a table, so I'm not wrapping the lines.
Is this possible to configure gvim so arrows navigation will be like in "most" tool? Arrow key will move the whole screen 1 character lef/right/top/bottom?
Thanks a lot.
I think this should do what you want.
set nocompatible
set nowrap
set virtualedit=all
nnoremap <Left> zh
nnoremap <Right> zl
nnoremap <Up> <C-y>
nnoremap <Down> <C-e>
If you want the same behavior in insert mode, add the same mappings again as a second set, but use inoremap instead of nnoremap.
The virtualedit setting will allow the cursor to move beyond the end of the line and continue on as if the line had infinite whitespace to the right.
NOTE: virtualedit is only available if Vim was compiled with that feature. You can check with :version. If this feature is available, you should see a + next to it, e.g. +virtualedit.

Vim: Map Esc Without Affecting Terminal Control Characters

I'm trying to map <Esc> to turn off search highlighting in Vim. The problem is that keys simulated by the terminal with +Esc are affected.
The terminal sends characters much fast than I type. Is there perhaps a way to map key + timeout in vim?
The same question was asked 4 years ago and the answer was that it can't be done. Is this (still) true?
Mapping :nohlsearch to escape key
Your troubles are being caused by some plugin or other, native vim handles this fine. Start vim with vim --noplugin, or if that's not enough then bypass your vimrc with vim -u NONE (or gvim -U NONE) and :source this:
set nocp " life's too short for pure vi-compatibility mode
set timeout ttimeout " enable separate mapping and keycode timeouts
set timeoutlen=250 " mapping timeout 250ms (adjust for preference)
set ttimeoutlen=20 " keycode timeout 20ms
nno <ESC> :nohls<CR>
I've never seen and can't reproduce the interference you're describing so I don't know what's causing it, all I can suggest is binary search with your plugin set.
Yes, it's still not possible for the reason given by ZyX in his answer.
<Esc> is "special" because its behavior sits between a "normal" key like a (you can map it to whatever you want) and a modifier key (it's used by the terminal to represent a lot of special keys like <Up>).
Safely mapping <Esc> to do anything else/more than <Esc> is possible but you'll have to noremap all the affected keys. Here is what I have in my vimrc to mitigate that side effect:
nnoremap <Esc>A <up>
nnoremap <Esc>B <down>
nnoremap <Esc>C <right>
nnoremap <Esc>D <left>
inoremap <Esc>A <up>
inoremap <Esc>B <down>
inoremap <Esc>C <right>
inoremap <Esc>D <left>

Toggle highlight while searching in Vim

I like highlighting while searching in vim. Here's what I want:
I search for a word with /
Then, all of the results are highlighted. If I press any key other than n or N, I want the highlighting to be toggled off.
If I press n or N again after any number of commands, I want to toggle on the highlighting.
Where do I start? I'm not even sure what to google.
I have this in my .vimrc
nnoremap <CR> :noh<CR>
so that when I'm done seeing the highlighting, I just hit enter to remove it. It stays gone until I hit n or N again.
Note: If you want to keep the functionality of enter, add another <CR> on the end of the command.
I remap control-l (lower case L) so that it clears the search result as well as repaints the screen. This line in .vimrc does it:
nnoremap <silent> <C-l> :nohl<CR><C-l>
You can manually disable the last highlight with nohl.
I will let you know if I can figure out how to automate this.
One method is to setup a toggle mapping. These are some toggle mappings I have in my .vimrc:
let mapleader="\\"
noremap <silent> <Leader>th :set invhls hls ?<CR>
noremap <silent> <Leader>tn :set invnumber number ?<CR>
noremap <silent> <Leader>ts :set invspell spell ?<CR>
noremap <silent> <Leader>tw :set invwrap wrap ?<CR>
To toggle highlighting just type \th for toggle hls. The others are line number, spell checking, line wrapping. The final hls ? will display the new mode.
I prefer this, because to me it is nothing but natural.
Start searching with /<pattern> and once done, simply type <Leader>/ to stop the highlighting.
nnoremap <silent> <Leader>/ :set nohl<CR>

How to always clear hlsearch on clicking enter?

Right now I am using:
nnoremap <cr> :nohlsearch<cr><cr>k
But after I press Enter my cursor goes to beginning of line.
I have additional <cr>k because I want to use default <Enter> behaviour for example when I try to open file in Ack results quickview.
If you want Enter to keep the default behavior, then this mapping should take care of it.
nnoremap <CR> :nohlsearch<CR><CR>
It turns off search highlighting, moves the cursor down, and only applies to normal mode.
An alternative approach is to locally override the new behavior in the quickfix window and the command-line window, where <CR> has special meaning:
:nnoremap <CR> :nohlsearch<CR>
:autocmd BufReadPost quickfix nnoremap <buffer> <CR> <CR>
:autocmd CmdwinEnter * nnoremap <buffer> <CR> <CR>

Best of both worlds: arrow keys for cursor movement or flipping through buffers

I really like this vim trick to use the left and right arrows to flip between buffers:
"left/right arrows to switch buffers in normal mode
map <right> :bn<cr>
map <left> :bp<cr>
(Put that in ~/.vimrc)
But sometimes I'm munching on a sandwich or something when scrolling around a file and I really want the arrow keys to work normally.
I think what would make most sense is for the arrow keys to have the above buffer-flipping functionality only if there are actually multiple buffers open.
Is there a way to extend the above to accomplish that?
I'd rather have a completely different mapping because:
cursors are really useful, and not having them because you have a hidden buffer will annoy you a lot
some plugins use <left> and <right> because they are less obfuscated than l and h; those plugins are likely to break with such mappings
Anyway, you can try this:
nnoremap <expr> <right> (len(filter(range(0, bufnr('$')), 'buflisted(v:val)')) > 1 ? ":bn\<cr>" : "\<right>")
nnoremap <expr> <left> (len(filter(range(0, bufnr('$')), 'buflisted(v:val)')) > 1 ? ":bp\<cr>" : "\<left>")
To see documentation on the pieces above:
:h :map-<expr>
:h len()
:h filter()
:h range()
:h bufnr()
:h buflisted()
I use alt-direction to switch between buffers.
nmap <A-Left> :bp<CR>
nmap <A-Right> :bn<CR>
If you modifying hl's defaults, then the arrows would feel more useful. (Like changing whichwrap to allow hl to go past the end of line.)
I do something similar with jk to make them different from my arrows:
" work more logically with wrapped lines
set wrap
set linebreak
noremap j gj
noremap k gk
noremap gj j
noremap gk k
That will wrap long lines and jk will move to what looks like the line below. (If you have one long line, then you'll move to the part of that line below the cursor.) Great for editing prose or long comments.
See also
help showbreak
I map Tab and Shift+Tab to switch buffers when in normal mode (makes sense to my brain and the keys are not doing anything useful otherwise).
Add this to your .vimrc
" Use Tab and Shift-Tab to cycle through buffers
nnoremap <Tab> bnext<CR>
nnoremap <S-Tab> :bprevious<CR>

Resources