Establecer el color del cursor diferente cuando está en una palabra resaltada


19

Con el esquema de colores actual que he estado usando, es difícil encontrar dónde está ubicado el cursor al navegar por los resultados de búsqueda. El color de resaltado y el color del cursor se mezclan para dificultar la búsqueda del cursor.

¿Cómo configuro el color del cursor diferente cuando está en una palabra resaltada?

Captura de pantalla del problema.

Respuestas:


14

Utilizo este fragmento de la fantástica charla de Damian Conway, Más instantáneamente mejor Vim (a 4m 59s). Hace que todo el resaltado parpadee brevemente cuando saltas entre los resultados de búsqueda.

" 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

Si desea que el cambio en el resaltado sea más persistente, puede modificar esto para llamar matchdeleteen otro momento (por ejemplo, cuando se mueve el cursor).

ACTUALIZAR:

Recientemente escribí esta versión más avanzada en respuesta a otra pregunta. Tiene los siguientes cambios ::

  1. (Opcionalmente) parpadea repetidamente: la versión original de Conway solo parpadea una vez: encendido y apagado
  2. Le permite interrumpir el parpadeo escribiendo otros comandos (como presionar nnuevamente para saltar al siguiente partido). Esto le permite establecer un tiempo más largo

ACTUALIZACIÓN 2:

El complemento vim-searchhi proporciona la función solicitada originalmente.


Funciona genial. Estaré usando esto desde ahora. Intentaré implementar el persistente en algún momento más tarde.
ma08

¿Qué hacen las 2 primeras líneas? Hasta donde puedo ver, las variables asignadas no se usan, y si elimino esas líneas, aún funciona.
Martin Tournoij

@Carpetsmoker Esas líneas (ahora eliminadas) eran buenas y anticuadas. Si observa la charla, verá que Conway llega a esta solución después de algunas iteraciones. Las variables innecesarias se usaron en las variaciones anteriores, pero no en esta. Lo copié en mi .vimrc antes de comenzar a aprender vimscript, y obviamente nunca volví a mirar el código, ¡incluso cuando lo pegué en mi respuesta! Bien descrito.
Rico

Recientemente reemplacé el complemento vim-pulse (creo que se llama) con este fragmento y es mucho mejor / más rápido
craigp

@Badger Me alegra escucharlo. :)
Rico

5

Basado en la respuesta de Rich aquí con algunas diferencias:

Puede borrar el resaltado con <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>

3

Puedes elegir un mejor color. Solo pon esto en tu vimrc:

hi Cursor guifg=#121212 guibg=#afd700

Esa es siempre una opción, solo estoy buscando ver si es posible establecer el color de acuerdo con el contexto.
ma08

No creo que sea útil, pero puede detectar si el patrón de búsqueda (en / o #) es el mismo que la palabra debajo del cursor y cambiar el resaltado del cursor
adelarsq

3

La única forma en que puedo pensar es usando los autocmds CursorMovedy CursorMovedI, estos se invocan cada vez que se mueve el cursor ...

Aquí hay un código que hace exactamente eso:

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

Hay algunas advertencias :

  • Esto solo funciona para gVim, ya que no es posible cambiar el color del cursor en el terminal Vim (esto es algo que configura en su emulador de terminal, y no es algo que Vim pueda controlar en la mayoría de los terminales).

  • No puedo encontrar una manera obvia de verificar si el personaje en el que estoy es parte del término de búsqueda actual y / o está siendo resaltado; la única forma es obtener la línea y regexp eso (nuevamente) con @/. Puede haber algunas diferencias menores en la interpretación de expresiones regulares entre /y match()según su configuración (ver :help match()).

  • No puedo encontrar una manera de verificar si actualmente estamos resaltando algo, el @/registro contiene la última búsqueda utilizada, independientemente de lo que estemos resaltando. Entonces, lo que hice fue reasignar /para establecer primero la g:searchingvariable para indicar que estamos haciendo una búsqueda activa, y con una <C-l>llamada :nohlsearchpara borrar el resaltado, y establecer g:searchingen falso para indicar que no estamos buscando ...

  • Esto se ejecuta cada vez que se mueve el cursor , puede que no sea muy rápido, especialmente para archivos / líneas grandes, sistemas lentos o expresiones regulares complicadas (aunque parece funcionar bien para mí).


1

Para mantener las cosas mínimas, pero aún funciona perfectamente para mí, tengo esto, inspirado desde arriba: resaltado simple hasta 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>

Ahora, nincluso sin hlsearch, me muestra el lugar donde aterricé hasta que muevo el cursor. Se SpellRareusa para hacer que sea más desagradable cuando solo un personaje coincide, de lo contrario es el suaveIncSearch


0

Intenté algunas de las otras respuestas enumeradas aquí y la solución aquí, pero las encontré distrayendo y propensas a mensajes de error. timakro ha escrito un complemento que resuelve el problema y hasta ahora está funcionando bien para mí.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.