2012-11-25 12 views
10

Ho un file che sembra qualcosa di simile:Ordinamento Vim Folds

dog{{{ 
blah blah blah 
}}} 
cat{{{ 
blah blah 
}}} 
aardvark{{{ 
blah blah blah blah 
}}} 

Nel mio vimrc ho set foldmethod=marker, in modo che il contenuto del file sono tutti piegati alle parentesi graffe. La mia domanda è, come posso ordinare il file basato sull'intestazione della piega? Voglio prima la sezione aarvaark, quindi cat, quindi dog.

Alcune sezioni piegate hanno altre pieghe al loro interno. Non voglio ordinare quei livelli di piega inferiori. Il file deve essere ordinato solo per il livello 1.

risposta

2

Con tutte le pieghe chiuse (zM o :set foldlevel=0), è possibile utilizzare cancellare dd e incollare p di spostare manualmente i blocchi piegati intorno. Questo va bene per piccole quantità di testo.

Per i testi enormi, che avrebbe dovuto scrivere una funzione sorta te stesso, come Vim non offre tale funzionalità. Il seguente algoritmo può essere utilizzato:

  1. Registrato tutte le linee piegati insieme con un delimitatore che non esiste nel testo (ad esempio <Nul>).
  2. Eseguire il comando :sort.
  3. Disunisci l'intervallo sul delimitatore speciale.

Con la gestione degli errori e dei casi d'angolo, è in realtà un bel po 'di sforzo di implementazione. Ho fatto un tentativo qui: https://gist.github.com/4145501

1

Un approccio potrebbe essere la seguente:

  1. cercare e sostituire le terminazioni di linea in modo che le pieghe livello-uno sono ciascuno su una riga (ossia di sostituire la linea terminando con una stringa unica che non appare altrove nel file).

  2. Usa :sort per ordinare le righe nel file, come al solito.

  3. Inverte la ricerca e la sostituzione dal punto 1 per reintrodurre la fine riga.

Questo potrebbe essere registrato come una macro Vim.

I passaggi 1 e 3 sarebbero semplici se non ci fossero pieghe nidificate o se esistesse un modo semplice per distinguere le pieghe di livello superiore da quelle nidificate (ad esempio se le linee di livello uno {{{} e}}} sono a sinistra e gli altri hanno lo spazio principale). Se questo non è il caso, probabilmente è ancora possibile ma molto più difficile.

1

avrei usato il potere di macro Vim.

Supponiamo che non si dispone di alcun altro personale nel file tranne i record e la prima registrazione inizia sulla prima riga. E che non hai l'inizio del livello 1 e finisci sulla stessa linea. E tutti i tuoi {} corrispondono bene.

Vai alla prima voce e registrare una macro per registrare un (qa - avviare la registrazione q - fermata)

/{^MV%k:s/\n/EEEEEE/^Mj^ 

Copia mia o meglio registrare da soli: (^ M - sta per letterale immettere)

  • /{^ M trova successivo {
  • V% k linea di selezione-morsa fino alla fine del livello 1, ma non la linea di chiusura con}}}
  • : s/\ n/EEEEEE/^ M cambia il simbolo 'fine linea' in una stringa unica all'interno della selezione
  • j^passa una riga in basso e alla riga della richiesta nel caso in cui il record precedente avesse spazi iniziali.

eseguire la macro a partire dalla seconda linea (supponiamo che il primo viene elaborato già quando ha registrato la macro.) In modalità normale 100000 @ a - uso qualunque sia il numero maggiore di numero dei record. La macro si fermerà da sola quando tutte le linee vengono elaborate se il primo record si trova nella prima riga del file. Come effetto collaterale selezionerà visivamente la prima linea - deselezionandola.

Ordina il file

:sort 

Ripristinare la fine delle linee: :% s/EEEEEE/^ M/g

Nota^M dovrebbero essere letterale entrare. Per digitare utilizzare Ctrl-V Enter

Funziona con livelli nidificati perché% salta alla chiusura corrispondente}. Questo è il motivo per cui è importante avere tutti i {} abbinati bene.

La macro si interrompe quando non è possibile salire con k è per questo che è necessario disporre del primo record sulla prima riga. Le linee vuote o qualsiasi cosa che non sia un record tra i record saranno ignorate dalla macro.

Il metodo sopra dovrebbe funzionare bene per il file. Se si desidera un approccio più generale con pieghe quindi utilizzare i seguenti comandi nella macro invece di/{e%

aprire In primo luogo tutte le piegature

ZJ - tornare all'inizio della prossima piega aperta

] z - vai alla fine della piega attuale.

Il resto della macro è lo stesso. Questo metodo è più generale ma l'ho trovato meno affidabile in quanto dipende da tutte le pieghe aperte, abilitazione piegatura e così via.