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()
Related
I use iTerm2 (Build 1.0.0.20130319) and Vim (bin of MacVim Snapshot 66) on top of OS X 10.7.5 as my CLI editing team.
In iTerm2 I defined to use a non-blinking vertical bar as a cursor shape.
In Vim I defined
" Enter insert mode (Cursor shape: vertical bar)
let &t_SI = "\<Esc>]50;CursorShape=1\x7"
" Leave insert mode (Cursor shape: block)
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
to be able to distinct between insert and normal mode. Basically this works fine. The problem arises when I leave Vim and return to the CLI. What happens is that the cursor does not return in its initial shape (vertical bar). Instead it decides to stay in a block shape.
Could I reset the cursor to it's initial shape or force it to return to be a vertical bar? I Could imagine to trigger an event on e.g. "VimLeave". But I don't know what I could pass as an escape sequence.
After a little bit more digging into :help I found out that
autocmd VimLeave * let &t_me="\<Esc>]50;CursorShape=1\x7"
would revert the cursor shape to its initial, or let's say a defined, shape.
That works great so far.
Does anyone know downsides of that approach? Besides VimLeave one could also trigger VimLeavePre or QuitPre.
EDIT:
Even better there's a new plugin available which does exactly what some people are looking for.
https://github.com/jszakmeister/vim-togglecursor
It's a little bit configurable, too:
let g:togglecursor_default = "block"
let g:togglecursor_insert = "line"
let g:togglecursor_leave = "line"
let g:togglecursor_disable_tmux = 0
Did you try this?
autocmd VimLeave * let &t_SI = "\<Esc>]50;CursorShape=1\x7"
I'm using Iterm with regular vim. This sets cursor solid on launch vim, blinks on insert mode. And returns to blinking on exit vim.
augroup myCmds
au!
autocmd VimEnter * silent !echo -ne "\e[2 q"
autocmd VimLeave * silent !echo -ne "\e[1 q"
augroup END
I tried this method before because I was used to Gvim's cursor style when switching to terminal. But I met the same problem and had no way to fix it.
Finally I have been using changing Cursor colour method. Once I got used to the style, I'm quite happy it and forget the cursor shape at all.
Change Cursor colour method
autocmd InsertEnter * set cul
autocmd InsertLeave * set nocul
Then set similar but different colour for Cursor than Normal in the theme if there is no built-in scheme in this theme.
Source: http://vim.wikia.com/wiki/Configuring_the_cursor
My sum of three methods for identifying insert mode in terminal:
How to make cursor change in different modes in vim?
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.
How to make vim automatically save only current buffer when focus is lost, not all files as described here http://vim.wikia.com/wiki/Auto_save_files_when_focus_is_lost
Based on your comments I can say that you have wrong question: you want not to “save only current buffer when focus is lost” (focus tends to have a meaning of “currently focused window”), but to “write buffer when switching to another one: when it is no longer in your focus of attention”. To complete this you may use
augroup AutoWrite
autocmd! BufLeave * :update
augroup END
, maybe combined with
set autowrite
and
set autowriteall
(sets of situations where first and second two variants are triggered intersect, but neither is a superset of another one).
Instead of :wa (write all), use :w.
Also you can try this
set updatetime=1000
autocmd CursorHoldI * silent w
just put it in your .vimrc
I start GVIM in not-maximized window mode and split its window horizontally making sure the windows are equally sized. How can I preserve this equal-sized split view when I maximize the main GVIM window? Whenever I maximize GVIM forgets that the windows have been equally split.
Thanks.
The command to equalize splits is ^W= (ctrl-W =), or in a script, wincmd =.
To do this automatically, you can use:
autocmd VimResized * wincmd =
I want to use Vim's soft wrap capability (:set wrap) to wrap some code at 80 characters, regardless of my actual window width.
I haven't been able to find a way to do this yet - all the soft wrapping seems tied to the width of the window
textwidth and wrapmargin are both for hard wrapping (they insert newline characters into the file)
vertical splitting into multiple windows and using :vertical resize 80 (possibly with :set breakat= to allow breaks on any character) on one of them sort of works (even though it's a bit hackish), but breaks when using :set number as the line numbers take up a variable number of columns (depending on the file length) and these are part of the 80.
Is there any way to do this in vim? It doesn't look promising, according to other sources.
Right now my approximation is just to have /^.\{80}\zs.\+ as my default search so it's at least highlighted. I thought about adding a :syntax item for it, but that broke when it overlapped other syntax items, so I dropped that idea.
You could
set a large minimum width for the line numbers column via :set numberwidth=6 and
then you could resize your window with :set columns=86 (or with the mouse) to the proper size.
If you edit a file with a million lines in it, you may have trouble, but that's unlikely. You're wasting 6 columns of screen real estate this way too. So there are still all kinds of problems.
You can highlight past the 80th column using :match like it says here and here.
Beyond that I can't see any way to do this. Seems like it'd be a nice feature though.
Try this:
set columns=80
autocmd VimResized * if (&columns > 80) | set columns=80 | endif
set wrap
set linebreak
set showbreak=+++
You can remove the if (&columns > 80) | if you always want 80 columns.
I don't have a solution to the soft wrap, but as for marking a column, as of Vim 7.3 (released 2010-08-15) :set colorcolumn=80 will highlight column 80. The color will depend on your syntax file.
See Vim 80 column layout concerns, :h colorcolumn.
Have you tried 'linebreak'?
*'linebreak'* *'lbr'* *'nolinebreak'* *'nolbr'*
'linebreak' 'lbr' boolean (default off)
local to window
{not in Vi}
{not available when compiled without the |+linebreak|
feature}
If on Vim will wrap long lines at a character in 'breakat' rather
than at the last character that fits on the screen. Unlike
'wrapmargin' and 'textwidth', this does not insert <EOL>s in the file,
it only affects the way the file is displayed, not its contents. The
value of 'showbreak' is used to put in front of wrapped lines.
This option is not used when the 'wrap' option is off or 'list' is on.
Note that <Tab> characters after an <EOL> are mostly not displayed
with the right amount of white space.
Combining eborisch's answer with some other answers I found here and things I had to work around, I came up with the following two-part solution:
This first part makes it easier to edit text with long lines:
" Allow enabling by running the command ":Freeform", or <leader>sw
command! Softwrap :call SetupSoftwrap()
map <Leader>sw :call SetupSoftwrap() <CR>
func! SetupFreeform()
" Use setlocal for all of these so they don't affect other buffers
" Enable line wrapping.
setlocal wrap
" Only break at words.
setlocal linebreak
" Turn on spellchecking
setlocal spell
" Make jk and 0$ work on visual lines.
nnoremap <buffer> j gj
nnoremap <buffer> k gk
nnoremap <buffer> 0 g0
nnoremap <buffer> $ g$
" Disable colorcolumn, in case you use it as a column-width indicator
" I use: let &colorcolumn = join(range(101, 300), ",")
" so this overrides that.
setlocal colorcolumn=
" cursorline and cursorcolumn don't work as well in wrap mode, so
" you may want to disable them. cursorline highlights the whole line,
" so if you write a whole paragraph on a single line, the whole
" paragraph will be highlighted. cursorcolumn only highlights the actual
" column number, not the visual line, so the highlighting will be broken
" up on wrapped lines.
setlocal nocursorline
setlocal nocursorcolumn
endfunc
With this alone you can get decent text wrapping for writing something like markdown, or a Readme.
As noted in other answers, getting wrapping at an exact column width requires telling vim exactly how many columns there are, and overwriting that each time vim gets resized:
command! -nargs=? Draft :call SetupDraftMode(<args>)
func! SetupDraftMode()
" I like 80 columns + 4 for line numbers
set columns=84
autocmd VimResized * if (&columns > 84) | set columns=84 | endif
:Softwrap
endfunc
There are still a couple of problems with this:
vim won't clear the screen outside of the columns you specify after calling set columns, and I can't figure out how to tell it to, so ideally you should call this immediately after opening vim
vim shows a prompt with the version number and some helpful commands when you open it, so these won't be cleared. You can add set shm+=I to disable that prompt
You can't open any vertical splits, because then both splits will be ~40 column. You would need to set columns to 2x your desired width and then always have a split open.
My vimscript is awful, but ideally someone could modify the Draft function above to take a column width as an argument, or use a global variable (g:explicit_vim_width?) that can be set manually if your window size changes.
There is no good way to do it. We can hack a makeshift setlocal softwrap with autocmd if we modify #eborisch answer. If we resize every time we enter a buffer, and we resize to a particular length when the local variable softwrap is set, we get the desired behaviour.
Let's suppose that we want to soft wrap to 80 columns, we can write the following in .vimrc.
augroup softwrap
autocmd VimResized * if (exists('b:softwrap') && &columns > 80) | set columns=80 | endif
autocmd BufEnter * set columns=999
augroup END
To turn on the mode for a particular buffer, use the following commands:
let b:softwrap=1
set columns=80