1つのvimバッファーで2つの異なる色の背景を使用できますか?


20

私はこの崇高なテキストの例のようにコンテキストに応じて単一のvimバッファ内に2つの異なる背景色を適用するための可能な解決策を探しています

その使用例の1つは、マークアップファイル内のコードスニペットに異なる色を付けて、目立つようにすることです。

しかし、私はそのようなセットアップの例を見たことはありません。

これはvimで可能ですか?


2
本当にこの答えを知っているのと同じように、私は関連している可能性がある、それは構文がSOにこのポストを強調して可能になることを示唆しているstackoverflow.com/questions/7033310/...
ニック・J・アダムス

回答:


9

これがどれだけうまくいくのか興味があったので、そのような作品を一緒にハッキングしました。

ここに画像の説明を入力してください

前の回答のコメントで述べたように、これを行う唯一の方法は、領域をスペースで埋めることです。これはまさに私たちが行うことです。書く前にこれらのスペースを削除するので、他の人に迷惑をかけないでください。

この例は、マークダウンファイルタイプに非常に限定されていることに注意してください!

副作用

  • テキストをコピーすると、多くのスペースもコピーされます
  • 使用しない$End予想されるように、もはや作品(それはコラム80になる)、およびなどのキー jkも異なる動作します。
  • '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の最初の回答ではなく、より完全に見えたので受け入れました。私はそれを試してみますが、すべての副作用のために使用するかどうかはわかりませんので、ここでは約束しません:)すべての努力に感謝します!
カロリスKoncevičius15年

1
@KarolisKoncevičiusありがとう。vimrcにも追加しました。いいようです:-)問題が発生した場合はお知らせください。
マーティントゥルノイ

ハハハ。まあ、これはハッキーと見なされると思いますが、思ったほど恐ろしくはありません。良くやった。もちろん、ここまで進んだところで、j、k、$などの問題をリマップすることで修正し、ヤンクする前に空白を削除する必要がありますか?;)
リッチ

2
@リッチええ、それはハックです。それは楽しいことでした;-)いくつかのキーを修正することは(どういうわけか)私の頭をも横切りましたが、私はすでにこれにかなりの時間を費やし、実際にそれが実際に動作するかどうか、そして私がさらにそれを過ごす前に、それのように:
マーティントゥルノイ

2
@Carpetsmokerさて、前回あなたがどこかに行ってそれを作った可能性があることを漠然とほのめかしたので、数週間以内にあなたの堅牢な多言語ソリューションを見ることを楽しみにしています。
リッチ

13

構文が強調表示された要素に異なる背景色を使用することは確かに可能です。コマンドで色guibgctermbg色を定義するだけhilightです。前者はGUI 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のバージョンよりも警告が少なくなります。

@ChristianBrabandtDynamicSignsプラグインは、この目的のために署名機能をより簡単に使用できるようにします


1
答えは+1。しかし(そして私が間違っている場合は私を修正します)、guibggvimでのみ動作します、そうですか?
カロリスKoncevičius15年

1
@カロリスはい。ターミナルVimの場合ctermbg、前述のようにを使用する必要があります。
リッチ

1
折り畳みを使用すると、目的のものが得られます:折り畳みは異なるbg色を持ちますが、これは異なるbg色セットを持つスペース文字で背景を塗りつぶすことで実現されます...これはいくつかの副作用を引き起こします: / pasteは正しく機能しなくなります(多くのスペース文字もコピーされるため、これは自分で確認する方法でもあります)。
マーティントゥルノイ

@リッチ、答えてくれてありがとう。(ブロックを強調表示するという点では)完全なソリューションではありませんが、これが可能であることを示す質問に完全に答えます。回答が受け入れられました。
カロリスKoncevičius15年

3
そのようなスクリプトを書くには、誰かが本当に夢中にならなければならないでしょう。
joeytwiddle
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.