Ustaw inny kolor kursora na wyróżnionym słowie

19

Przy obecnym używanym przeze mnie schemacie kolorów trudno jest znaleźć pozycję kursora podczas nawigacji w wynikach wyszukiwania. Kolor podświetlenia i kolor kursora mieszają się, co utrudnia znalezienie kursora.

Jak ustawić inny kolor kursora, gdy znajduje się na wyróżnionym słowie?

Zrzut ekranu problemu

ma08
źródło

Odpowiedzi:

14

Korzystam z tego fragmentu fantastycznej wypowiedzi Damiana Conwaya „ More Natychmiast Better Vim” (na 4m 59s). Powoduje krótkie mrugnięcie całej podświetlenia podczas przeskakiwania między wynikami wyszukiwania.

" 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

Jeśli chcesz, aby zmiana w podświetlaniu była bardziej trwała, możesz ją dostosować, aby wywoływać matchdeletew innym momencie (np. Gdy kursor się porusza).

AKTUALIZACJA:

Niedawno napisałem tę bardziej zaawansowaną wersję w odpowiedzi na inne pytanie. Ma następujące zmiany:

  1. (Opcjonalnie) miga wielokrotnie: oryginalna wersja Conwaya miga tylko raz: włącz i wyłącz,
  2. Pozwala przerwać mruganie, wpisując inne polecenia (takie jak nponowne naciśnięcie, aby przejść do następnego dopasowania). Pozwala to ustawić dłuższy czas

AKTUALIZACJA 2:

Vim-searchhi plugin dostarcza pierwotnie żądanej funkcji.

Bogaty
źródło
Działa świetnie. Będę tego używać od teraz. Spróbuję wdrożyć ten trwały jakiś czas później.
ma08
Co robią pierwsze 2 linie? O ile widzę, przypisane zmienne nie są używane, a jeśli usunę te linie, nadal będzie działać.
Martin Tournoij
@Carpetsmoker Te linie (teraz usunięte) były dobrym staromodnym cruftem. Jeśli obejrzysz rozmowę, zobaczysz, że Conway doszedł do tego rozwiązania po kilku iteracjach. Niepotrzebne zmienne były używane we wcześniejszych odmianach, ale nie w tej. Skopiowałem go do mojego .vimrc, zanim naprawdę zacząłem uczyć się vimscript, i oczywiście nigdy więcej nie spojrzałem na kod, nawet po wklejeniu go do mojej odpowiedzi! Dobrze zauważony.
Bogaty
Niedawno zastąpiłem dodatek vim-puls (chyba nazywa się) tym fragmentem i jest znacznie lepszy / szybszy
craigp
@Badger Cieszę się, że to słyszę. :)
Rich
5

Na podstawie odpowiedzi Richa z pewnymi różnicami:

Możesz usunąć zaznaczenie za pomocą <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
źródło
3

Możesz wybrać lepszy kolor. Po prostu umieść to na swoim vimrc:

hi Cursor guifg=#121212 guibg=#afd700
adelarsq
źródło
To zawsze jest opcja, chcę tylko sprawdzić, czy można ustawić kolor zgodnie z kontekstem.
ma08
Nie sądzę, aby było to przydatne, ale możesz wykryć, czy wzorzec wyszukiwania (on / or #) jest taki sam jak słowo pod kursorem i zmienić podświetlenie kursora
adelarsq
3

Jedyny sposób, w jaki mogę myśleć, to użycie CursorMovedi CursorMovedIautocmds, są one wywoływane za każdym razem, gdy kursor jest przesuwany ...

Oto kod, który dokładnie to robi:

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

Istnieje kilka zastrzeżeń :

  • Działa to tylko dla gVim, ponieważ zmiana koloru kursora nie jest możliwa w terminalu Vim (jest to coś, co konfigurujesz w emulatorze terminali, a Vim nie może kontrolować w większości terminali).

  • Nie mogę znaleźć oczywistego sposobu sprawdzenia, czy znak, na którym jestem, jest częścią bieżącego wyszukiwanego terminu i / lub jest podświetlany; jedynym sposobem jest uzyskanie linii i wyrażenie regularne za pomocą @/. Mogą występować niewielkie różnice w interpretacji wyrażeń regularnych pomiędzy /i w match()zależności od twoich ustawień (patrz :help match()).

  • Nie mogę znaleźć sposobu, aby sprawdzić, czy aktualnie coś wyróżniamy, @/rejestr zawiera ostatnio używane wyszukiwanie, niezależnie od tego, co wyróżniamy. Zrobiłem więc remap, /aby najpierw ustawić g:searchingzmienną, aby wskazać, że wykonujemy aktywne wyszukiwanie, a wraz z <C-l>wywoływaniem :nohlsearchwyczyścić podświetlanie, i ustawić g:searchingna false, aby wskazać, że nie szukamy ...

  • Jest uruchamiany za każdym razem, gdy kursor się porusza , może nie być bardzo szybki, szczególnie w przypadku dużych plików / linii, powolnych systemów lub skomplikowanych wyrażeń regularnych (wydaje mi się, że działa dobrze).

Martin Tournoij
źródło
1

Aby wszystko było minimalne, ale nadal działa dla mnie idealnie, mam to, zainspirowane z góry: zwykłe podkreślenie, aż 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>

Teraz nnawet bez hlsearchpokazuje mi, gdzie wylądowałem, dopóki nie przesunę kursora. SpellRareSłuży do uczynienia go bardziej ovbious gdy tylko pojedyncze mecze charakter, inaczej jest to gładkiIncSearch

perelo
źródło
0

Próbowałem kilka innych odpowiedzi tutaj wymienionych i rozwiązania tutaj, ale zauważyłem, że są one rozpraszające i podatne na komunikaty o błędach. timakro napisał wtyczkę, która rozwiązuje problem i do tej pory działa dobrze dla mnie.

Jan
źródło