Có thể sử dụng hai nền màu khác nhau trong một bộ đệm vim không?


20

Tôi đang tìm kiếm một giải pháp khả thi cho việc áp dụng hai màu nền khác nhau trong một bộ đệm vim duy nhất tùy thuộc vào ngữ cảnh như trong ví dụ văn bản tuyệt vời này .

Một trường hợp sử dụng đó là các đoạn mã màu bên trong các tệp đánh dấu khác nhau để chúng nổi bật hơn.

Tuy nhiên tôi chưa bao giờ thấy một ví dụ với một thiết lập như vậy.

Đây có phải là tất cả có thể trong vim?


2
thực sự muốn biết câu trả lời cho điều này, tôi sẽ đề nghị rằng nó sẽ có thể với cú pháp làm nổi bật bài này trên SO có thể liên quan stackoverflow.com/questions/7033310/...
Nick J Adams

Câu trả lời:


9

Bởi vì tôi tò mò việc này sẽ hoạt động tốt như thế nào, tôi đã hack một thứ gì đó cùng loại đó.

nhập mô tả hình ảnh ở đây

Như đã đề cập trong các ý kiến ​​về câu trả lời trước đó, cách duy nhất để làm điều này là lấp đầy các vùng bằng khoảng trắng; đó chính xác là những gì chúng ta làm; trước khi viết, chúng tôi xóa các khoảng trắng này, vì vậy bạn không nên làm phiền bất kỳ ai khác với nó.

Lưu ý rằng ví dụ này rất cụ thể cho kiểu đánh dấu!

Tác dụng phụ :

  • Sao chép văn bản cũng sẽ sao chép rất nhiều khoảng trắng
  • Sử dụng $Endkhông còn hoạt động như mong đợi (nó đi đến cột 80) và các phím như jkcũng hoạt động khác nhau.
  • Nền không được hiển thị khi 'list'được bật
  • Các dòng trống hoàn toàn không hoạt động, bạn cần thêm thủ công một tab hoặc 4 khoảng trắng
  • ... Có lẽ nhiều hơn?

Trước tiên, bạn cần thêm phần này vào ~/.vim/after/syntax/markdown.vim:

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

Tất nhiên, bạn có thể điều chỉnh màu sắc theo ý thích của mình ;-)

Sau đó, thêm phần này vào vimrc của bạn:

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

Tôi sẽ không giải thích từng dòng mã, các ý kiến ​​sẽ làm cho ý chính chung của nó rõ ràng ;-)


Cảm ơn câu trả lời này. Tôi đã chấp nhận nó thay vì câu trả lời ban đầu được đưa ra bởi @Rich vì nó có vẻ đầy đủ hơn. Tôi sẽ dùng thử nhưng không chắc là tôi sẽ sử dụng nó vì tất cả các tác dụng phụ nên không có lời hứa nào ở đây :) Cảm ơn rất nhiều vì tất cả nỗ lực!
Karolis Koncevičius

1
@ KarolisKoncevičius Cảm ơn. Tôi đã thêm nó vào vimrc của tôi. Có vẻ tốt :-) Hãy cho tôi biết nếu bạn gặp vấn đề.
Martin Tournoij

Hahaha. Vâng, tôi nghĩ rằng điều này đủ điều kiện là hacky, nhưng nó không khủng khiếp như tôi mong đợi. Công việc tốt. Tất nhiên, bây giờ bạn đã đi xa đến mức này, bạn không cảm thấy bắt buộc phải khắc phục các vấn đề với j, k, $, v.v. bằng cách ánh xạ lại chúng và xóa khoảng trắng trước khi kéo dài? ;)
Giàu

2
@Rich Vâng, đó là một hack. Điều đó làm cho nó trở nên thú vị ;-) Việc sửa một số phím (bằng cách nào đó) cũng xuất hiện trong đầu tôi, nhưng tôi đã dành khá nhiều thời gian cho việc này, và trước tiên muốn xem liệu nó có thực sự hoạt động không, và nếu tôi thậm chí thích nó, trước khi dành nhiều thời gian hơn cho nó :-)
Martin Tournoij

