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.)
Related
I would like to set up VIM for Cobol development and wanted to have the lines form column 7 to 11 marked so as to indicate the code areas. However, when I added this line of code in my vimrc file it colorized the NERDTree too.
set colorcolumn=7,11,73,80
autocmd VimEnter * NERDTree
autocmd VimEnter * wincmd p
How can I make the NERDTree columns not colorized and keep colorization only on the working file?
With the following line in your vimrc:
set colorcolumn=7,11,73,80
you define a global value for a window-local option which is reused for every new window. It is set for the 1st window, which passes it on to the 2nd window, etc.
Since that specific value for that specific option only is to be applied to Cobol buffers, you are supposed to use Vim's built-in filetype plugin support:
Make sure you have either of those lines in your vimrc:
filetype plugin on
filetype plugin indent on
filetype indent plugin on
See :help :filetype.
Create after/ftplugin/cobol.vim under your Vim runtime. On a typical Unix system, it should look like this:
$HOME/.vim/after/ftplugin/cobol.vim
And add the line below:
setlocal colorcolumn=7,11,73,80
We use :help :setlocal to make sure that the option won't be passed on to other windows.
I can do <C-O>:noh<CR> when I'm in insert mode, but it doesn't work when done automatically:
autocmd InsertEnter * :nohlsearch
This works, but it behaves differently:
autocmd InsertEnter * :set nohlsearch
To clarify, what I want is to run :nohlsearch if I enter insert node, but I still want to keep the ability to do /<CR>N to search for another item.
I think, what you want can be accomplished by setting the search register directly:
:autocmd InsertEnter * :let let #/=''
If you want to restore the highlighting when returning from insert mode, you would need to save and restore the pattern, something like this should do it:
:autocmd InsertEnter * :let b:_search=#/|let #/=''
:autocmd InsertLeave * :let #/=get(b:,'_search','')
This saves and restores the current search pattern in the buffer local variable b:_search.
You should write a function calling :nohl and then redraw:
function DisableHL()
nohl
redraw
endfunction
and then autocmd InsertEnter * :call DisableHL()
I think I came up with a smart-ish way of accomplishing exactly the same effect (at least it does exactly what I want and I seem to want what you asked for).
I have this in my vimrc:
Disable highlighting when entering Insert mode
autocmd InsertEnter * set nohlsearch
Re-enable highlighting when pressing any of the nN?/ keys before sending the key, then send the key
for s:k in ['n', 'N', '?', '/']
execute('nnoremap ' . s:k . ' :set hlsearch<cr>' . s:k)
endfor
to hide last search's hightlighting
(I like to be able to quickly disable it without entering insert mode)
nnoremap <silent> <bs> :set nohlsearch<cr>
It basically sets [no]hlsearch on the fly as you use the commands.
I also checked, and at least on my setup it doesn't mess if using nN?/ as normal mode command (for vim's default commands at least) arguments (like dtN to delete until next N), although this might be a concern if you ever remap any of those keys, or if a plugin does it without you noticing it.
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.
I am using :set textwidth=80 to make the Vim editor do hard wrapping automatically. However, sometimes for certain lines within a file (e.g. tables in LaTeX), I do not want Vim to do any hard wrapping automatically. Is there a way to mark certain lines to disable hard wrapping in Vim? Or automatically :set textwidth=0 just for specified lines?
There's nothing out-of-the-box, but you can build a solution with an :autocmd <buffer> on the CursorMoved,CursorMovedI events. On each move of the cursor, you have to check whether you're currently in one of those "certain lines", and modify the local 'textwidth' option accordingly:
autocmd CursorMoved,CursorMovedI <buffer> if IsSpecialLine() | setlocal textwidth=0 | else | setlocal textwidth=80 | endif
Put this into ~/.vim/after/ftplugin/tex.vim. (This requires that you have :filetype plugin on; use of the after directory allows you to override any default filetype settings done by $VIMRUNTIME/ftplugin/tex.vim.) Alternatively, you could define an :autocmd FileType tex autocmd ... directly in your ~/.vimrc, but this tends to become unwieldy once you have many customizations.
For the IsSpecialLine() function, you probably need to match a regular expression on the current line (getline('.') =~# "..."). If you can identify the "certain lines" through syntax highlighting, my OnSyntaxChange plugin can do all the work for you.
I've tried Ingo Karkat answer. Although it does work very well and does what the OP asks, I find it distracting (if I have long tables with row hundreds of characters long, there are a lot of shifts up and down when passing over tables) and can slow down a lot vim on big files (the textwidth and wrap are changed for the whole file, so running the autocmd for every cursor movement can be costly).
So I propose a static solution based on the idea that hopefully you have to modify a table as few times as possible. I've added the following to my ftplugin/tex.vim file:
" By default the text is
let s:textwidth = 90
let &l:textwidth=s:textwidth
" Toggle between "textwidth and wrap" and "textwidth=0 and nowrap".
" When editing a table, can be useful to have all the '&' aligned (using e.g.
" ':Tabularize /&') but without line brakes and wraps. Besides it's very
" annoying when line brakes "happen" while editing.
" As hopefully tables must be edited only from time to time, one can toggle
" wrap and textwidth by hand.
function! ToggleTwWrap() "{{{
" if textwidth and wrap is used, then disable them
if &textwidth > 0
let &l:textwidth=0
setlocal nowrap
else " otherwise re-enable them
let &l:textwidth=s:textwidth
setlocal wrap
endif
endfunction
So now if I want to edit manually a table I simply do
:call ToggleTwWrap()
to disable wrapping and textwidth and then again when I'm done with the table.
And of course you can create a command or a map
You can certainly set it for specific file types, but I don't think you can change those settings (or any, really) for individual lines.
Ingo Karat's answer works but setting textwidth on every single cursor move is too slow. This adapted version will only call setlocal textwidth= if the text width is actually going to change. This speeds things up considerably:
autocmd CursorMoved,CursorMovedI <buffer> if IsSpecialLine() | if &textwidth != 0 | setlocal textwidth=0 | endif | else | if &textwidth != 80 | setlocal textwidth=80 | endif | endif
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.