我正在寻找一种可能的解决方案,具体取决于上下文,例如在此sublime文本示例中,在单个vim缓冲区中应用两种不同的背景颜色。

一种用例是对标记文件中的代码片段进行不同的颜色编码因此它们更加突出。

但是我从未见过这样的设置示例。

在vim中这是否有可能?

评论

我真的很想知道答案,所以我建议通过语法突出显示SO上的帖子可能是有可能的stackoverflow.com/questions/7033310/…

#1 楼

因为我很好奇它的工作原理,所以我一起破解了一些东西。



如之前的评论中所述答案,唯一的方法是
用空格填充区域;这正是我们所做的;在写之前,我们
删除这些空格,因此您不应该为此而烦扰其他人。

请注意,此示例非常适合markdown文件类型!

副作用:


复制文本还会复制很多空格
使用$和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\)\(.\{-}\)\( *\)$//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给出的最初答案,因为它似乎更完整。我会尝试一下,但是由于所有副作用我不确定是否会使用它,所以在这里不做承诺:)大谢谢您所做的一切!

– KarolisKoncevičius
2015年2月25日在17:43

@KarolisKoncevičius谢谢。我也将其添加到了vimrc中。看起来不错:-)如果您遇到问题,请告诉我。

–马丁·图尔诺伊(Martin Tournoij)
2015年2月25日在18:00



哈哈哈好吧,我认为这可算是骇人听闻的,但是还不如我所料。不错的工作。当然,既然您已经走了这么远,您是否不感到被迫通过重新映射来解决j,k,$等问题,并在拉动之前删除了空白? ;)

–丰富
2015年2月25日在21:32



@Rich是的,这是一个hack。这使它变得很有趣;-)修复一些键(以某种方式)也使我心烦,但是我已经花了很多时间在此上,并且想首先看看它是否真的起作用,以及是否我甚至喜欢它,然后再花更多的时间:-)

–马丁·图尔诺伊(Martin Tournoij)
2015年2月25日在21:34



@Carpetsmoker好吧,我上次模糊地暗示您可能离开并成功了,所以我希望在接下来的几周内看到您强大的多语言解决方案。

–丰富
15年2月26日在8:14

#2 楼

对于语法突出显示的元素,当然可以使用其他背景色。只需在guibg命令中定义ctermbghilight颜色即可。前者为GUI Vim设置背景颜色,而后者为终端Vim设置。

但是,它有一个重要的限制,即它只能为文件中实际存在的字符设置背景颜色。 br />
这样做的结果是背景色不能延伸超过一行文本的末端到窗口的边缘,因此无法为示例中的代码块着色:



还可以使用“符号”功能更改整个行的背景颜色。 (请参阅linehl中的:help sign.txt)这行需要着色,并在文件内容更改时保持更新。
默认情况下,放置标志时,标志列将显示在窗口的左侧。可以使用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的DynamicSigns插件使为此目的使用Sign功能更加容易:他在此答案中描述了如何使用它。 。

评论


+1为答案。但是(如果我错了,请纠正我),但是guibg仅适用于gvim,对吗?

– KarolisKoncevičius
2015年2月5日,14:35

@Karolis是的。对于终端Vim,您需要使用ctermbg,如前所述。

–丰富
2015年2月5日在14:38

如果使用折叠,则可以得到想要的结果:折叠具有不同的bg颜色,但是,这是通过在背景中填充具有不同bg颜色设置的空格字符来实现的。这会产生一些副作用:复制/ paste无法正常工作(因为它还会复制很多空格字符,这也是您可以自己验证的方式)。

–马丁·图尔诺伊(Martin Tournoij)
2015年2月5日15:11



@Rich,谢谢您的回答。尽管这不是一个完美的解决方案(以高亮显示块),但它完全回答了表明这是可能的问题。答案已接受。

– KarolisKoncevičius
2015年2月6日在13:32

编写这样的脚本必须有人真的很疯狂。

– joeytwiddle
15年2月26日在8:04