Content generation differs with SequenceMatcher (Python)
I want to create a difference between versions of text (more precisely, Markdown articles) in Python.
I want to format this diff the way Github does it .
I looked difflib
and found that it does what I want. However, the class is Differ
too high-level; I would have to parse the diff lines to generate HTML with diffs embedded. The class Differ
uses the class SequenceMatcher
to generate its differences. But looking at it SequenceMatcher
, it's very low-level in comparison. I didn't even figure out how to do a linear diff (I'll admit I didn't spend a lot of time experimenting).
Does anyone know of any resources for using the class SequenceMatcher
(other than the documentationdifflib
)?
a source to share
The SequenceMatcher is actually not that low-level. The most interesting method for you is get_grouped_opcodes
. It will return a generator that generates change lists.
I'll explain this with an example from a random commit on GitHub . Let's say you run SequenceMatcher(None, a, b).get_grouped_opcodes()
in the old and new tabs_events.js file. The generator will generate two groups that represent these "..." lines on GitHub. This is basically a group of changes. In each of the groups, you have a list of detailed changes, stored as tuples. For the first group, it returns two changes that look like this (the first item is the change type, the next two numbers represent the range of rows to be removed after adding the range of rows):
('replace', 24, 29, 24, 29)
('insert', 33, 33, 33, 35)
The first one tells you to replace lines 24-28 (starting at 0) from the old file with lines 24-28 from the new file. The second tells you to insert lines 33-34 from the new file on line 33 into the old file. I think it's clear what to do 'delete'
with 'equal'
those lines that are not highlighted in GitHub.
If you don't mind reading the source code, take a look at the implementation difflib.unified_diff()
. It's pretty simple and generates the plain text equivalent you want.
a source to share