2010-05-04 10 views
2

Je veux générer un diff entre les révisions de texte (plus spécifiquement, les articles au format Markdown) en Python.Génération de diffs de contenu à l'aide de SequenceMatcher (Python)

Je souhaite formater ce diff d'une manière similaire à ce que fait Github.

J'ai regardé difflib et j'ai constaté qu'il fait ce que je veux. Cependant, la classe Differ est trop élevée; Je devrais analyser les lignes de diff pour générer du HTML avec des différences en ligne. La classe Differ utilise la classe SequenceMatcher pour générer ses différences. Mais en regardant le SequenceMatcher, il est très bas niveau en comparaison. Je n'ai même pas compris comment faire un diff line-by-line (j'avoue que je n'ai pas passé beaucoup de temps à expérimenter).

Quelqu'un connaît-il des ressources pour utiliser la classe SequenceMatcher (en plus de the difflib documentation)?

Répondre

7

SequenceMatcher n'est en réalité pas de niveau inférieur. La méthode la plus intéressante pour vous est get_grouped_opcodes. Il renverra un générateur, qui génère des listes avec des descriptions de changement.

Je vais l'expliquer sur un exemple d'un random commit on GitHub. Disons que vous exécutez SequenceMatcher(None, a, b).get_grouped_opcodes() sur l'ancien et le nouveau fichier "tabs_events.js". Le générateur va générer deux groupes, qui sont représentés par ces lignes "..." dans GitHub. C'est fondamentalement un groupe de changements. Dans chacun des groupes, vous disposez d'une liste de modifications détaillées stockées sous forme de tuples. Pour le premier groupe, il retourne deux changements qui ressemblent à ceci (le premier élément est un type de changement, les deux chiffres représentent une plage de lignes à supprimer, puis une plage de ligne à ajouter):

('replace', 24, 29, 24, 29) 
('insert', 33, 33, 33, 35) 

Le premier vous dit de remplacer les lignes 24-28 (commençant par 0) de l'ancien fichier par les lignes 24-28 du nouveau fichier. Le second vous dit d'insérer les lignes 33 à 34 du nouveau fichier sur la ligne 33 dans l'ancien fichier. Je pense qu'il est clair ce que 'delete' faire et 'equal' sont ces lignes qui ne sont pas mis en évidence dans GitHub.

Si cela ne vous dérange pas de lire le code source, jetez un oeil à la mise en œuvre de . C'est assez simple et cela génère un équivalent en texte brut de ce que vous voulez.