Можно ли использовать два разных цветовых фона в одном буфере vim?

20

Я ищу возможное решение для применения двух разных цветов фона внутри одного буфера vim в зависимости от контекста, как в этом примере возвышенного текста .

Один из вариантов использования - по-разному раскрасить фрагменты кода внутри файлов разметки, чтобы они выделялись больше.

Однако я никогда не видел пример с такой установкой.

Это вообще возможно в vim?

Каролис Концевичюс
источник
2
очень хотел бы знать ответ на этот вопрос, я хотел бы предположить, что это будет возможно с выделением синтаксиса, этот пост на SO может быть актуален stackoverflow.com/questions/7033310/…
Ник Дж. Адамс

Ответы:

9

Поскольку мне было любопытно, насколько хорошо это будет работать, я взломал что-то подобное.

введите описание изображения здесь

Как упоминалось в комментариях к предыдущему ответу, единственный способ сделать это - заполнить регионы пробелами; именно это мы и делаем; перед тем как написать, мы удалим эти пробелы, поэтому вам не следует беспокоить кого-либо еще.

Обратите внимание, что этот пример очень специфичен для типа файла уценки!

Побочные эффекты :

  • Копирование текста также скопирует много пробелов
  • Использование $и Endбольше не работает должным образом (это относится к столбцу 80), а ключи, такие как jи, kведут себя по-другому.
  • Фон не отображается, когда 'list'включен
  • Полностью пустые строки не работают, вам нужно вручную добавить табуляцию или 4 пробела
  • ... может быть, еще?

Во-первых, вам нужно добавить это в ваш ~/.vim/after/syntax/markdown.vim:

syn clear markdownCodeBlock                                                 
syn region markdownCodeBlock start="    \|\t" end="$"                       
hi def markdownCodeBlock ctermbg=230 guibg=lightyellow                      

Вы можете настроить цвета по своему вкусу, конечно ;-)

Затем добавьте это в ваш vimrc:

fun! MarkdownBlocks()                                                       
    fun! s:fill(line)                                                       
        " Remove all trailing whitespace                                    
        let l:line = substitute(a:line, " *$", "", "")                      

        " Add trailing whitespace up to 'textwidth' length                  
        return l:line . repeat(' ', (&tw > 0 ? &tw : 80) - strdisplaywidth(l:line))
    endfun                                                                  

    " Get all lines in a list                                               
    let l:lines = getline(1, line('$'))                                     

    " Map s:fill() to the lines that are a code block                       
    call map(l:lines, 'v:val[0] == "\t" || v:val[:3] == "    " ? s:fill(v:val) : v:val')

    " Reset the buffer to the lines                                         
    call setline(1, l:lines)                                                
endfun                                                                      

" Remove all the trailing spaces                                            
fun! MarkdownBlocksClean()                                                  
    let l:save_cursor = getpos(".")                                         
    silent %s/^\(    \|\t\)\(.\{-}\)\( *\)$/\1\2/e                          
    call setpos('.', l:save_cursor)                                         
endfun                                                                      
au BufWritePre *.markdown call MarkdownBlocksClean()                        

" Set spaces on loading the file, leaving insert mode, and after writing it 
au FileType markdown call MarkdownBlocks()                                  
au InsertLeave *.markdown call MarkdownBlocks()                             
au BufWritePost *.markdown call MarkdownBlocks()                            

Я не собираюсь объяснять код построчно, комментарии должны прояснить общую суть ;-)

Мартин Турной
источник
Спасибо за этот ответ. Я принял его вместо первоначального ответа, данного @Rich, потому что он казался более полным. Я попробую это, но не уверен, буду ли я использовать это из-за всех побочных эффектов, так что не обещайте здесь :) Большое спасибо за все усилия!
Каролис Концевичюс
1
@ KarolisKoncevičius Спасибо. Я добавил это в мой vimrc также. Это кажется хорошим :-) Дайте мне знать, если у вас возникнут проблемы.
Мартин Турной
Хахаха. Ну, я думаю, что это считается хакерским, но это не так ужасно, как я ожидал. Хорошая работа. Конечно, теперь, когда вы зашли так далеко, вы не чувствуете себя обязанным исправить проблемы с j, k, $ и т. Д., Переназначив их, и убрав пробел перед тем, как дергать? ;)
Богатый
2
@Rich Да, это взломать. Это было забавно ;-) Исправление некоторых клавиш (как-то) тоже пришло мне в голову, но я уже потратил немало времени на это и хочу сначала посмотреть, работает ли он вообще, и если я даже нравится, прежде чем тратить на это еще больше времени :-)
Мартин Турной
2
@Carpetsmoker Ну, в прошлый раз, когда я смутно намекнул, что что-то может быть возможно, вы ушли и сделали это, поэтому я с нетерпением жду возможности увидеть ваше надежное многоязычное решение через пару недель.
Богатый
13

