Ist es möglich, zwei verschiedene Farbhintergründe in einem einzigen VIM-Puffer zu verwenden?

20

Ich suche nach einer möglichen Lösung für das Anwenden von zwei verschiedenen Hintergrundfarben in einem einzelnen Vim-Puffer, abhängig vom Kontext, wie in diesem hervorragenden Textbeispiel .

Ein Anwendungsfall besteht darin, Codeausschnitte in Markup-Dateien anders zu färben, damit sie besser zur Geltung kommen.

Ich habe jedoch noch nie ein Beispiel mit einem solchen Setup gesehen.

Ist das überhaupt in vim möglich?

Karolis Koncevičius
quelle
2
würde wirklich gerne die Antwort auf diese wissen, würde ich vorschlagen , dass es möglich sein wird , mit Syntax - Beitrag auf SO Hervorhebung von Bedeutung sein kann stackoverflow.com/questions/7033310/...
Nick J Adams

Antworten:

9

Weil ich neugierig war, wie gut das funktionieren würde, habe ich so etwas zusammen gehackt.

Bildbeschreibung hier eingeben

Wie in den Kommentaren zur früheren Antwort erwähnt, besteht die einzige Möglichkeit darin, Regionen mit Leerzeichen zu füllen. was ist genau das, was wir tun; Bevor Sie schreiben, entfernen wir diese Leerzeichen, sodass Sie niemanden damit belästigen sollten.

Beachten Sie, dass dieses Beispiel sehr spezifisch für den Abschriften-Dateityp ist!

Nebenwirkungen :

  • Beim Kopieren von Text werden auch viele Leerzeichen kopiert
  • Die Verwendung von $und Endfunktioniert nicht mehr wie erwartet (siehe Spalte 80), und Tasten wie jund kverhalten sich ebenfalls anders.
  • Der Hintergrund wird nicht angezeigt, wenn 'list'aktiviert ist
  • Völlig leere Zeilen funktionieren nicht, Sie müssen manuell einen Tabulator oder 4 Leerzeichen hinzufügen
  • ... vielleicht mehr?

Zuerst müssen Sie dies zu Ihrem hinzufügen ~/.vim/after/syntax/markdown.vim:

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

Sie können die Farben natürlich nach Ihren Wünschen anpassen ;-)

Dann fügen Sie dies zu Ihrem vimrc hinzu:

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

Ich werde den Code nicht Zeile für Zeile erklären, die Kommentare sollten den allgemeinen Kern klarstellen ;-)

Martin Tournoij
quelle
Danke für diese Antwort. Ich akzeptierte es anstelle der ursprünglichen Antwort von @Rich, weil es vollständiger schien. Ich werde es ausprobieren, aber ich bin mir nicht sicher, ob ich es aufgrund der Nebenwirkungen verwenden werde, also hier kein Versprechen :) Vielen Dank für die Mühe!
Karolis Koncevičius
1
@ KarolisKoncevičius Danke. Ich habe es auch zu meinem vimrc hinzugefügt. Es scheint schön :-) Lass es mich wissen, wenn du auf Probleme stößt.
Martin Tournoij,
Hahaha. Nun, ich denke, das wird als hacky eingestuft, aber es ist nicht so schrecklich, wie ich erwartet hatte. Gute Arbeit. Natürlich, jetzt, wo Sie so weit gekommen sind, fühlen Sie sich nicht gezwungen, die Probleme mit j, k, $ usw. zu beheben, indem Sie sie neu zuordnen und den Leerraum vor dem Ruckeln entfernen? ;)
Rich
2
@Rich Ja, es ist ein Hack. Das hat Spaß gemacht ;-) Es ist mir auch (irgendwie) in den Sinn gekommen, einige der Schlüssel zu reparieren, aber ich habe bereits eine ganze Weile damit verbracht und möchte zuerst sehen, ob es überhaupt funktioniert und ob ich
Ich
2
@Carpetsmoker Nun, das letzte Mal, als ich vage angedeutet habe, dass etwas möglich sein könnte, sind Sie fortgegangen und haben es geschafft, also freue ich mich darauf, Ihre robuste mehrsprachige Lösung in ein paar weiteren Wochen zu sehen.
Rich
13

Es ist durchaus möglich, für syntaktisch hervorgehobene Elemente eine andere Hintergrundfarbe zu verwenden. Definieren Sie einfach die guibgund ctermbgFarben in Ihrem hilightBefehl. Ersteres legt die Hintergrundfarbe für GUI Vim und letzteres für Terminal Vim fest.

Dies hat jedoch die wichtige Einschränkung, dass nur die Hintergrundfarben für Zeichen festgelegt werden können, die tatsächlich in der Datei vorhanden sind.

Dies hat zur Folge, dass sich die Hintergrundfarbe nicht über das Ende des Texts in einer Zeile bis zum Fensterrand erstrecken kann. Daher ist die Färbung der in Ihrem Beispiel gezeigten Codeblöcke nicht möglich:

Ein Beispiel für die in Vim mögliche Hintergrundfärbung

Sie können auch die Hintergrundfarbe ganzer Linien mit der Funktion „Signieren“ ändern. (Siehe linehlin :help sign.txt)

Ein Beispiel für die Färbung des Hintergrunds mit Zeichen

Beachten Sie jedoch Folgendes:

  1. Dazu muss Code geschrieben werden, um Zeichen in jede Zeile zu setzen, die gefärbt werden müssen, und diese müssen aktualisiert werden, wenn sich der Inhalt der Datei ändert.

  2. Standardmäßig wird beim Platzieren eines Zeichens die Zeichenspalte links im Fenster angezeigt. Es ist möglich, die Farbe der Zeichenspalte mit der Markierungsgruppe zu ändern SignColumn, und in neueren Versionen von Vim kann sie vollständig entfernt werden. (Siehe :help 'signcolumn'.)

Um beispielsweise die Carpetsmoker-Lösung so anzupassen , dass sie den ( stabileren ) Zeichenmechanismus verwendet, können Sie Folgendes tun:

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

Dies vereinfacht den Code etwas und hat weniger Einschränkungen als die Carpetsmoker-Version.

@ChristianBrabandt ‚s DynamicSigns Plugin die Sign - Funktion für diesen Zweck macht die Verwendung einfacher: Er beschreibt , wie es so in tun , verwendet diese Antwort .

Reich
quelle
1
+1 für eine Antwort. Allerdings (und korrigiere mich, wenn ich falsch guibgliege ), funktioniert aber nur für gvim, ist das richtig?
Karolis Koncevičius
1
@ Karolis Ja. Für das Terminal Vim müssen Sie ctermbgwie angegeben verwenden.
Rich
1
Wenn Sie Falten verwenden, erhalten Sie, was Sie wollen: Die Falten haben eine andere Hintergrundfarbe, dies wird jedoch erreicht, indem der Hintergrund mit Leerzeichen gefüllt wird, die eine andere Hintergrundfarbe haben ... Dies verursacht einige Nebenwirkungen: Kopieren / paste funktioniert nicht mehr richtig (da es auch viele Leerzeichen kopiert, können Sie dies auch selbst überprüfen).
Martin Tournoij
@Rich, danke für die Antwort. Es ist zwar keine perfekte Lösung (in Bezug auf das Hervorheben von Blöcken), aber es beantwortet die Frage, die zeigt, dass dies möglich ist, vollständig. Antwort akzeptiert.
Karolis Koncevičius
3
Jemand müsste wirklich verrückt sein, um ein solches Skript zu schreiben.
Joeytwiddle