Defina a cor do cursor diferente quando estiver em uma palavra destacada

19

Com o esquema de cores atual que estou usando, é difícil encontrar onde o cursor está posicionado ao navegar pelos resultados da pesquisa. A cor de destaque e a cor do cursor estão combinadas, dificultando a localização do cursor.

Como faço para definir a cor do cursor diferente quando está em uma palavra destacada?

Captura de tela do problema

ma08
fonte

Respostas:

14

Uso esse trecho da fantástica palestra de Damian Conway, Mais instantaneamente melhor Vim (aos 4m 59s). Faz com que todo o destaque pisque brevemente quando você pula entre os resultados da pesquisa.

" 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

Se você deseja que a alteração no destaque seja mais persistente, você pode ajustar isso para chamar matchdeleteem outro momento (por exemplo, quando o cursor se move).

ATUALIZAR:

Eu escrevi recentemente esta versão mais avançada em resposta a outra pergunta. Possui as seguintes alterações:

  1. (Opcionalmente) pisca repetidamente: a versão original de Conway pisca apenas uma vez: liga e desliga,
  2. Permite interromper o piscar digitando outros comandos (como pressionar nnovamente para pular para a próxima partida). Isso permite que você defina um tempo mais longo

ATUALIZAÇÃO 2:

O plug - in vim-searchhi fornece o recurso solicitado originalmente.

Rico
fonte
Funciona bem. Eu vou usar isso a partir de agora. Vou tentar implementar o persistente algum tempo depois.
ma08 27/03/2015
O que as 2 primeiras linhas fazem? Tanto quanto posso ver, as variáveis ​​atribuídas não são usadas e, se eu remover essas linhas, ainda funcionará.
Martin Tournoij
@Carpetsmoker Essas linhas (agora excluídas) eram uma boa crosta antiquada. Se você assistir à palestra, verá que Conway chega a essa solução após algumas iterações. As variáveis ​​desnecessárias foram usadas nas variações anteriores, mas não nesta. Copiei-o no meu .vimrc antes de realmente começar a aprender vimscript e, obviamente, nunca mais olhei o código novamente, mesmo ao colá-lo na minha resposta! Bem manchado.
Rico
Eu recentemente substituiu o vim-pulso (eu acho que é chamado) addon com esse trecho e é muito melhor / mais rápido
craigp
@Badger Fico feliz em ouvir isso. :)
Ricos
5

Baseado na resposta de Rich aqui, com algumas diferenças:

Você pode limpar o realce com <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>
Martin Tournoij
fonte
3

Você pode escolher uma cor melhor. Basta colocar isso no seu vimrc:

hi Cursor guifg=#121212 guibg=#afd700
adelarsq
fonte
Essa é sempre uma opção, só estou olhando para ver se é possível definir cores de acordo com o contexto.
MA08
Eu não acho que é útil, mas você pode detectar se o padrão de pesquisa (on / ou #) é o mesmo que a palavra sob o cursor e alterar o cursor destacar
adelarsq
3

A única maneira de pensar é usando os autocmds CursorMovede CursorMovedI, estes são chamados toda vez que o cursor é movido ...

Aqui está um código que faz exatamente isso:

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>/

Existem algumas advertências :

  • Isso funciona apenas para o gVim, já que não é possível alterar a cor do cursor no terminal Vim (isso é algo que você configura no emulador de terminal e não algo que o Vim pode controlar na maioria dos terminais).

  • Não consigo encontrar uma maneira óbvia de verificar se o personagem em que faço parte faz parte do termo de pesquisa atual e / ou está sendo destacado; a única maneira é pegar a linha e regexpá-la (novamente) com @/. Pode haver algumas pequenas diferenças na interpretação do regexp entre /e match()dependendo das suas configurações (consulte :help match()).

  • Não consigo encontrar uma maneira de verificar se atualmente estamos destacando algo, o @/registro contém a última pesquisa usada, independentemente do que estamos destacando. Então, o que fiz foi remapear /para definir primeiro a g:searchingvariável para indicar que estamos fazendo uma pesquisa ativa e, com <C-l>isso, chamamos :nohlsearchpara limpar o realce e definimos g:searchingcomo false para indicar que não estamos pesquisando ...

  • Isso é executado toda vez que o cursor se move , pode não ser muito rápido, especialmente para arquivos / linhas grandes, sistemas lentos ou regexps complicados (embora pareça funcionar bem para mim).

Martin Tournoij
fonte
1

Para manter as coisas mínimas, mas ainda funciona perfeitamente para mim, eu tenho isso, inspirado por cima: destaque simples até 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>

Agora, nmesmo sem hlsearchme mostra onde aterrissou até mover o cursor. O SpellRareé usado para torná-lo mais ovbious quando apenas um único personagem corresponde, caso contrário, é o bomIncSearch

perelo
fonte
0

Tentei algumas das outras respostas listadas aqui e a solução aqui, mas as achei perturbadoras e propensas a mensagens de erro. O timakro escreveu um plugin que resolve o problema e está funcionando bem para mim até agora.

John
fonte