Comprimi vim fold su una sola riga, simile a Atom o Sublime Text


13

Sono un fan del modo in cui Atom e Sublime Text gestiscono la piegatura della linea, in cui è visibile la prima riga di ogni piega (completa di evidenziazione della sintassi) e un indicatore viene aggiunto alla fine della riga che indica la piega.

Guarda lo screenshot qui sotto che confronta la piegatura del rientro di Vim (in alto) rispetto a quella di Atom (in basso):Piegatura codice Vim vs. Atom

Vim dedica due linee per ogni piega. La prima riga funge da intestazione e la seconda riga descrive alcune informazioni sulla piega (numero di righe e testo all'interno della piega).

Atom usa solo una linea e usa un piccolo indicatore alla fine della linea per indicare la piega, insieme al colore aggiunto ai numeri di linea a sinistra. Lo stile pieghevole di Atom utilizza meno spazio sullo schermo ma comunica comunque tutte le informazioni di cui ho veramente bisogno.

Sono parziale allo stile pieghevole Atom. Sembra più pulito e coerente, secondo me, in particolare quando si elencano più metodi o attributi in una riga (come nello screenshot sopra).

C'è un modo per approssimare approssimativamente lo stile pieghevole di Atom in Vim?


1
Penso che sia perché le tue pieghe in realtà non iniziano con la linea che contiene le parentesi aperte. Vim usa solo il testo della piega sulla linea dove inizia la piega. Vedi, ad esempio, come il posizionamento del controvento influisce su di esso in C: imgur.com/3h70dPf,wfCLPm7
muru,

Ma questo è Python, nessuna parentesi graffa coinvolta ( from __future__ import braces) ... Come hai configurato la piegatura? E puoi incollare questo frammento di codice (o un altro che dimostra il problema)? Vim piega su una sola linea, ma come menzionato da Muru, le tue pieghe iniziano una linea in ritardo.
Martin Tournoij,

@Carpetsmoker le parentesi graffe sono solo per l'illustrazione di dove inizia la piega. Lo stesso effetto può essere visto, diciamo, su Haskell.
muru,

@MikeHearn La mia risposta precedente era completamente errata. L'ho aggiornato per includere una soluzione al problema.
Ricco

Risposte:


12

Due linee contro una linea

In Vim, tutte le linee all'interno di una piega verranno compresse su una sola linea e l' 'foldtext'opzione determina quindi la sinossi di quelle linee (di solito trattini, il numero di linee piegate e il contenuto delle prime (o tutte)).

Nel tuo esempio, in Vim {...}viene piegato solo il blocco parametri stesso; la riga sopra (che utilizza i parametri) non fa parte del fold. Al contrario, nell'altro editor, quella riga che utilizza i parametri appartiene alla piega, e il suo foldtext (per usare la terminologia di Vim) è il contenuto di quella riga più il marcatore aggiunto.

Adattamento

In Vim, le pieghe possono essere generate con mezzi diversi (vedi :help fold-methods) e dipendono 'filetype'dal buffer. La difficoltà di includere la linea sopra nella piega dipende da questo; verificare con :setlocal foldmethod?. Con il rientro del rientro , non c'è nulla che tu possa influenzare; devi passare a un altro metodo. Per la piegatura della sintassi , ciò significherebbe adattare le definizioni della sintassi e potrebbe essere molto complicato. Avrai più fortuna se viene utilizzata un'espressione , ma significherebbe comunque comprendere e cambiare la logica. (È improbabile che l'autore del plugin filetype abbia fornito una configurazione per influenzare questo.)

Evidenziazione della sintassi della linea piegata

Questo purtroppo non è affatto possibile. Vim utilizza sempre il Foldedgruppo di evidenziazione per l'intera linea piegata. Puoi modificarlo tramite i :highlightcomandi nel tuo ~/.vimrc, ma la differenziazione individuale della sintassi andrà persa.


5

Vim mostra già le pieghe come un'unica riga. Tuttavia, nella indentpiegatura di Vim , tutte le linee che hanno lo stesso rientro sono incluse in una piega. Quindi, nel tuo screenshot, le linee a cui ti riferisci come "intestazioni" (es. Quella iniziale collection_base_url) non sono comprese nelle pieghe.

Puoi ottenere qualcosa di simile al pieghevole di Atom usando Vim foldexpr foldmethod:

" Finds the indent of a line. The indent of a blank line is the indent of the
" first non-blank line above it.
function! FindIndent(line_number, indent_width)
    " Regular expression for a "blank" line
    let regexp_blank = "^\s*$"

    let non_blank_line = a:line_number
    while non_blank_line > 0 && getline(non_blank_line) =~ regexp_blank
        let non_blank_line = non_blank_line - 1
    endwhile
    return indent(non_blank_line) / a:indent_width
endfunction

" 'foldexpr' for Atom-style indent folding
function! AtomStyleFolding(line_number)
    let indent_width = &shiftwidth

    " Find current indent
    let indent = FindIndent(a:line_number, indent_width)

    " Now find the indent of the next line
    let indent_below = FindIndent(a:line_number + 1, indent_width)

    " Calculate indent level
    if indent_below > indent
        return indent_below
    elseif indent_below < indent
        return "<" . indent
    else
        return indent
    endif
endfunction

set foldexpr=AtomStyleFolding(v:lnum)
set foldmethod=expr

Questo definisce un'espressione di piega (vedi :help fold-expr) come segue:

  • Per le righe che precedono immediatamente le righe rientrate, restituisce il rientro del blocco che segue.
  • Per le righe rientrate, restituisce il rientro. (Diviso per la larghezza del turno in modo che ogni livello di rientro aumenti il ​​valore restituito di 1)
  • Per le linee alla fine di un blocco di linee rientrate, restituisce una stringa "<N", dove N è impostato sul rientro. Questo dice a Vim che una piega di livello N termina su quella linea.

Aggiornare

@alxndr chiede nei commenti se è possibile estenderlo per includere le rubriche superate di Ruby endnelle pieghe. È possibile iniziare sostituendo la " Calculate indent levelsezione con quanto segue:

if indent_below > indent
    return indent_below
elseif getline(a:line_number) =~ '^\s*end\s*$'
    return "<" . (indent + 1)
else
    return indent
endif

Allo stato attuale, questa non è la soluzione più efficace (ad es. Non riuscirà se l' endistruzione si trova sulla stessa riga, dopo un punto e virgola). Potresti modificare l'espressione regolare e il codice circostante per risolvere questo problema, ma dato che ora sei nel regno dell'analisi della sintassi effettiva del file, sospetto che le cose potrebbero diventare molto più complicate prima di avere una buona soluzione.


Ottimo approccio Questa risposta potrebbe essere generalizzata per gestire anche dire Ruby, con la sua superata endper finire un blocco?
alxndr,

1
@alxndr Ho modificato la mia risposta con qualche discussione.
Rich

@Rich: trovo molto utile anche la piega del testo Sublime che mostra solo un segno ...alla fine della riga come simbolo di un blocco di testo piegato e fa meno distrazione che deve evidenziare l'intera prima riga del blocco di testo come in vim. Ho provato la tua piega sopra con il comportamento di piega predefinito di vim, semplice non funziona. Come avere una piega che dia un segno alla fine della prima riga del blocco di testo con Python? Devo aprire una nuova domanda? Ho appena provato di nuovo la tua piega, in effetti funziona molto bene con la riga di rientro. super Grazie.
Tuyen Pham,

Questo è fantastico! Ho cercato qualcosa che funzioni in modalità org come piegare e questo aiuta molto!
priomsrb
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.