Чи можливо використовувати два різних кольорових фони в одному буфері vim?


20

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

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

Однак я ніколи не бачив приклад із подібними налаштуваннями.

Чи це взагалі можливо vim?


2
я дуже хотів би дізнатися відповідь на це, я б припустив, що це можливо, якщо підкреслити синтаксис цієї публікації на SO може бути доречним stackoverflow.com/questions/7033310/…
Nick J Adams

Відповіді:


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команді. Перший встановлює колір фону для GUI Vim, а другий для терміналу Vim.

Однак це має важливе обмеження, що він може встановлювати лише кольори фону для символів, які фактично існують у файлі.

Результатом цього є те, що колір фону не може поширюватися на кінець тексту на рядку до краю вікна, тому забарвлення блоків коду, показаних у вашому прикладі, неможливо:

Приклад фарбування фону можливий у Vim

Ви також можете змінити колір фону для цілих рядків за допомогою функції Sign. (Див. 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працює лише для гвіму, чи правильно?
Кароліс Концевічус

1
@Karolis Так. Для терміналу Vim потрібно використовувати ctermbg, як зазначено.
Багатий

1
Якщо ви використовуєте складки, ви отримуєте те, що хочете: складки мають інший колір bg, однак це відбувається шляхом заповнення фону символами пробілу, які мають інший набір кольорів bg ... Це спричиняє деякі побічні ефекти: копіюйте / paste більше не працюватиме належним чином (оскільки це також буде копіювати багато символів пробілу, це також можна перевірити це на собі).
Мартін Турноїй

@Rich, дякую за відповідь. Хоча це не ідеальне рішення (в частині виділення блоків), він повністю відповідає на питання, демонструючи, що це можливо. Відповідь прийнято.
Кароліс Концевічус

3
Хтось мав би бути справді божевільним, щоб написати такий сценарій.
joeytwiddle
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.