Comment trier plusieurs blocs de texte par la première ligne de chaque bloc dans Vim?

11

J'ai plusieurs blocs de texte, ou en d'autres termes, plusieurs fonctions comme celle-ci:

def ==(other)
  ...
end

def to_s(full=false)
  ...
end

def to_a
  ...
end

def to_hash
  ...
end

def inspect
  ...
end

Je veux trier les fonctions par ordre alphabétique selon la signature de la fonction. Comment cela peut-il se faire le plus facilement dans Vim?

Hubro
la source
définissez ce que vous entendez par signature de fonction, s'il vous plaît. De quel type de fonctions s'agit-il? De plus, sur quelle plate-forme travaillez-vous sous OS, la distribution et le numéro de version seraient TRÈS utiles.
mdpc
1
pourquoi cela doit-il être fait dans VIM? il existe d'excellents utilitaires unix / linux intégrés qui peuvent être facilement bricolés pour ce type de choses .... awk me vient à l'esprit.
mdpc
@mdpc: Par la signature de la fonction, je veux juste dire la ligne contenant def .... Je suis sous Linux, donc l'un de ces utilitaires fonctionnera pour moi.
Hubro

Réponses:

12

C'est relativement simple (et, je crois, proche de ce que Jason avait en tête):

  1. transformez toutes vos fonctions en une seule ligne en remplaçant toutes les nouvelles lignes par un caractère fantaisie:

    :g/def/,/end/s/\n/§
    
  2. trier ces doublures avec:

    :%sort
    
  3. étendez toutes vos fonctions à leur état individuel initial:

    :g/def/s/§/\r
    
romainl
la source
1
De même, si les lignes vierges peuvent être considérées comme des séparateurs uniques, cela pourrait être fait avec :g/./,/^$/-s/\n/§/g, puis :%sort, et ensuites/§/\r/g
ArtBIT
3

J'ai écrit le plugin AdvancedSorters pour simplifier les trois étapes distinctes données dans la réponse de @ romainl en une seule commande:

:SortRangesByRange /^def\>/,/^end\>\_s*\zs$/

Le modèle ici est légèrement plus complexe pour inclure également correctement les lignes vides de séparation.

Ingo Karkat
la source
Remarque: Vous aurez actuellement besoin d'un Vim 7.4.218 assez nouveau pour cela; Je fournirai bientôt une mise à jour qui prend également en charge les anciennes versions de Vim.
Ingo Karkat
2

La meilleure façon de penser à cela sans écrire une fonction qui analyse les définitions, serait de remplacer les délimiteurs de ligne non précédés par endun autre délimiteur unique (+ EOL +?), Puis de :sortremplacer les délimiteurs de ligne. Il pourrait probablement être enregistré dans une macro.

Une fonction pourrait être meilleure cependant, dans le cas où vous souhaitez utiliser la sélection visuelle.

Jason
la source
2

Essayez le plugin vissort. Il prend en charge une fonction de tri des blocs:

  • : '<'> BS nextblock endblock findtag tagpat tagsub
  • : [range] appeler BlockSort (nextblock, endblock, findtag, tagpat, tagsub)

Si des arguments manquent, BlockSort () vous interrogera pour eux. Les modèles de bloc suivant / bloc de fin délimitent un bloc, le modèle findtag est utilisé pour trouver une ligne contenant une "balise" qui sera utilisée pour le tri; tagpat et tabsub sont utilisés dans un substitut pour extraire la balise de tri de la ligne contenant la balise.

Vous pouvez obtenir vissort.vim sur http://www.drchip.org/astronaut/vim/index.html#VISSORT

user21497
la source