Apakah mungkin menggunakan dua latar belakang warna yang berbeda dalam satu buffer vim?

20

Saya mencari solusi yang mungkin untuk menerapkan dua warna latar belakang yang berbeda di dalam buffer vim tunggal tergantung pada konteks seperti pada contoh teks luhur ini .

Salah satu contoh penggunaannya adalah untuk memberi warna cuplikan kode di dalam file markup secara berbeda sehingga lebih menonjol.

Namun saya belum pernah melihat contoh dengan setup seperti itu.

Apakah ini mungkin dalam vim?

Karolis Koncevičius
sumber
2
ingin benar-benar mengetahui jawaban untuk ini, saya akan menyarankan bahwa mungkin dengan sintaks menyoroti posting ini di SO mungkin relevan stackoverflow.com/questions/7033310/…
Nick J Adams

Jawaban:

9

Karena saya ingin tahu seberapa bagus ini akan bekerja, saya telah meretas sesuatu bersama-sama seperti itu.

masukkan deskripsi gambar di sini

Seperti disebutkan dalam komentar pada jawaban sebelumnya, satu-satunya cara untuk melakukan ini adalah mengisi daerah dengan ruang; itulah tepatnya yang kami lakukan; sebelum menulis, kami menghapus spasi ini, jadi Anda seharusnya tidak mengganggu orang lain dengan itu.

Perhatikan bahwa contoh ini sangat spesifik untuk tipe file penurunan harga!

Efek samping :

  • Menyalin teks juga akan menyalin banyak ruang
  • Menggunakan $dan Endtidak lagi berfungsi seperti yang diharapkan (masuk ke kolom 80), dan tombol seperti jdan kjuga berperilaku berbeda.
  • Latar belakang tidak ditampilkan saat 'list'diaktifkan
  • Baris yang benar-benar kosong tidak berfungsi, Anda perlu menambahkan tab atau 4 spasi secara manual
  • ... Mungkin lebih?

Pertama, Anda perlu menambahkan ini ke ~/.vim/after/syntax/markdown.vim:

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

Anda dapat menyesuaikan warna sesuai keinginan Anda, tentu saja ;-)

Kemudian, tambahkan ini ke vimrc Anda:

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()                            

Saya tidak akan menjelaskan kode baris-demi-baris, komentar harus membuat intisari umum menjadi jelas ;-)

Martin Tournoij
sumber
Terima kasih atas jawaban ini. Saya menerimanya alih-alih jawaban awal yang diberikan oleh @Rich karena sepertinya lebih lengkap. Saya akan mencobanya tetapi tidak yakin apakah saya akan menggunakannya karena semua efek samping jadi tidak ada janji di sini :) Terima kasih banyak untuk semua usahanya!
Karolis Koncevičius
1
@ KarolisKoncevičius Terima kasih. Saya menambahkannya ke vimrc saya juga. Tampaknya bagus :-) Beritahu saya jika Anda mengalami masalah.
Martin Tournoij
Ha ha ha. Yah saya pikir ini memenuhi syarat sebagai peretasan, tapi itu tidak mengerikan seperti yang saya harapkan. Pekerjaan yang baik. Tentu saja, sekarang setelah Anda melangkah sejauh ini, tidakkah Anda merasa terdorong untuk memperbaiki masalah dengan j, k, $, dll. Dengan memetakannya kembali, dan menghapus ruang putih sebelum menarik? ;)
Kaya
2
@ Rich Ya, ini retasan. Itu membuatnya menyenangkan untuk dilakukan ;-) Memperbaiki beberapa tombol (entah bagaimana) terlintas di pikiran saya juga, tapi saya sudah menghabiskan cukup banyak waktu untuk hal ini, dan ingin pertama melihat apakah itu benar-benar berfungsi sama sekali, dan jika saya bahkan menyukainya, sebelum menghabiskan lebih banyak waktu di atasnya :-)
Martin Tournoij
2
@Carpetsmoker Nah terakhir kali saya samar-samar mengisyaratkan bahwa ada sesuatu yang mungkin Anda pergi dan berhasil, jadi saya berharap untuk melihat solusi multi-bahasa Anda yang kuat dalam beberapa minggu lagi.
Kaya
13

Tentunya dimungkinkan untuk menggunakan warna latar yang berbeda untuk elemen yang disorot sintaksis. Cukup tentukan guibgdan ctermbgwarna dalam hilightperintah Anda . Yang pertama mengatur warna latar belakang untuk GUI Vim, dan yang terakhir untuk terminal Vim.

Namun, ini memiliki batasan penting yang hanya dapat mengatur warna latar belakang untuk karakter yang sebenarnya ada dalam file.

Hasil dari ini adalah bahwa warna latar tidak dapat melampaui melewati akhir teks pada garis ke tepi jendela, sehingga pewarnaan dari blok kode yang ditunjukkan dalam contoh Anda tidak mungkin:

Contoh pewarnaan latar belakang mungkin di Vim

Anda juga dapat mengubah warna latar belakang seluruh garis menggunakan fitur Masuk. (Lihat linehldi :help sign.txt)

Contoh mewarnai latar belakang dengan tanda-tanda

Namun, perhatikan bahwa:

  1. Melakukan hal itu memerlukan kode penulisan untuk menempatkan tanda pada setiap baris yang perlu diwarnai dan tetap memperbaruinya seiring dengan perubahan isi file,

  2. Secara default, saat menempatkan tanda, kolom tanda akan ditampilkan di sebelah kiri jendela. Dimungkinkan untuk mengubah pewarnaan kolom tanda dengan SignColumngrup sorotan, dan dalam versi Vim yang lebih baru dapat dihapus seluruhnya. (Lihat :help 'signcolumn'.)

Misalnya, untuk mengadaptasi solusi Carpetsmoker untuk menggunakan mekanisme tanda (lebih kuat), Anda dapat melakukan hal berikut:

" 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()

Ini agak menyederhanakan kode, dan memiliki lebih sedikit peringatan daripada versi Carpetsmoker.

@ChristianBrabandt 's DynamicSigns Plugin membuat menggunakan fitur Masuk untuk tujuan ini lebih mudah: ia menjelaskan bagaimana menggunakannya untuk melakukannya dalam jawaban ini .

Kaya
sumber
1
+1 untuk jawaban. Namun (dan koreksi saya jika saya salah) tetapi guibghanya berfungsi untuk gvim, benarkah itu?
Karolis Koncevičius
1
@ Karolis Ya. Untuk terminal Vim, Anda perlu menggunakan ctermbg, seperti yang dinyatakan.
Kaya
1
Jika Anda menggunakan lipatan, maka Anda mendapatkan apa yang Anda inginkan: Lipatan memiliki warna bg berbeda, namun, ini dilakukan dengan mengisi latar belakang dengan karakter spasi yang memiliki set warna bg berbeda ... Ini menyebabkan beberapa efek samping: salin / paste tidak akan berfungsi dengan baik lagi (karena ini juga akan menyalin banyak karakter spasi, ini juga bagaimana Anda dapat memverifikasi ini sendiri).
Martin Tournoij
@ Rich, terima kasih atas jawabannya. Meskipun ini bukan solusi yang sempurna (dalam hal menyoroti blok) itu sepenuhnya menjawab pertanyaan yang menunjukkan bahwa ini mungkin. Jawaban diterima.
Karolis Koncevičius
3
Seseorang harus benar - benar gila untuk menulis naskah seperti itu.
joeytwiddle