Skip to content
TwinScope0.3.10

Reading a result

Every comparison opens the same way: counts first, then the detail. The chassis around the diff is identical for all five engines, so learning it once is enough.

Click to enlarge
Counts first, detail second. How much changed is nearly always the first question.

The summary strip#

PartWhat it is
17 changesThe total: added plus removed plus modified
+4 addedPresent on both sides but new here
-2 removedGone from the after side
~11 modifiedChanged in place
Engine chipsWhatever this engine counts that the three above cannot express
3 suppressedDifferences that existed and were hidden by an option you set
‹ 3 / 17 ›The change stepper
A trailing chipbefore ↔ after, so a screenshot of the strip identifies itself

The three coloured counts come from the engine, not from the view. That distinction matters as soon as you touch a normalisation option: those options re-run the comparison rather than filtering what is on screen, so the counts always describe exactly what you are looking at.

The chips each engine adds#

The strip renders these verbatim — it knows nothing about engines, which is how each one gets its own vocabulary without a special case.

EngineAdds
TextThe line count of the longer side
JSONThe node count, and a ⚠ N type changes chip when a value changed type
FoldersHow many files were identical, how many were paired as renames, how many were unreadable, the total size delta, and a partial scan chip when the tree hit the entry cap
ImagesThe percentage of pixels that differ, the number of changed regions, and a size mismatch chip when the dimensions differ
BinaryThe verdict — identical or different — and the byte delta when the sizes differ

Stepping through changes#

‹ 3 / 17 › in the strip and ⌥↑ / ⌥↓ are the same control. So is whatever the view does to bring a change into sight.

The view registers how many changes it has and how to reveal any one of them; the store owns which change is current. That is why the number, the keys and the scroll position cannot drift apart — there is only one index. Before you have stepped anywhere the position reads , and with nothing to step through the stepper is not rendered at all.

⌥↑ and ⌥↓ only take over the keys when a comparison actually has changes; otherwise they are left to the system. Full detail in Change navigation.

The status line#

The bar along the bottom carries the facts about the comparison itself rather than about the diff:

SideShows
Left, while runningThe engine's label and the current stage
Left, when finishedWhich engine ran, then how the before input was decoded — its encoding and its line endings
Right, while runningThe percentage
Right, when finishedCompared in 42 ms

Encoding and line endings live here rather than in a chip because they are facts about the files, and because they answer the question "why does line 1 differ when it looks identical?" — a byte-order mark or a CRLF/LF mismatch, usually. See Encodings.

The toolbar#

ControlNotes
The engine chipNames the engine that actually ran, which is the authoritative answer if it disagrees with the detection bar
The engine's own controlsView modes, filters, thresholds — each view portals its controls into this one toolbar rather than drawing its own
The search boxA find in the text diff and a filter in the JSON and folder views; disabled, not inert, for views that do not use it. See Search and filter
Export ▾Three formats, and ⌘⇧E to repeat the last one
← New comparisonClears both inputs as well as the result — "new" means new
A breadcrumbOnly after a folder drill-in: it returns to the parent comparison without re-running it, so a 10,000-file scan is never repeated because you opened one file

When a comparison fails#

The failure panel is deliberately plain: what happened, in the engine's own words, and the ways out.

ElementBehaviour
Comparison failedAnything that went wrong, including an engine crash
Comparison cancelledYou pressed Cancel. Rendered in muted text, not in the failure colour
The messageThe engine's own — a JSON parse error names the line and column; a missing file names the file
Back to CompareReturns to the two inputs
Copy detailsPuts the reason, both input names with their kinds, and the engine on the clipboard. Not offered for a cancellation, because there is nothing to report
Clipboard, after Copy detailsbash
TwinScope crash: The comparison engine stopped unexpectedly. Try again.
before: app-v1.bin (binary)
after:  app-v2.bin (binary)
engine: Binary comparison

Four lines, pasteable into an issue: the failure reason, both inputs with the kinds TwinScope decided they were, and the engine that was running. The kinds are there because a surprising kind is the cause of a surprising failure more often than the engine is.

An engine can offer a way out#

Some failures are only failures for that engine. When one knows another engine could still say something useful, it attaches that suggestion to the error and the panel renders it as the primary button.

The worked example is unparseable JSON: the structural engine cannot proceed, but the two files are still text, so the panel offers Compare as text and one click gets you a line diff of the file that would not parse — which is usually exactly what you need to find the stray comma.

Taking it with you#

Export writes a self-contained HTML report or a Markdown summary, or copies a unified patch to the clipboard. Reports carry the same counts, options and normalisation notes you are looking at, so the file explains itself to whoever opens it. See Export.