Конечно, можно использовать другой цвет фона для выделенных синтаксисом элементов. Просто определите guibgи ctermbgцвета в вашей hilightкоманде. Первый устанавливает цвет фона для графического интерфейса Vim, а второй - для терминала Vim.

Однако это имеет важное ограничение: он может устанавливать цвета фона только для символов, которые фактически существуют в файле.

Результатом этого является то, что цвет фона не может простираться за конец текста на линии до края окна, поэтому раскраска блоков кода, показанная в вашем примере, невозможна:

Пример окраски фона возможен в Vim

Вы также можете изменить цвет фона целых линий, используя функцию подписи. (См. linehlВ :help sign.txt)

Пример раскраски фона знаками

Однако обратите внимание, что:

  1. Это требует написания кода для размещения знаков в каждой строке, которая должна быть окрашена, и их обновления по мере изменения содержимого файла,

  2. По умолчанию при размещении знака столбец знака будет отображаться в левой части окна. Можно изменить окраску столбца знака с группой SignColumnподсветки, и в более поздних версиях Vim ее можно полностью удалить. (См :help 'signcolumn'.)

Например, чтобы адаптировать решение Carpetsmoker для использования (более надежного) механизма подписи, вы можете сделать следующее:

" Define a highlight group and a sign that uses it
highlight default markdownCodeBlock ctermbg=230 guibg=lightyellow
sign define codeblock linehl=markdownCodeBlock

" Use signs to highlight code blocks
function! MarkdownBlocks()
    function! s:applySign(idx, val)
        if a:val[0] == "\t" || a:val[:3] == "    "
            let l = a:idx + 1
            execute "sign place " . l . " line=" . l . " name=codeblock file=" . expand("%:p")
        endif
    endfunction

    " Remove old signs
    execute "sign unplace * file=" . expand("%:p")

    " Get all lines in a list
    let l:lines = getline(1, line('$'))
    " Add new signs
    call map(l:lines, function('s:applySign'))
endfunction

" Set signs on loading the file, leaving insert mode, and after writing it
au FileType markdown call MarkdownBlocks()
au InsertLeave *.markdown call MarkdownBlocks()
au BufWritePost *.markdown call MarkdownBlocks()

Это несколько упрощает код и имеет меньше предостережений, чем версия Carpetsmoker.

@ChristianBrabandt «s DynamicSigns плагин делает с помощью функции Sign для этой цели проще: он описывает , как использовать его , чтобы сделать это в этом ответе .

Богатый
источник
1
+1 за ответ. Однако (и поправьте меня, если я ошибаюсь), но guibgработает только на gvim, это правильно?
Каролис Концевичюс
1
@ Каролис Да. Для терминала Vim вам необходимо использовать ctermbg, как указано.
Богатый
1
Если вы используете сгибы, то вы получаете то, что хотите: складки имеют другой цвет bg, однако это достигается путем заполнения фона пробелами, для которых установлен другой цвет bg ... Это вызывает некоторые побочные эффекты: copy / paste больше не будет работать должным образом (так как он также скопирует много пробелов, это также как вы можете проверить это самостоятельно).
Мартин Турной
@Rich, спасибо за ответ. Хотя это не идеальное решение (с точки зрения выделения блоков), оно полностью отвечает на вопрос, демонстрирующий, что это возможно. Ответ принят.
Каролис Концевичюс
3
Кто-то должен быть действительно сумасшедшим, чтобы написать такой сценарий.
Joeytwiddle