回答:
このスニペットは、Damian Conwayの素晴らしい講演「More Instantly Better Vim」(4分59秒)を使用しています。検索結果間をジャンプすると、ハイライト全体が短時間点滅します。
" Damian Conway's Die Blinkënmatchen: highlight matches
nnoremap <silent> n n:call HLNext(0.1)<cr>
nnoremap <silent> N N:call HLNext(0.1)<cr>
function! HLNext (blinktime)
let target_pat = '\c\%#'.@/
let ring = matchadd('ErrorMsg', target_pat, 101)
redraw
exec 'sleep ' . float2nr(a:blinktime * 1000) . 'm'
call matchdelete(ring)
redraw
endfunction
強調表示の変更をより永続的にしたい場合は、これを微調整matchdelete
して、他の時間(たとえば、カーソルが移動したとき)に呼び出します。
私は最近、別の質問に答えてこのより高度なバージョンを書きました。以下の変更があります。
n
次の一致にジャンプするためにもう一度押すなど)。これにより、より長い時間を設定できます。VIM-searchhiプラグインは、もともと要求された機能を提供します。
ここでのRichの回答に基づいて、いくつかの違いがあります。
を使用して強調表示をクリアでき<C-l>
ます。
fun! SearchHighlight()
silent! call matchdelete(b:ring)
let b:ring = matchadd('ErrorMsg', '\c\%#' . @/, 101)
endfun
fun! SearchNext()
try
execute 'normal! ' . 'Nn'[v:searchforward]
catch /E385:/
echohl ErrorMsg | echo "E385: search hit BOTTOM without match for: " . @/ | echohl None
endtry
call SearchHighlight()
endfun
fun! SearchPrev()
try
execute 'normal! ' . 'nN'[v:searchforward]
catch /E384:/
echohl ErrorMsg | echo "E384: search hit TOP without match for: " . @/ | echohl None
endtry
call SearchHighlight()
endfun
" Highlight entry
nnoremap <silent> n :call SearchNext()<CR>
nnoremap <silent> N :call SearchPrev()<CR>
" Use <C-L> to clear some highlighting
nnoremap <silent> <C-L> :silent! call matchdelete(b:ring)<CR>:nohlsearch<CR>:set nolist nospell<CR><C-L>
私が考えることができる唯一の方法は、CursorMoved
およびCursorMovedI
autocmds を使用することです。これらはカーソルが移動するたびに呼び出されます...
これを正確に行うコードを次に示します。
fun! CursorColour()
if !g:searching | return | endif
let l:prev_end = 0
" Loop until we've found all matches of the current search pattern
while 1
let l:start = match(getline('.'), @/, l:prev_end)
" No more matches: stop looping
if l:start == -1 | break | endif
let l:cursor = col('.')
" Check if the cursor is inside the string
if l:cursor > l:start && l:cursor <= l:start + strlen(@/)
hi Cursor guifg=#121212 guibg=#afd700
return
endif
" Set start location for next loop iteration
let l:prev_end = l:start + strlen(@/)
endwhile
" We return if we're on a highlighted string, if we're here we didn't
" match anything
call ResetCursorColour()
endfun
fun! ResetCursorColour()
hi Cursor guifg=#ffffff guibg=#000000
endfun
autocmd CursorMoved,CursorMovedI * call CursorColour()
let g:searching=0
nnoremap <silent> <C-L> :nohlsearch<CR>:let g:searching=0<CR>:call ResetCursorColour()<CR><C-L>
nnoremap / :let g:searching=1<CR>/
いくつかの注意事項があります:
これはgVimでのみ機能します。これは、ターミナルVimではカーソルの色を変更できないためです(これはターミナルエミュレータで設定するものであり、Vimがほとんどのターミナルで制御できるものではありません)。
自分の現在のキャラクターが現在の検索用語の一部であるか、強調表示されているかどうかを確認する明確な方法が見つかりません。唯一の方法は、行を取得し、それを(再び)正規表現すること@/
です。設定間/
およびmatch()
設定によっては、正規表現の解釈に若干の違いがある場合があります(を参照:help match()
)。
現在、実際に何かを強調表示しているかどうかを確認する方法が見つかりません@/
。強調表示の内容に関係なく、レジスタには最後に使用した検索が含まれています。そこで/
、最初にg:searching
変数を設定してアクティブな検索を行っていることを示すようにリマップし、強調表示をクリアするため<C-l>
に呼び出し:nohlsearch
て、g:searching
検索していないことを示すためにfalseに設定しました...
これは、カーソルが移動するたびに実行され、特に大きなファイル/行、遅いシステム、複雑な正規表現ではあまり高速ではないかもしれません(私にとってはうまくいくようです)。
物事を最小限に抑えるために、それでも私にとって完璧に機能するように、私はこれを上からインスピレーションを得ていますCursorMoved
:
function! HLNext()
let l:higroup = matchend(getline('.'), '\c'.@/, col('.')-1) == col('.')
\ ? 'SpellRare' : 'IncSearch'
let b:cur_match = matchadd(l:higroup, '\c\%#'.@/, 101)
redraw
augroup HLNext
autocmd CursorMoved <buffer>
\ execute 'silent! call matchdelete('.b:cur_match.')'
\ | redraw
\ | autocmd! HLNext
augroup END
endfunction
nnoremap <silent> * *:call HLNext()<CR>
nnoremap <silent> # #:call HLNext()<CR>
nnoremap <silent> n n:call HLNext()<cr>
nnoremap <silent> N N:call HLNext()<cr>
今、n
さえせずにhlsearch
、私はカーソルを移動するまで、私は上陸した私のショー。SpellRare
それ以外の場合はスムーズだし、それはより多くのovbious場合にのみ、単一の文字が一致するために使用されますIncSearch