segmentsFor method
line as styled segments, ready to paint. With words, the segments
are split where the line's changed words start and end, and those are
marked DiffSegment.changed. A line without tokens, such as an
expanded line of a parsed patch, is one plain segment.
Implementation
List<DiffSegment> segmentsFor(DiffLine line, [WordChanges? words]) {
if (line.text.isEmpty) return const [];
var tokens = tokensFor(line);
// Not tokenized yet, or outside the hunks: one plain token, so changed
// words are still marked.
if (tokens.isEmpty) {
tokens = [ThemedToken(line.text, 0, _plain, _plainScopes)];
}
final ranges = words?.rangesFor(line) ?? const <CharRange>[];
final segments = <DiffSegment>[];
var r = 0;
for (final token in tokens) {
final end = token.offset + token.text.length;
var pos = token.offset;
while (pos < end) {
while (r < ranges.length && ranges[r].end <= pos) {
r++;
}
final inRange = r < ranges.length && ranges[r].start <= pos;
final next = inRange
? math.min(end, ranges[r].end)
: (r < ranges.length ? math.min(end, ranges[r].start) : end);
segments.add(
DiffSegment(
token.text.substring(pos - token.offset, next - token.offset),
token.style,
changed: inRange,
),
);
pos = next;
}
}
return segments;
}