RFC - fixing comparison feature
Pavel Sanda <[email protected]> Wed, 29 Jul 2026 11:08:30 +0200
| Newsgroups | gmane.editors.lyx.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi,
I see lyx comparison feature broken for main two reasons:
1) it produces char-like diffs spilled across the words and sentences even for word-like changes which makes it totally unreadable for naked eye (bug #6889)
2) it's superslow on any non trivial changeset
Below is the attempt to narrow heuristics to fix 1).
Please send me your comments or objections if you have any before I start shaping the code.
Pavel
---
IV. Myers postprocessing refining the diff on non-CJK languages
Problem:
The previous steps create mathematically minimal but frequently unreadable diff -
it scatters tiny CT fragments across words and sentences. Example from bug #6889:
instead of {unique}[single] the results looks like {u}[si]n{iqu}[gl]e.
Approach:
First refine for single chars and later we switch to words (for performance reasons)
while leaving the char-level diffs functional so small char-level typos are easily seen.
References:
- LibreOffice takes the opposite route - diffs whole words (so no question of scatter).
- MS Word gives choice between char vs word level.
IVa. Detector for "this word's character diff is the scattered-noise"
* First some terminology:
"Single continuous run" - at most one deleted block, then at most one inserted block, in that order
- {...} - pure deletion
- [...] - pure insertion
- {...}[...] - deletion immediately followed by insertion (a substitution)
- []{} does not occur (compare always emits delete first)
- mixtures {}[]{}[] do not occur (compare always build whole subrange as deleted/inserted -
mixture always occurs with snake inside (>=1 unchanged character) eg {}[]s{}[], but
the it's no more continuous run.
"Unchanged interior" - a run of unchanged characters (="survivor") that touches neither end
of the word - i.e. it has changed text on both sides.
"Crumb" - an interior unchanged piece of 1-2 characters (this 3 chars threshold is the only knob
in our collapse detector).
* Now the heuristics:
Keep char-diff for: edits are single continous run (one consecutive {del}[ins] run) OR
"real shared text, not coincidence" - edits are separated by substantial
(>= 3 char) unchanged stretches.
Otherwise reject diff, collapse as whole word diff {old}[new].
* Consequences
1. A single contiguous edit has only boundary (prefix/suffix) survivors, so it is always kept ->
typo fixes stay character-precise: correct[i]on.
2. A substantial unchanged interior is kept: {d}[m]isprove{n}[d] keeps the real shared stem
isprove even though both ends changed.
3. A crumb triggers a whole-word collapse: {unique}[single], {beating}[boaring].
4. The decision is per-word all-or-nothing: one interior crumb collapses the entire word,
because a half-cleaned word still reads as fragments.
5. The trigger is the size of the interior unchanged survivor, not the amount of change - so a
big change with a solid survivor is kept, while a tiny change straddling a crumb is collapsed.
* Examples:
------------------------------------------------------------------------------------------------------
| old -> new | raw character diff | unchanged interior | verdict | result |
------------------------------------------------------------------------------------------------------
| correcton -> correction | correct[i]on | none (all boundary) | keep | correct[i]on |
------------------------------------------------------------------------------------------------------
| disproven -> misproved | {d}[m]isprove{n}[d] | isprove (7) | keep | {d}[m]isprove{n}[d] |
------------------------------------------------------------------------------------------------------
| unique -> single | {u}[si]n{iqu}[gl]e | n (1) | collapse | {unique}[single] |
------------------------------------------------------------------------------------------------------
| beating -> boaring | b{e}[o]a{t}[r]ing | a (1) | collapse | {beating}[boaring] |
------------------------------------------------------------------------------------------------------
--
lyx-devel mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-devel