2
@Carpetsmoker Lần cuối cùng tôi mơ hồ nói bóng gió rằng có thể bạn đã bỏ đi và làm nó, vì vậy tôi mong được thấy giải pháp đa ngôn ngữ mạnh mẽ của bạn trong vài tuần nữa.
Giàu

13

Chắc chắn có thể sử dụng màu nền khác cho các yếu tố được tô sáng theo cú pháp. Chỉ cần xác định guibgctermbgmàu sắc trong hilightlệnh của bạn . Cái trước đặt màu nền cho GUI Vim và cái sau cho terminal Vim.

Tuy nhiên, điều này có giới hạn quan trọng là nó chỉ có thể đặt màu nền cho các ký tự thực sự tồn tại trong tệp.

Kết quả của điều này là màu nền không thể kéo dài qua phần cuối của văn bản trên một dòng đến cạnh của cửa sổ, do đó không thể tô màu các khối mã được hiển thị trong ví dụ của bạn:

Một ví dụ về màu nền có thể có trong Vim

Bạn cũng có thể thay đổi màu nền của toàn bộ dòng bằng tính năng Dấu. (Xem linehltrong :help sign.txt)

Một ví dụ về tô màu nền với các dấu hiệu

Tuy nhiên, lưu ý rằng:

  1. Làm như vậy đòi hỏi phải viết mã để đặt các dấu hiệu trên mỗi dòng cần được tô màu và giữ cho các cập nhật này khi nội dung của tệp thay đổi,

  2. Theo mặc định, khi đặt một dấu hiệu, cột dấu hiệu sẽ được hiển thị ở bên trái của cửa sổ. Có thể thay đổi màu của cột ký hiệu với SignColumnnhóm tô sáng và trong các phiên bản gần đây hơn của Vim, nó có thể được loại bỏ hoàn toàn. (Xem :help 'signcolumn'.)

Ví dụ: để điều chỉnh giải pháp của Carpetsmoker để sử dụng cơ chế ký hiệu (mạnh mẽ hơn), bạn có thể làm như sau:

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

Điều này đơn giản hóa phần nào mã và có ít cảnh báo hơn phiên bản của Carpetsmoker.

Plugin DynamicSigns của @ChristianBrabandt làm cho việc sử dụng tính năng Dấu hiệu cho mục đích này dễ dàng hơn: anh mô tả cách sử dụng nó để làm như vậy trong câu trả lời này .


1
+1 cho câu trả lời. Tuy nhiên (và sửa tôi nếu tôi sai) nhưng guibgchỉ hoạt động cho gvim, điều đó có đúng không?
Karolis Koncevičius

1
@Karolis Có. Đối với thiết bị đầu cuối Vim bạn cần sử dụng ctermbg, như đã nêu.
Giàu

1
Nếu bạn sử dụng các nếp gấp, thì bạn sẽ có được những gì bạn muốn: Các nếp gấp có màu bg khác nhau, tuy nhiên, điều này được thực hiện bằng cách điền vào nền với các ký tự khoảng trắng có bộ màu bg khác ... Điều này gây ra một số hiệu ứng phụ: sao chép / dán sẽ không hoạt động chính xác nữa (vì nó cũng sẽ sao chép rất nhiều ký tự khoảng trắng, đây cũng là cách bạn có thể tự xác minh điều này).
Martin Tournoij

@Rich, cảm ơn vì câu trả lời. Mặc dù nó không phải là một giải pháp hoàn hảo (về mặt làm nổi bật các khối), nó hoàn toàn trả lời câu hỏi chứng minh rằng điều này là có thể. Trả lời Được chấp nhận.
Karolis Koncevičius 6/2/2015

3
Ai đó sẽ phải thực sự điên rồ để viết một kịch bản như vậy.
joeytwiddle
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.