Atur warna kursor berbeda ketika pada kata yang disorot

19

Dengan colourscheme saat ini yang telah saya gunakan, sulit untuk menemukan di mana kursor diposisikan saat menavigasi melalui hasil pencarian. Warna yang disorot dan warna kursor berpadu membuat sulit untuk menemukan kursor.

Bagaimana cara mengatur warna kursor yang berbeda ketika kata itu disorot?

Tangkapan layar masalah

ma08
sumber

Jawaban:

14

Saya menggunakan cuplikan ini dari ceramah fantastis Damian Conway, More Instantly Better Vim (pada 4m 59s). Ini menyebabkan seluruh sorotan berkedip sebentar ketika Anda melompat di antara hasil pencarian.

" 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

Jika Anda ingin perubahan dalam penyorotan menjadi lebih persisten, Anda dapat mengubah ini untuk memanggil matchdeletedi waktu lain (misalnya ketika kursor bergerak).

MEMPERBARUI:

Baru-baru ini saya menulis versi yang lebih canggih ini sebagai jawaban atas pertanyaan lain. Ini memiliki perubahan berikut ::

  1. (Secara opsional) berkedip berulang kali: Versi asli Conway hanya berkedip sekali: hidup dan mati,
  2. Memungkinkan Anda menginterupsi kedipan dengan mengetik perintah lain (seperti menekan nlagi untuk melompat ke pertandingan berikutnya.) Ini memungkinkan Anda untuk mengatur waktu yang lebih lama

PEMBARUAN 2:

The vim-searchhi plugin menyediakan fitur awalnya diminta.

Kaya
sumber
Bagus sekali. Saya akan menggunakan ini dari sekarang. Saya akan mencoba menerapkan yang persisten beberapa waktu kemudian.
ma08
Apa yang dilakukan 2 baris pertama? Sejauh yang saya bisa lihat, variabel yang ditugaskan tidak digunakan, dan jika saya menghapus garis-garis itu, masih berfungsi.
Martin Tournoij
@Carpetsmoker Baris-baris itu (sekarang dihapus) adalah cruft kuno yang bagus. Jika Anda menonton ceramah, Anda akan melihat bahwa Conway tiba di solusi ini setelah beberapa iterasi. Variabel yang tidak perlu digunakan dalam variasi sebelumnya, tetapi tidak dalam variabel ini. Saya menyalinnya ke dalam .vimrc saya sebelum saya benar-benar mulai belajar vimscript, dan jelas tidak pernah melihat kode lagi, bahkan ketika menempelkannya ke jawaban saya! Terlihat dengan baik.
Kaya
Saya baru-baru ini menggantikan addon vim-pulse (saya pikir itu disebut) dengan snippet ini dan itu jauh lebih baik / lebih cepat
craigp
@ Bard Senang mendengarnya. :)
Rich
5

Berdasarkan jawaban Rich di sini dengan beberapa perbedaan:

Anda dapat menghapus sorotan dengan <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
sumber
3

Anda dapat memilih warna yang lebih baik. Cukup letakkan ini di vimrc Anda:

hi Cursor guifg=#121212 guibg=#afd700
adelarsq
sumber
Itu selalu menjadi pilihan, saya hanya mencari untuk melihat apakah mungkin untuk mengatur warna sesuai dengan konteksnya.
ma08
Saya tidak berpikir itu berguna, tetapi Anda dapat mendeteksi apakah pola pencarian (pada / atau #) sama dengan kata di bawah kursor dan mengubah sorotan Kursor
adelarsq
3

Satu-satunya cara yang dapat saya pikirkan adalah dengan menggunakan CursorMoveddan CursorMovedIautocmds, ini dipanggil setiap kali kursor dipindahkan ...

Berikut adalah beberapa kode yang melakukan hal itu:

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

Ada beberapa peringatan :

  • Ini hanya berfungsi untuk gVim, karena mengubah warna kursor tidak dimungkinkan di terminal Vim (ini adalah sesuatu yang Anda konfigurasikan di emulator terminal Anda, dan bukan sesuatu yang dapat dikendalikan Vim di sebagian besar terminal).

  • Saya tidak dapat menemukan cara yang jelas untuk memeriksa apakah karakter yang saya gunakan adalah bagian dari istilah pencarian saat ini dan / atau sedang disorot; satu-satunya cara adalah mendapatkan garis, dan regexp (lagi) dengan @/. Mungkin ada beberapa perbedaan kecil pada interpretasi regexp antara /dan match()tergantung pada pengaturan Anda (lihat :help match()).

  • Saya tidak dapat menemukan cara untuk memeriksa apakah saat ini kami sedang menyorot sesuatu, @/register berisi pencarian yang terakhir digunakan, terlepas dari apa yang kami sorot. Jadi yang saya lakukan adalah memetakan ulang /untuk mengatur g:searchingvariabel untuk mengindikasikan bahwa kami sedang melakukan pencarian aktif, dan dengan itu <C-l>kami memanggil :nohlsearchuntuk menghapus sorotan, dan mengatur g:searchingke false untuk menunjukkan bahwa kami tidak mencari ...

  • Ini dijalankan setiap kali kursor bergerak , mungkin tidak terlalu cepat terutama untuk file / baris besar, sistem lambat atau regexps yang rumit (sepertinya berfungsi baik bagi saya).

Martin Tournoij
sumber
1

Untuk menjaga hal-hal minimal, tetapi masih berfungsi dengan baik untuk saya, saya punya ini, terinspirasi dari atas: sorot polos hingga 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>

Sekarang, nbahkan tanpa hlsearchmenunjukkan kepada saya di mana saya mendarat sampai saya memindahkan kursor. Ini SpellRaredigunakan untuk membuatnya lebih ovbious ketika hanya satu karakter yang cocok, kalau tidak itu mulusIncSearch

Perelo
sumber
0

Saya mencoba beberapa jawaban lain yang tercantum di sini dan solusinya di sini tetapi menemukan mereka mengganggu dan rentan terhadap pesan kesalahan. timakro telah menulis sebuah plugin yang memecahkan masalah dan bekerja dengan baik untuk saya sejauh ini.

John
sumber