What something fishy is going on in Vim with relative number? - vim

In Vim, you can set relative numbers
:set relativenumber
You will see the numbers who are subtracting of counting from the line where your cursor is placed. But I don't like the 0 as cursor, so I did :set number
And tadaa, you see the number of the current line where your cursor is.
I set it in my vimrc.
set relativenumber
set number
But I noticed something wrong. When you opened a split window, you see that the number where your cursor is, have jumped back to 0 in the window. When you close the window, you see that the number is still 0 in another buffer.
I tried to fix this in my vimrc, to give the autocmmands when you doing something with windows or buffers:
set relativenumber
set number
autocmd BufWinEnter * set nu
autocmd BufDelete * set nu
autocmd BufCreate * set number
autocmd BufLeave * set number
autocmd BufWinEnter * set nu
autocmd WinEnter * set nu
But nothing of them worked so far. The cursor still jumps back to 0. Can anyone tell me what I'm doing wrong there?
When I am in the window, and I set the number manually, it worked. But why can't I give it to an autocommand?

Related

Toggle absolute and relative numbering in VIM by insert/normal mode

I use the relative line number setting in vim. I would like vim to automatically switch to absolute line numbers when I am in insert mode and back to relative in normal mode. Currently I have tried this code in my vimrc
autocmd InsertEnter * :set number
autocmd InsertLeave * :set relativenumber
Unfortunately this only gets me part of the way there. This toggles on relative numbers the first time I leave insert mode, but will no longer go back to absolute numbers upon entering insert mode again.
First, do a
set number
Then
autocmd InsertEnter * :set norelativenumber
autocmd InsertLeave * :set relativenumber

Vim line numbers, absolute within visual mode and relative within insert

I have line numbers set within my .vimrc.
I'm wanting to switch to relativenumbers when in insert mode, and switch back to regular numbers in visual mode.
I've tried:
autocmd InsertEnter * :set number
autocmd InsertLeave * :set relativenumber
But this isn't working. I'm using Vim7.4.52 in terminal, Ubuntu.
If possible I want to do this automatically, so I haven't got to fiddle with manually entering a command.
number and relativenumber setting are not exclusive anymore, so rather use something like this:
autocmd InsertEnter * :set nonumber relativenumber
autocmd InsertLeave * :set number norelativenumber
Or use one of the many plugins, that do that (sorry, I don't remember which ones do that).

How to set a portion of the status line a certain color only if an element is evaluated- Vim

In Vim I'm trying to make my status-line to work how I want it to.
Here's what I'm going for:
When the file I'm editing has been saved, I want it to look like this when saved:
And this when unsaved:
The former I see, but I get this when saved:
(If those are too small to see, you can get the links here, here, and here)
Here's what I have so far:
set statusline=%1*\ %n:\ %f\ %y\ %(%#mid#%m%)%=%1*%6v%6l\%6L\ %*
Any suggestions?
Ideally I would like to be able to see the top when unsaved and the second one when saved.
Edit
After some searching I've come up with this, which seems like as good a start as any:
highlight User1 guibg=Black guifg=DarkYellow
highlight mid guibg=DarkRed guifg=Yellow
set statusline=%1*\ %n:\ %f\ %y\ %=%6v%6l\%6L\ %*
autocmd InsertChange * if (&modified) | set statusline=%1*\ %n:\ %f\ %y\ %#mid#%m%=%1*%6v%6l\%6L\ %* | endif
autocmd BufWrite * set statusline=%1*\ %n:\ %f\ %y\ %=%6v%6l\%6L\ %*
However, I can't seem to figure out when InsertChanged is actually called.
After much searching I found a solution that works for all my purposes:
set laststatus=2
highlight User1 guibg=Black guifg=DarkYellow
highlight mid guibg=DarkRed guifg=Yellow
let s:default = '%1* %n: %f %y %=%6v%6l%6L %*'
let s:changed = '%1* %n: %f %y %#mid#%m%=%1*%6v%6l%6L %*'
fun IsModified()
if &modified
return s:changed
endif
return s:default
endfun
autocmd BufEnter * set statusline=%!IsModified()
autocmd BufLeave * let &l:statusline = IsModified()
You're right that you can use :autocmds to update the statusline colors. However, InsertChange does not trigger when you think it is; it is merely for switching between normal inserting and overriding. Unfortunately, there's no exact event for "buffer changed"; you can trigger on InsertEnter and CursorHold, and then check the &modified flag.
My StatusLineHighlight plugin indicates the state of the buffer (modified, readonly, unmodifiable, special non-file "scratch") / window (is preview window) by changing the highlighting of the window's status line. You can either use it directly, or at least find useful implementation hints for your own one.

detect, if ctrlp is opened/active

I like the relativenumbers, but they turn out to be slow if I move through files with very long lines. So I added
autocmd CursorMoved,CursorMovedI * if &relativenumber | set norelativenumber | endif
autocmd CursorHold,CursorHoldI * set relativenumber
set updatetime=500
to my vimrc. It disables relative numbers during cursor movement and enables them afterwards again. However, this also enables them in ctrlp. Especially since ctrlp disables number, this causes columns to jump as soon as I cursor. Is there a way to detect, if I'm currently in the curlp file browser?
The CtrlP scratch buffer probably has a distinct name (if bufname('') =~ 'ctrlp')) or filetype (if &filetype ==# 'ctrlp') that you can use in a condition on a similar autocmd BufEnter.
(Note: I don't use the plugin, so the above names are just for illustration.)

How do I change the background color of current buffer or pane 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.

Resources