Skip to content

Commit

Permalink
Properly indent multi-line labels for mutli-span highlights
Browse files Browse the repository at this point in the history
  • Loading branch information
nex3 committed Jul 13, 2022
1 parent 24151fd commit 1a3c90f
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 9 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# 1.9.1-dev
# 1.9.1

* Properly handle multi-line labels for multi-span highlights.

* Populate the pubspec `repository` field.

Expand Down
54 changes: 47 additions & 7 deletions lib/src/highlighter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import 'span.dart';
import 'span_with_context.dart';
import 'utils.dart';

import 'file.dart';

/// A class for writing a chunk of text with a particular span highlighted.
class Highlighter {
/// The lines to display, including context around the highlighted spans.
Expand Down Expand Up @@ -367,12 +369,14 @@ class Highlighter {
_writeMultilineHighlights(line, highlightsByColumn, current: highlight);
if (highlightsByColumn.isNotEmpty) _buffer.write(' ');

late int underlineLength;
_colorize(() {
var start = _buffer.length;
_writeUnderline(line, highlight.span,
highlight.isPrimary ? '^' : glyph.horizontalLineBold);
_writeLabel(highlight.label);
underlineLength = _buffer.length - start;
}, color: color);
_buffer.writeln();
_writeLabel(highlight, highlightsByColumn, underlineLength);
} else if (highlight.span.start.line == line.number) {
if (highlightsByColumn.contains(highlight)) return;
replaceFirstNull(highlightsByColumn, highlight);
Expand All @@ -394,16 +398,18 @@ class Highlighter {
_buffer.write(' ');
_writeMultilineHighlights(line, highlightsByColumn, current: highlight);

late int underlineLength;
_colorize(() {
var start = _buffer.length;
if (coversWholeLine) {
_buffer.write(glyph.horizontalLine * 3);
} else {
_writeArrow(line, math.max(highlight.span.end.column - 1, 0),
beginning: false);
}
_writeLabel(highlight.label);
underlineLength = _buffer.length - start;
}, color: color);
_buffer.writeln();
_writeLabel(highlight, highlightsByColumn, underlineLength);
replaceWithNull(highlightsByColumn, highlight);
}
}
Expand Down Expand Up @@ -442,9 +448,43 @@ class Highlighter {
..write('^');
}

/// Writes a space followed by [label] if [label] isn't `null`.
void _writeLabel(String? label) {
if (label != null) _buffer.write(' $label');
/// Writes [highlight]'s label.
///
/// The `_buffer` is assumed to be written to the point where the first line
/// of `highlight.label` can be written after a space, but this takes care of
/// writing indentation and highlight columns for later lines.
///
/// The [underlines] is the length of the line written between the highlights
/// and the beginning of the first label.
void _writeLabel(
_Highlight highlight, List<_Highlight?> highlightsByColumn, int underlineLength) {
final label = highlight.label;
if (label == null) {
_buffer.writeln();
return;
}

final lines = label.split('\n');
final color = highlight.isPrimary ? _primaryColor : _secondaryColor;
_colorize(() => _buffer.write(' ${lines.first}'), color: color);
_buffer.writeln();

for (var text in lines.skip(1)) {
final lineStart = _buffer.length;
_writeSidebar();
_buffer.write(' ');
for (var columnHighlight in highlightsByColumn) {
if (columnHighlight == null || columnHighlight == highlight) {
_buffer.write(' ');
} else {
_buffer.write(glyph.verticalLine);
}
}

_buffer.write(' ' * underlineLength);
_colorize(() => _buffer.write(' $text'), color: color);
_buffer.writeln();
}
}

/// Writes a snippet from the source text, converting hard tab characters into
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: source_span
version: 1.9.1-dev
version: 1.9.1
description: A library for identifying source spans and locations.
repository: https://github.com/dart-lang/source_span

Expand Down
96 changes: 96 additions & 0 deletions test/multiple_highlight_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,100 @@ quibble bibble boop
| === two
'"""));
});

group('indents mutli-line labels', () {
test('for the primary label', () {
expect(file.span(17, 21).highlightMultiple('line 1\nline 2\nline 3', {}),
equals("""
,
2 | whiz bang boom
| ^^^^ line 1
| line 2
| line 3
'"""));
});

group('for a secondary label', () {
test('on the same line', () {
expect(
file.span(17, 21).highlightMultiple(
'primary', {file.span(22, 26): 'line 1\nline 2\nline 3'}),
equals("""
,
2 | whiz bang boom
| ^^^^ primary
| ==== line 1
| line 2
| line 3
'"""));
});

test('on a different line', () {
expect(
file.span(17, 21).highlightMultiple(
'primary', {file.span(31, 34): 'line 1\nline 2\nline 3'}),
equals("""
,
2 | whiz bang boom
| ^^^^ primary
3 | zip zap zop
| === line 1
| line 2
| line 3
'"""));
});
});

group('for a multiline span', () {
test('that covers the whole last line', () {
expect(
file.span(12, 70).highlightMultiple('line 1\nline 2\nline 3', {}),
equals("""
,
2 | / whiz bang boom
3 | | zip zap zop
4 | | fwee fwoo fwip
5 | | argle bargle boo
| '--- line 1
| line 2
| line 3
'"""));
});

test('that covers part of the last line', () {
expect(
file.span(12, 66).highlightMultiple('line 1\nline 2\nline 3', {}),
equals("""
,
2 | / whiz bang boom
3 | | zip zap zop
4 | | fwee fwoo fwip
5 | | argle bargle boo
| '------------^ line 1
| line 2
| line 3
'"""));
});
});

test('with an overlapping span', () {
expect(
file.span(12, 70).highlightMultiple('line 1\nline 2\nline 3',
{file.span(54, 89): 'two', file.span(0, 27): 'three'}),
equals("""
,
1 | /- foo bar baz
2 | |/ whiz bang boom
| '+--- three
3 | | zip zap zop
4 | | fwee fwoo fwip
5 | /+ argle bargle boo
| |'--- line 1
| | line 2
| | line 3
6 | | gibble bibble bop
| '---- two
'"""));
});
});
}

0 comments on commit 1a3c90f

Please sign in to comment.