È possibile utilizzare due sfondi di colore diverso in un unico buffer vim?


20

Sto cercando una possibile soluzione per applicare due diversi colori di sfondo all'interno di un singolo buffer vim a seconda del contesto come in questo sublime esempio di testo .

Un caso d'uso è quello di colorare in modo diverso i frammenti di codice all'interno dei file di markup in modo che risaltino maggiormente.

Tuttavia non ho mai visto un esempio con una configurazione del genere.

Tutto ciò è possibile in vim?


2
mi piacerebbe davvero sapere la risposta a questo, suggerirei che sarà possibile con l'evidenziazione della sintassi che questo post su SO possa essere rilevante stackoverflow.com/questions/7033310/…
Nick J Adams,

Risposte:


9

Dato che ero curioso di sapere come avrebbe funzionato, ho hackerato qualcosa insieme in quel tipo di opere.

inserisci qui la descrizione dell'immagine

Come menzionato nei commenti sulla risposta precedente, l'unico modo per farlo è riempire le aree di spazi; che è esattamente quello che facciamo; prima di scrivere, rimuoviamo questi spazi, quindi non dovresti disturbare nessun altro.

Nota che questo esempio è molto specifico per il tipo di file markdown!

Effetti collaterali :

  • La copia del testo copierà anche molti spazi
  • L'uso $e Endnon funziona più come previsto (va alla colonna 80), e tasti come je kanche comportarsi diversamente.
  • Lo sfondo non viene visualizzato quando 'list'è abilitato
  • Le righe completamente vuote non funzionano, è necessario aggiungere manualmente una scheda o 4 spazi
  • ... Forse di più?

Innanzitutto, devi aggiungere questo al tuo ~/.vim/after/syntax/markdown.vim:

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

Puoi regolare i colori a tuo piacimento, ovviamente ;-)

Quindi, aggiungi questo al tuo 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()                            

Non ho intenzione di spiegare il codice riga per riga, i commenti dovrebbero chiarire l'essenza generale ;-)


Grazie per questa risposta L'ho accettato invece della risposta iniziale data da @Rich perché sembrava più completa. Lo proverò ma non sono sicuro che lo userò a causa di tutti gli effetti collaterali, quindi nessuna promessa qui :) Grande grazie per tutto lo sforzo!
Karolis Koncevičius,

1
@ KarolisKoncevičius Grazie. L'ho aggiunto anche al mio vimrc. Sembra carino :-) Fammi sapere se riscontri problemi.
Martin Tournoij,

Hahaha. Beh, penso che questo si qualifichi come hacky, ma non è così orribile come mi aspettavo. Bel lavoro. Certo, ora che sei andato così lontano, non ti senti obbligato a risolvere i problemi con j, k, $, ecc. Rimappandoli e rimuovendo lo spazio bianco prima di strappare? ;)
Ricco

2
@Rich Sì, è un trucco. È stato divertente farlo ;-) Risolvere anche alcuni dei tasti (in qualche modo) mi è passato per la testa, ma ho già trascorso un bel po 'di tempo su questo, e voglio prima vedere se funziona davvero, e se io mi piace, prima di passare ancora più tempo su di esso :-)
Martin Tournoij,

2
@Carpetsmoker Beh, l'ultima volta che ho vagamente accennato che qualcosa potrebbe essere possibile sei andato via e l'hai fatto, quindi non vedo l'ora di vedere la tua solida soluzione multilingue in un'altra coppia di settimane.
Ricco il

13

È certamente possibile utilizzare un colore di sfondo diverso per gli elementi evidenziati dalla sintassi. Basta definire i colori guibge ctermbgnel tuo hilightcomando. Il primo imposta il colore di sfondo per GUI Vim e il secondo per il terminale Vim.

Tuttavia, questo ha l'importante limitazione che può solo impostare i colori di sfondo per i caratteri che esistono effettivamente nel file.

Il risultato di ciò è che il colore di sfondo non può estendersi oltre la fine del testo su una linea fino al bordo della finestra, quindi la colorazione dei blocchi di codice mostrati nel tuo esempio non è possibile:

Un esempio della colorazione di sfondo possibile in Vim

Puoi anche cambiare il colore di sfondo di intere linee usando la funzione Firma. (Vedi linehlin :help sign.txt)

Un esempio di colorazione dello sfondo con segni

Tuttavia, si noti che:

  1. Ciò richiede la scrittura di codice per posizionare i segni su ogni riga che deve essere colorata e mantenerli aggiornati quando il contenuto del file cambia,

  2. Per impostazione predefinita, quando si posiziona un segno, la colonna del segno verrà visualizzata a sinistra della finestra. È possibile modificare la colorazione della colonna dei segni con il SignColumngruppo di evidenziazione e nelle versioni più recenti di Vim può essere rimossa completamente. (Vedi :help 'signcolumn'.)

Ad esempio, per adattare la soluzione di Carpetsmoker all'utilizzo del meccanismo (più robusto) dei segni, è possibile effettuare le seguenti operazioni:

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

Questo semplifica un po 'il codice e presenta meno avvertenze rispetto alla versione di Carpetsmoker.

Il plug -in DynamicSigns di @ChristianBrabandt semplifica l' utilizzo della funzione Sign a questo scopo: descrive come utilizzarlo per farlo in questa risposta .


1
+1 per una risposta. Tuttavia (e correggimi se sbaglio) ma guibgfunziona solo per gvim, giusto?
Karolis Koncevičius,

1
@Karolis Sì. Per il terminale Vim è necessario utilizzare ctermbg, come indicato.
Ricco

1
Se usi le pieghe, ottieni quello che vuoi: le pieghe hanno un colore bg diverso, tuttavia, questo si ottiene riempiendo lo sfondo di caratteri spaziali che hanno un set di colori bg diverso ... Questo provoca alcuni effetti collaterali: copia / paste non funzionerà più correttamente (poiché copierà anche molti caratteri spaziali, è anche possibile verificarlo da soli).
Martin Tournoij,

@Rich, grazie per la risposta. Sebbene non sia una soluzione perfetta (in termini di evidenziazione dei blocchi), risponde pienamente alla domanda dimostrando che ciò è possibile. Risposta accettata
Karolis Koncevičius,

3
Qualcuno dovrebbe essere davvero pazzo per scrivere una sceneggiatura del genere.
joeytwiddle,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.