I use a lot of tabs in my Vim workflow, and each tab may have several splits in them. I recently discovered in Preserving equal sized split view that having this line in my vimrc helps will automatically make my splits equally sized.
autocmd VimResized * wincmd =
However, it only seems to resize the current tab I'm on if I resize the window that Vim is in. For other tabs, the splits are still unequally sized. Is there a way to automatically resize the splits in all tabs when the window size changes?
You can use the :tabdo command to execute the sequence In all existing tabs. This already gets the job done:
autocmd VimResized * tabdo wincmd =
There's one possibly undesirable side effect though, it will end the command on the last tab. You can work around that by saving it and restoring it after the end of the command. It's easier to do so by defining a function.
function! ResizeWindows()
let savetab = tabpagenr()
tabdo wincmd =
execute 'tabnext' savetab
endfunction
autocmd VimResized * call ResizeWindows()
I have been using vim for a couple of months now however my current workflow involves continuously scrolling down and up. For that i use Ctrl+f and Ctrl+b
So whenever I use the Ctrl+f combination the new text appears on the center of the screen. I wanted to know if there was a way for vim to always have a light coloured line in the center of screen (so i could use the line as a reference to the new content whenever i press ctrl+f (scroll half screen)). I know this request sounds odd but I am curious if such a feature exists?
You can try this smooth scroll plugin: https://github.com/terryma/vim-smooth-scroll I think it may solve your problem.
Put this in your .vimrc or in a script:
augroup HlMid
autocmd!
autocmd CursorMoved * :call HighlightMiddle()
augroup END
function! HighlightMiddle()
normal! M
execute "match search /\\%".line('.')."l/"
normal! ^O
endfunction!
EDIT: As rgoliveira stated in the comment that could interfere with match command. You need only to remove the autocommand and make it back whenever you use it:
Remove:
:autocmd! HlMid CursorMoved *
Reload:
:autocmd HlMid CursorMoved * :call HighlightMiddle()
For the last command in the function normal! ^o you get ^o by typing ctrl+v ctrl+o
I would like to be able to highlight the word under cursor without going to the next result.
The solution I found uses a marker:
noremap * mP*N`P
Is there any better solution ?
I noticed vim is not really good to keep the position of its cursor after the execution of commands. For instance, when I switch buffer, the cursor go back to the begining of the line.
I might be interesting to have a global setting for this.
There's unfortunately no global setting for that.
One common solution to the "highlight without moving" problem is:
nnoremap * *``
One solution to the "keep the cursor position when switching buffers" problem is:
augroup CursorPosition
autocmd!
autocmd BufLeave * let b:winview = winsaveview()
autocmd BufEnter * if(exists('b:winview')) | call winrestview(b:winview) | endif
augroup END
As detailed here, you can define a map as follows:
:nnoremap <F8> :let #/='\<<C-R>=expand("<cword>")<CR>\>'<CR>:set hls<CR>
My SearchHighlighting plugin changes the * command, so that it doesn't jump to the next match; you can still jump by supplying a [count]. It also extends that command to visual mode (another frequently requested feature not in Vim), and some more.
Imagine I'm coding, and I have different split panes open. What settings should I pass into vimrc to change the background color as I switch from one buffer/pane to another?
I have tried:
autocmd BufEnter * highlight Normal ctermbg=black
autocmd BufLeave * highlight Normal ctermbg=white
I would like to add that I am sure that I've got 256 colors enabled
Actually, there is a way to get this effect. See the answer by #blueyed to this related question: vim - dim inactive split panes. He provides the script below and when placed in my .vimrc it does dim the background of inactive windows. In effect, it makes their background the same colour specified for the colorcolumn (the vertical line indicating your desired text width).
" Dim inactive windows using 'colorcolumn' setting
" This tends to slow down redrawing, but is very useful.
" Based on https://groups.google.com/d/msg/vim_use/IJU-Vk-QLJE/xz4hjPjCRBUJ
" XXX: this will only work with lines containing text (i.e. not '~')
" from
if exists('+colorcolumn')
function! s:DimInactiveWindows()
for i in range(1, tabpagewinnr(tabpagenr(), '$'))
let l:range = ""
if i != winnr()
if &wrap
" HACK: when wrapping lines is enabled, we use the maximum number
" of columns getting highlighted. This might get calculated by
" looking for the longest visible line and using a multiple of
" winwidth().
let l:width=256 " max
else
let l:width=winwidth(i)
endif
let l:range = join(range(1, l:width), ',')
endif
call setwinvar(i, '&colorcolumn', l:range)
endfor
endfunction
augroup DimInactiveWindows
au!
au WinEnter * call s:DimInactiveWindows()
au WinEnter * set cursorline
au WinLeave * set nocursorline
augroup END
endif
You can't. The :highlight groups are global; i.e. when you have multiple window :splits, all window backgrounds will be colored by the same Normal highlight group.
The only differentiation between active and non-active windows is the (blinking) cursor and the differently highlighted status line (i.e. StatusLine vs. StatusLineNC). (You can add other differences, e.g. by only turning on 'cursorline' in the current buffer (see my CursorLineCurrentWindow plugin.))
One of the design goals of Vim is to work equally well in a primitive, low-color console as in the GUI GVIM. When you have only 16 colors available, a distinction by background color is likely to clash with the syntax highlighting. I guess that is the reason why Vim hasn't and will not have this functionality.
Basically what Kent said above will work -- surprisingly well at that. The only limitation is that you can only dim the foreground color. Copy this into vimrc, and evoke :call ToggleDimInactiveWin().
let opt_DimInactiveWin=0
hi Inactive ctermfg=235
fun! ToggleDimInactiveWin()
if g:opt_DimInactiveWin
autocmd! DimWindows
windo syntax clear Inactive
else
windo syntax region Inactive start='^' end='$'
syntax clear Inactive
augroup DimWindows
autocmd BufEnter * syntax clear Inactive
autocmd BufLeave * syntax region Inactive start='^' end='$'
augroup end
en
let g:opt_DimInactiveWin=!g:opt_DimInactiveWin
endfun
A few things I had to look up in writing this:
(1) windo conveniently executes a command across all windows
(2) augroup defines autocommand groups, which can be cleared with autocmd! group
For Neovim users, there is the winhighlight option. The help file provides the following example:
Example: show a different color for non-current windows:
set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
Personally, I use my statusline to let me know this. I use the WinEnter and WinLeave autocmds to switch to an inactive status line (grayed out) when leaving and an active statusline (bright colors) when entering. The split panes you mention are windows in vim. This also works because :help statusline tells us that its setting is global or local to a window, so you can use :setlocal statusline=... or let &l:statusline=... to only apply to the current window.
Your method won't work because a) BufEnter and BufLeave aren't necessarily the events that you want and b) highlight groups are global, so changing Normal's definition changes it for every window.
I would like to know how to change, if possible, the cursor in Vim (in color, shape, etc.) depending on what mode you are in.
I am constantly forgetting that I am not in Insert mode and start typing code, which results in all sorts of crazy things happening. It would be helpful if there was some sort of visual indication on the cursor.
The following works in xterm, urxvt, and other terminal emulators on Linux; iTerm2 on macOS; Git Bash with ConEmu on Windows; and more (see comments):
let &t_SI = "\e[6 q"
let &t_EI = "\e[2 q"
" reset the cursor on start (for older versions of vim, usually not required)
augroup myCmds
au!
autocmd VimEnter * silent !echo -ne "\e[2 q"
augroup END
Other options (replace the number after \e[):
Ps = 0 -> blinking block.
Ps = 1 -> blinking block (default).
Ps = 2 -> steady block.
Ps = 3 -> blinking underline.
Ps = 4 -> steady underline.
Ps = 5 -> blinking bar (xterm).
Ps = 6 -> steady bar (xterm).
When you use tmux, it is important to use it like that (without the \<Esc>Ptmux; escape). tmux will keep track of the correct cursor shape when you switch windows/panes.
If it does not work for you, try either to set TERM=xterm-256color before starting tmux, or add this to your .tmux.conf (thanks #Steven Lu):
set -ga terminal-overrides ',*:Ss=\E[%p1%d q:Se=\E[2 q'
A popular approach to indicate switching to and from Insert mode is
toggling the cursorline option, which is responsible for whether
the current screen line is highlighted (see :help cursorline):
:autocmd InsertEnter,InsertLeave * set cul!
or, alternatively:
:autocmd InsertEnter * set cul
:autocmd InsertLeave * set nocul
Modify the CursorLine highlighting group to change the styling
of the cursor line to your liking (see :help :highlight and
:help highlight-groups).
This approach assumes, of course, that you do not use the cursor
line highlighting in Normal mode.
Not sure if anyone else is facing a delay after hitting the Esc key to go back to normal mode to show the block cursor but if so, this is the way I fix it too.
Actually I'm using iTerm2 and using Vim inside my terminal on macOS. And when entering to insert mode, the cursor still being a block and is kind of confusing when you are at insert mode or normal mode.
I wanted to show a thin line as cursor when in insert mode and back to block when in normal mode as MacVim does. And to do so it's pretty simple, just added this to my .vimrc file as described here:
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_SR = "\<Esc>]50;CursorShape=2\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
But as you can see there was a delay when hitting ESC to exit insert mode back to normal mode and show the block as cursor again. So to fix it I found this:
set ttimeout
set ttimeoutlen=1
set ttyfast
And now it works pretty fine as you can see:
I hope it could help any one else! 👻
If you are using tmux and iTerm2 on macOS,
the following changes the cursor from a block to a cursor and highlights the current line
if exists('$TMUX')
let &t_SI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=1\x7\<Esc>\\"
let &t_EI = "\<Esc>Ptmux;\<Esc>\<Esc>]50;CursorShape=0\x7\<Esc>\\"
else
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
endif
:autocmd InsertEnter * set cul
:autocmd InsertLeave * set nocul
credit: https://gist.github.com/andyfowler/1195581
To change the shape of the cursor in different modes, you can add the following into your .vimrc file.
For the GNOME Terminal (version 2.26):
if has("autocmd")
au InsertEnter * silent execute "!gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_shape ibeam"
au InsertLeave * silent execute "!gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_shape block"
au VimLeave * silent execute "!gconftool-2 --type string --set /apps/gnome-terminal/profiles/Default/cursor_shape ibeam"
endif
If you use more than one profile in GNOME Terminal, you might have to adapt this to your profiles.
For Konsole in KDE4:
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
This works with multiple tabs and windows.
See also: “Change cursor shape in different modes” on Vim Tips Wiki.
You may try the Terminus Vim plugin:
In insert mode, the cursor shape changes to a thin vertical bar. In replace mode, it changes to an underline. On returning to normal mode, it reverts to the standard "block" shape.
I find it useful to only have the cursor blinking in Insert mode and keep it static in other modes.
set guicursor+=n-v-c:blinkon0
According to this post on "Vim Tips WiKi":
"To change the shape of the cursor in different modes, you can add the following into your vimrc:"
"For Terminal on macOS"
"Mode Settings
let &t_SI.="\e[5 q" "SI = INSERT mode
let &t_SR.="\e[4 q" "SR = REPLACE mode
let &t_EI.="\e[1 q" "EI = NORMAL mode (ELSE)
"Cursor settings:
" 1 -> blinking block
" 2 -> solid block
" 3 -> blinking underscore
" 4 -> solid underscore
" 5 -> blinking vertical bar
" 6 -> solid vertical bar
Scripts for other OS are also included in that post.
If you are using a modern version of nvim and you wanted to achieve this, you can avoid some of these fancy workarounds listed above.
The below settings will switch from block cursor in normal mode, to underline cursor in replace to line cursor in insert.
# ~/.tmux.conf
set -g default-terminal "screen-256color"
set -ga terminal-overrides ",*256col*:Tc"
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q',w
" ~/.vimrc
" Sets cursor styles
" Block in normal, line in insert, underline in replace
set guicursor=n-v-c-sm:block,i-ci-ve:ver25-Cursor,r-cr-o:hor20
I managed to get this working with the following settings pulled from these two sources.
tui-cursor-shape
guicursor
I don't think this adds much to the answers that other people have already provided but I wanted to somehow summarise things in one place and also have links to the relevant references.
This is what the relevant snippet from my .vimrc looks like:
" Cursor appearance
"
" See also: [1]'ANSI Control Functions Summary', [2]DECSCUSR, [3]xterm+tmux
" entry in terminfo.src.
" [1] https://www.vt100.net/docs/vt510-rm/chapter4.html
" [2] https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
" [3] https://raw.githubusercontent.com/mirror/ncurses/master/misc/terminfo.src
"
" On:
" - entered insert mode
let &t_SI = "^[[5 q^[]12;Magenta\007" " blinking bar (Ss) in magenta (Cs)
" - entered replace mode
let &t_SR = "^[[0 q^[]12;Red\007" " blinking block (Ss) in red (Cs)
" - leaving insert/replace mode
let &t_EI = "^[[2 q^[]112\007" " terminal power-on style (Se) and colour (Cr)
Note: The '^[' characters are actually one ESC (escape sequence) control character.
This works properly on xfce4-terminal:
add following script to your .vimrc
if has("autocmd")
au InsertEnter * silent execute "!sed -i.bak -e 's/TERMINAL_CURSOR_SHAPE_BLOCK/TERMINAL_CURSOR_SHAPE_IBEAM/' ~/.config/xfce4/terminal/terminalrc"
au InsertLeave * silent execute "!sed -i.bak -e 's/TERMINAL_CURSOR_SHAPE_IBEAM/TERMINAL_CURSOR_SHAPE_BLOCK/' ~/.config/xfce4/terminal/terminalrc"
au VimLeave * silent execute "!sed -i.bak -e 's/TERMINAL_CURSOR_SHAPE_IBEAM/TERMINAL_CURSOR_SHAPE_BLOCK/' ~/.config/xfce4/terminal/terminalrc"
endif
Brief:
As You know xfce4-terminal keeps preferences in .config/xfce4/terminal/terminalrc file. The script changes TERMINAL_CURSOR_SHAPE_BLOCK to TERMINAL_CURSOR_SHAPE_IBEAM when you're in insert mode, and back to block when you leave insert mode or vim. Feel free to change IBEAM to anything you want (BLOCK, IBEAM and UNDERLINE available).
I usually have the current vim mode onto statusline, among other things. If you seek simplicity, you can set only this information onto the statusline.
However, usually the really crazy things happen when you have caps lock depressed and are in command mode (since hjkl now are HJKL - just J and K is enough to make you pull your hair out when you don't understand what's happening. Do a :h J and :h K to see what I mean). Just beware the caps lock key and you'll be fine most of the time IMO.