Files
dotfiles/.config/vim/vimrc.d/80-autocommands.vim
Julian Prein 0006a778f9 vim:aucmd: Improve highlighting on mode changes
When entering visual mode it does not really make sense to keep the
cword highlighting but it should restart automatically (i.e. without
CursorMoved) when leaving back out of visual mode.

About directly starting selection highlighting I am still unsure since I
rarely ever want to highlight only one character and it could decrease
performance.
2024-03-24 16:56:12 +01:00

158 lines
4.2 KiB
VimL

" Autocommands """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Bitfield for highlight_current augroup
const s:CLEAR_HIGHS_CWORD = 1
const s:CLEAR_HIGHS_VISUAL = 2
const s:CLEAR_HIGHS_ALL = 3
" Terminal
if (has('nvim'))
" Disable spellcheck
augroup terminal_no_spellcheck
au!
autocmd TermOpen * setlocal nospell
augroup END
endif
" change cursor shape depending on mode
augroup cursor_shape_by_mode
au!
if (has('nvim'))
" Beam when exiting
autocmd VimLeave * silent !echo -ne "\e[5 q"
else
" https://vim.fandom.com/wiki/Change_cursor_shape_in_different_modes
" https://github.com/tmux/tmux/issues/1593
if exists('$TMUX')
" Start insert mode - vertical bar/beam
let &t_SI = "\ePtmux;\e\e[5 q\e\\"
" Start replace mode - horizontal bar/underline
let &t_SR = "\ePtmux;\e\e[3 q\e\\"
" End insert or replace mode - block
let &t_EI = "\ePtmux;\e\e[1 q\e\\"
" Block when entering
autocmd VimEnter * silent !echo -ne "\ePtmux;\e\e[1 q\e\\"
" Beam when exiting
autocmd VimLeave * silent !echo -ne "\ePtmux;\e\e[5 q\e\\"
else
" Start insert mode - vertical bar/beam
let &t_SI = "\e[5 q"
" Start replace mode - horizontal bar/underline
let &t_SR = "\e[3 q"
" End insert or replace mode - block
let &t_EI = "\e[1 q"
" Block when entering
autocmd VimEnter * silent !echo -ne "\e[1 q"
" Beam when exiting
autocmd VimLeave * silent !echo -ne "\e[5 q"
endif
endif
augroup END
" Custom bindings when debugging
augroup termdebug_bindings
au!
autocmd SourcePost termdebug.vim tnoremap <Esc> <C-\><C-n>
augroup END
" Highlight word under cursor
function! ClearHighlights(what = s:CLEAR_HIGHS_ALL)
if and(a:what, s:CLEAR_HIGHS_CWORD) && exists('w:cword_match_id')
call matchdelete(w:cword_match_id)
unlet w:cword_match_id
unlet w:old_cword
endif
if and(a:what, s:CLEAR_HIGHS_VISUAL) && exists('w:visual_match_ids')
for l:pairs in w:visual_match_ids
let l:id = l:pairs[0]
let l:win = l:pairs[1]
call matchdelete(l:id, l:win)
endfor
unlet w:visual_match_ids
endif
endfunction
function! HighlightCurrentWord()
if exists('w:old_cword') && w:old_cword == expand('<cword>')
" Do not delete and readd the match if on the same word
return
endif
call ClearHighlights()
if (expand('<cword>') != '')
let w:old_cword = expand('<cword>')
let w:cword_match_id = matchadd(
\ 'CursorColumn',
\ '\V\<' . escape(expand('<cword>'), '/\') . '\>',
\ -1)
endif
endfunction
function! HighlightVisualSel()
call ClearHighlights()
let l:old_reg = getreg('"')
let l:old_regtype = getregtype('"')
silent! norm ygv
let w:visual_match_ids = []
" Add match to all windows containing the current buffer
for l:win in win_findbuf(bufnr())
let w:visual_match_ids += [[
\ matchadd(
\ 'CursorColumn',
\ '\V' . substitute(escape(@", '\'), '\n', '\\n', 'g'),
\ -1,
\ -1,
\ {'window': l:win}),
\ l:win
\ ]]
endfor
call setreg('"', l:old_reg, l:old_regtype)
endfunction
augroup highlight_current
au!
au CursorMoved * if mode() == 'n' |
\ call HighlightCurrentWord() |
\ else |
\ call HighlightVisualSel() |
\ endif
au CursorMovedI * call HighlightCurrentWord()
au WinLeave * call ClearHighlights()
au ModeChanged [vV\x16]*:* call ClearHighlights(s:CLEAR_HIGHS_VISUAL) | call HighlightCurrentWord()
au ModeChanged *:[vV\x16]* call ClearHighlights(s:CLEAR_HIGHS_CWORD) | call HighlightVisualSel()
augroup END
" When switching focus to another window, keep the cursor location underlined.
function! HighlightOldCursorPos()
let w:cursor_pos_match_id = matchaddpos(
\ 'Underlined',
\ [getcurpos()[1:2]])
endfunction
function! ClearOldCursorPos()
if exists('w:cursor_pos_match_id')
call matchdelete(w:cursor_pos_match_id)
unlet w:cursor_pos_match_id
endif
endfunction
augroup highlight_old_cursor_pos
au!
au WinLeave * call HighlightOldCursorPos()
au WinEnter * call ClearOldCursorPos()
" TODO: WinLeave is not triggered when entering command line mode and
" CmdlineEnter is triggered **after** entering
" nnoremap : :call HighlightOldCursorPos()<CR>:
" au CmdlineLeave * call ClearOldCursorPos()
augroup END
" Do not mark input from stdin as modified
augroup stdin_not_modified
au!
au StdinReadPost * set nomodified
augroup END