Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

Commit acfa8d1

Browse files
committed
Properly indent multi-line labels for mutli-span highlights
1 parent 24151fd commit acfa8d1

File tree

4 files changed

+147
-13
lines changed

4 files changed

+147
-13
lines changed

‎CHANGELOG.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# 1.9.1-dev
1+
# 1.9.1
2+
3+
* Properly handle multi-line labels for multi-span highlights.
24

35
* Populate the pubspec `repository` field.
46

‎lib/src/highlighter.dart‎

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -367,12 +367,13 @@ class Highlighter {
367367
_writeMultilineHighlights(line, highlightsByColumn, current: highlight);
368368
if (highlightsByColumn.isNotEmpty) _buffer.write(' ');
369369

370-
_colorize(() {
370+
final underlineLength = _colorize(() {
371+
final start = _buffer.length;
371372
_writeUnderline(line, highlight.span,
372373
highlight.isPrimary ? '^' : glyph.horizontalLineBold);
373-
_writeLabel(highlight.label);
374+
return _buffer.length - start;
374375
}, color: color);
375-
_buffer.writeln();
376+
_writeLabel(highlight, highlightsByColumn, underlineLength);
376377
} else if (highlight.span.start.line == line.number) {
377378
if (highlightsByColumn.contains(highlight)) return;
378379
replaceFirstNull(highlightsByColumn, highlight);
@@ -394,16 +395,17 @@ class Highlighter {
394395
_buffer.write(' ');
395396
_writeMultilineHighlights(line, highlightsByColumn, current: highlight);
396397

397-
_colorize(() {
398+
final underlineLength = _colorize(() {
399+
final start = _buffer.length;
398400
if (coversWholeLine) {
399401
_buffer.write(glyph.horizontalLine * 3);
400402
} else {
401403
_writeArrow(line, math.max(highlight.span.end.column - 1, 0),
402404
beginning: false);
403405
}
404-
_writeLabel(highlight.label);
406+
return _buffer.length - start;
405407
}, color: color);
406-
_buffer.writeln();
408+
_writeLabel(highlight, highlightsByColumn, underlineLength);
407409
replaceWithNull(highlightsByColumn, highlight);
408410
}
409411
}
@@ -442,9 +444,42 @@ class Highlighter {
442444
..write('^');
443445
}
444446

445-
/// Writes a space followed by [label] if [label] isn't `null`.
446-
void _writeLabel(String? label) {
447-
if (label != null) _buffer.write(' $label');
447+
/// Writes [highlight]'s label.
448+
///
449+
/// The `_buffer` is assumed to be written to the point where the first line
450+
/// of `highlight.label` can be written after a space, but this takes care of
451+
/// writing indentation and highlight columns for later lines.
452+
///
453+
/// The [underlineLength] is the length of the line written between the
454+
/// highlights and the beginning of the first label.
455+
void _writeLabel(_Highlight highlight, List<_Highlight?> highlightsByColumn,
456+
int underlineLength) {
457+
final label = highlight.label;
458+
if (label == null) {
459+
_buffer.writeln();
460+
return;
461+
}
462+
463+
final lines = label.split('\n');
464+
final color = highlight.isPrimary ? _primaryColor : _secondaryColor;
465+
_colorize(() => _buffer.write(' ${lines.first}'), color: color);
466+
_buffer.writeln();
467+
468+
for (var text in lines.skip(1)) {
469+
_writeSidebar();
470+
_buffer.write(' ');
471+
for (var columnHighlight in highlightsByColumn) {
472+
if (columnHighlight == null || columnHighlight == highlight) {
473+
_buffer.write(' ');
474+
} else {
475+
_buffer.write(glyph.verticalLine);
476+
}
477+
}
478+
479+
_buffer.write(' ' * underlineLength);
480+
_colorize(() => _buffer.write(' $text'), color: color);
481+
_buffer.writeln();
482+
}
448483
}
449484

450485
/// Writes a snippet from the source text, converting hard tab characters into
@@ -496,10 +531,11 @@ class Highlighter {
496531

497532
/// Colors all text written to [_buffer] during [callback], if colorization is
498533
/// enabled and [color] is not `null`.
499-
void _colorize(void Function() callback, {required String? color}) {
534+
T _colorize<T>(T Function() callback, {required String? color}) {
500535
if (_primaryColor != null && color != null) _buffer.write(color);
501-
callback();
536+
final result = callback();
502537
if (_primaryColor != null && color != null) _buffer.write(colors.none);
538+
return result;
503539
}
504540
}
505541

‎pubspec.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: source_span
2-
version: 1.9.1-dev
2+
version: 1.9.1
33
description: A library for identifying source spans and locations.
44
repository: https://github.com/dart-lang/source_span
55

‎test/multiple_highlight_test.dart‎

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,100 @@ quibble bibble boop
328328
| === two
329329
'"""));
330330
});
331+
332+
group('indents mutli-line labels', () {
333+
test('for the primary label', () {
334+
expect(file.span(17, 21).highlightMultiple('line 1\nline 2\nline 3', {}),
335+
equals("""
336+
,
337+
2 | whiz bang boom
338+
| ^^^^ line 1
339+
| line 2
340+
| line 3
341+
'"""));
342+
});
343+
344+
group('for a secondary label', () {
345+
test('on the same line', () {
346+
expect(
347+
file.span(17, 21).highlightMultiple(
348+
'primary', {file.span(22, 26): 'line 1\nline 2\nline 3'}),
349+
equals("""
350+
,
351+
2 | whiz bang boom
352+
| ^^^^ primary
353+
| ==== line 1
354+
| line 2
355+
| line 3
356+
'"""));
357+
});
358+
359+
test('on a different line', () {
360+
expect(
361+
file.span(17, 21).highlightMultiple(
362+
'primary', {file.span(31, 34): 'line 1\nline 2\nline 3'}),
363+
equals("""
364+
,
365+
2 | whiz bang boom
366+
| ^^^^ primary
367+
3 | zip zap zop
368+
| === line 1
369+
| line 2
370+
| line 3
371+
'"""));
372+
});
373+
});
374+
375+
group('for a multiline span', () {
376+
test('that covers the whole last line', () {
377+
expect(
378+
file.span(12, 70).highlightMultiple('line 1\nline 2\nline 3', {}),
379+
equals("""
380+
,
381+
2 | / whiz bang boom
382+
3 | | zip zap zop
383+
4 | | fwee fwoo fwip
384+
5 | | argle bargle boo
385+
| '--- line 1
386+
| line 2
387+
| line 3
388+
'"""));
389+
});
390+
391+
test('that covers part of the last line', () {
392+
expect(
393+
file.span(12, 66).highlightMultiple('line 1\nline 2\nline 3', {}),
394+
equals("""
395+
,
396+
2 | / whiz bang boom
397+
3 | | zip zap zop
398+
4 | | fwee fwoo fwip
399+
5 | | argle bargle boo
400+
| '------------^ line 1
401+
| line 2
402+
| line 3
403+
'"""));
404+
});
405+
});
406+
407+
test('with an overlapping span', () {
408+
expect(
409+
file.span(12, 70).highlightMultiple('line 1\nline 2\nline 3',
410+
{file.span(54, 89): 'two', file.span(0, 27): 'three'}),
411+
equals("""
412+
,
413+
1 | /- foo bar baz
414+
2 | |/ whiz bang boom
415+
| '+--- three
416+
3 | | zip zap zop
417+
4 | | fwee fwoo fwip
418+
5 | /+ argle bargle boo
419+
| |'--- line 1
420+
| | line 2
421+
| | line 3
422+
6 | | gibble bibble bop
423+
| '---- two
424+
'"""));
425+
});
426+
});
331427
}

0 commit comments

Comments
 (0)