Установите другой цвет курсора для выделенного слова

19

С текущей цветовой схемой, которую я использовал, трудно найти, где находится курсор при навигации по результатам поиска. Цвет выделения и цвет курсора смешиваются, что затрудняет поиск курсора.

Как установить другой цвет курсора, когда он находится на выделенном слове?

Скриншот проблемы

ma08
источник

Ответы:

14

Я использую этот фрагмент из фантастического выступления Дамиана Конвея « Больше мгновенно лучше, Вим» (в 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в другое время (например, когда курсор перемещается).

ОБНОВИТЬ:

Я недавно написал эту более продвинутую версию в ответ на другой вопрос. Имеются следующие изменения:

  1. (Дополнительно) мигает несколько раз: оригинальная версия Конвея просто мигает один раз: вкл, а затем выключен,
  2. Позволяет прерывать мигание, вводя другие команды (например, nснова нажимая для перехода к следующему совпадению). Это позволяет установить более длительное время

ОБНОВЛЕНИЕ 2:

ВИМ-searchhi плагин обеспечивает первоначально запрошенную функцию.

Богатый
источник
Прекрасно работает. Я буду использовать это с этого момента. Я постараюсь реализовать постоянный один позже.
ma08
Что делают первые 2 строки? Насколько я вижу, назначенные переменные не используются, и если я удаляю эти строки, он все еще работает.
Мартин Турной
@Carpetsmoker Эти строки (теперь удаленные) были старомодными. Если вы посмотрите доклад, вы увидите, что Конвей приходит к этому решению после нескольких итераций. Ненужные переменные использовались в более ранних вариантах, но не в этом. Я скопировал его в свой .vimrc, прежде чем я действительно начал изучать vimscript, и, очевидно, никогда больше не смотрел на код, даже когда вставлял его в свой ответ! Хорошо подмечено.
Богатый
Недавно я заменил аддон vim-pulse (кажется, он называется) на этот фрагмент, и теперь он намного лучше / быстрее
craigp
@Badger Рад это слышать. :)
Богатый
5

Основываясь на ответе Рича здесь с некоторыми отличиями:

Вы можете очистить выделение с помощью <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

Вы можете выбрать лучший цвет. Просто поместите это в свой vimrc:

hi Cursor guifg=#121212 guibg=#afd700
adelarsq
источник
Это всегда вариант, я просто смотрю, можно ли установить цвет в соответствии с контекстом.
ma08
Я не думаю, что это полезно, но вы можете определить, совпадает ли шаблон поиска (on / or #) со словом под курсором, и изменить подсветку курсора
adelarsq
3

Единственный способ, о котором я могу думать, - это использование CursorMovedи CursorMovedIautocmds, они вызываются при каждом перемещении курсора ...

Вот код, который делает именно это:

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, чтобы указать, что мы не ищем ...

  • Он запускается каждый раз, когда курсор перемещается , он может быть не очень быстрым, особенно для больших файлов / строк, медленных систем или сложных регулярных выражений (хотя мне кажется, что это работает нормально).

Мартин Турной
источник
1

Чтобы все было минимальным, но все же отлично работает для меня, у меня есть это, вдохновленное сверху: обычная подсветка до 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

perelo
источник
0

Я попробовал некоторые другие ответы, перечисленные здесь и решение здесь, но нашел их отвлекающими и склонными к сообщениям об ошибках. Тимакро написал плагин, который решает проблему и пока работает хорошо для меня.

Джон
источник