@@ -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
0 commit comments