하나의 vim 버퍼에 두 가지 다른 색 배경을 사용할 수 있습니까?


20

이 숭고한 텍스트 예제와 같은 컨텍스트에 따라 단일 vim 버퍼 안에 두 개의 다른 배경색을 적용하는 가능한 솔루션을 찾고 있습니다.

그 중 하나의 사용 사례는 마크 업 파일 내부의 코드 조각을 다르게 색상 화하여 더 두드러지게 만드는 것입니다.

그러나 나는 그런 설정으로 예제를 보지 못했습니다.

이것은 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의 초기 답변 대신 더 완벽 해 보였으므로 받아 들였습니다. 나는 그것을 시도하지만 모든 부작용 때문에 그것을 사용할 것인지 확실하지 않으므로 여기에 약속이 없습니다 :) 큰 모든 노력에 감사드립니다!
Karolis Koncevičius

1
@ KarolisKoncevičius 감사합니다. 나는 그것을 vimrc에도 추가했다. 좋은 것 같습니다 :-) 문제가 발생하면 알려주십시오.
Martin Tournoij

하하하 글쎄, 나는 이것이 해키처럼 자격이 있다고 생각하지만, 예상만큼 끔찍한 것은 아닙니다. 좋은 작업. 물론, 지금까지 나아 갔으므로 j, k, $ 등의 문제를 다시 매핑하여 수정하고 얀킹하기 전에 공백을 제거해야한다고 생각하지 않습니까? ;)
Rich

2
@Rich 그래, 해킹이야. ;-) 일부 키를 수정하면 (어쨌든) 내 마음을 넘어갔지 만 이미 이것에 꽤 많은 시간을 보냈으며 실제로 실제로 작동하는지 확인하고 싶습니다. 그 것처럼, 그것에 더 많은 시간을 보내기 전에 :-)
Martin Tournoij

2
@Carpetsmoker 글쎄, 지난 번에 나는 당신이 사라져서 그것을 만들 수 있다는 것을 모호하게 암시 했으므로 다른 몇 주 안에 강력한 다국어 솔루션을 기대합니다.
Rich

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 플러그인은 이러한 목적으로 Sign 기능을보다 쉽게 ​​사용할 수있게 해줍니다. 이 답변 에서 이를 사용하는 방법을 설명합니다 .


1
답변 +1 그러나 (그리고 내가 틀렸다면 나를 교정하십시오.)하지만 guibggvim에서만 작동합니다.
Karolis Koncevičius

1
@Karolis 예. 터미널 Vim의 경우 ctermbg명시된 대로을 사용해야합니다 .
Rich

1
접기를 사용하면 원하는 것을 얻을 수 있습니다. 접기에는 다른 bg 색상이 있지만, 배경에 다른 bg 색상 세트가있는 공백 문자로 배경을 채워서 수행됩니다. 이로 인해 몇 가지 부작용이 발생합니다. / paste는 더 이상 제대로 작동하지 않습니다 (많은 공백 문자도 복사하므로이를 직접 확인할 수 있습니다).
Martin Tournoij

@Rich, 답변 주셔서 감사합니다. 블록을 강조하는 관점에서 완벽한 솔루션은 아니지만 이것이 가능하다는 것을 보여주는 질문에 완전히 대답합니다. 답변이 수락되었습니다.
Karolis Koncevičius

3
그런 스크립트를 작성 하려면 누군가가 정말 미쳐야 할 것입니다.
joeytwiddle
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.