Skip to content

Commit 5915f69

Browse files
committed
feat: Make multiline label collapsing configurable per label
1 parent e45dba4 commit 5915f69

File tree

2 files changed

+92
-3
lines changed

2 files changed

+92
-3
lines changed

src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,25 @@ impl<Id: fmt::Debug + Hash + PartialEq + Eq + ToOwned> Span for (Id, RangeInclus
120120
}
121121
}
122122

123+
/// A type that describes when a multiline label should hide its contents with ellipses
124+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
125+
pub enum LabelCollapseLines {
126+
/// Hides the contents of the label with ellipses if it is over the line limit
127+
MaxLines(usize),
128+
/// Always hides contents of multiline labels with ellipses
129+
Always,
130+
/// Always show the entire label contents (never use ellipses)
131+
Never,
132+
}
133+
123134
/// A type that represents the way a label should be displayed.
124135
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
125136
struct LabelDisplay {
126137
msg: Option<String>,
127138
color: Option<Color>,
128139
order: i32,
129140
priority: i32,
141+
collapse_when: LabelCollapseLines,
130142
}
131143

132144
/// A type that represents a labelled section of source code.
@@ -153,6 +165,7 @@ impl<S: Span> Label<S> {
153165
color: None,
154166
order: 0,
155167
priority: 0,
168+
collapse_when: LabelCollapseLines::Always,
156169
},
157170
}
158171
}
@@ -197,6 +210,14 @@ impl<S: Span> Label<S> {
197210
self.display_info.priority = priority;
198211
self
199212
}
213+
214+
/// Specify when the label should hide multiline contents with ellipses
215+
///
216+
/// If unspecified, defaults to always collapsing multiline labels with `LabelCollapseLines::Always`
217+
pub fn with_collapse_lines_when(mut self, collapse_when: LabelCollapseLines) -> Self {
218+
self.display_info.collapse_when = collapse_when;
219+
self
220+
}
200221
}
201222

202223
/// A type representing a diagnostic that is ready to be written to output.

src/write.rs

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::io;
22
use std::ops::Range;
33

4-
use crate::{Config, IndexType, LabelDisplay};
4+
use crate::{Config, IndexType, LabelCollapseLines, LabelDisplay};
55

66
use super::draw::{self, StreamAwareFmt, StreamType, WrappedWriter};
77
use super::{Cache, CharSet, LabelAttach, Report, ReportStyle, Show, Span, Write};
@@ -626,7 +626,20 @@ impl<S: Span, K: ReportStyle> Report<S, K> {
626626
.iter()
627627
.any(|label| label.char_span.contains(&line.span().start()));
628628
if !is_ellipsis && within_label {
629-
is_ellipsis = true;
629+
// Check to see if all the multiline labels containing this line use ellipses
630+
let should_collapse = multi_labels
631+
.iter()
632+
.filter(|label| label.char_span.contains(&line.span().start()))
633+
.all(|label| match label.display_info.collapse_when {
634+
LabelCollapseLines::Always => true,
635+
LabelCollapseLines::MaxLines(max_lines) => {
636+
label.end_line - label.start_line >= max_lines
637+
}
638+
LabelCollapseLines::Never => false,
639+
});
640+
if should_collapse {
641+
is_ellipsis = true;
642+
}
630643
} else {
631644
if !self.config.compact && !is_ellipsis {
632645
write_margin(&mut w, idx, false, is_ellipsis, false, None, &[], &None)?;
@@ -1000,7 +1013,8 @@ mod tests {
10001013
use insta::assert_snapshot;
10011014

10021015
use crate::{
1003-
Cache, CharSet, Config, IndexType, Label, Report, ReportKind, ReportStyle, Source, Span,
1016+
Cache, CharSet, Config, IndexType, Label, LabelCollapseLines, Report, ReportKind,
1017+
ReportStyle, Source, Span,
10041018
};
10051019

10061020
impl<S: Span, K: ReportStyle> Report<S, K> {
@@ -1405,6 +1419,60 @@ mod tests {
14051419
"###);
14061420
}
14071421

1422+
#[test]
1423+
fn multiline_label_show_3() {
1424+
let source = "pear\napple\n==\norange\nbanana";
1425+
let msg = remove_trailing(
1426+
Report::build(ReportKind::Error, 0..0)
1427+
.with_config(no_color_and_ascii())
1428+
.with_label(
1429+
Label::new(5..20)
1430+
.with_message("illegal comparison")
1431+
.with_collapse_lines_when(LabelCollapseLines::MaxLines(3)),
1432+
)
1433+
.finish()
1434+
.write_to_string(Source::from(source)),
1435+
);
1436+
assert_snapshot!(msg, @r"
1437+
Error:
1438+
,-[ <unknown>:1:1 ]
1439+
|
1440+
2 | ,-> apple
1441+
3 | | ==
1442+
4 | |-> orange
1443+
| |
1444+
| `------------ illegal comparison
1445+
---'
1446+
");
1447+
}
1448+
1449+
#[test]
1450+
fn multiline_label_longer_than_max_span_line_count() {
1451+
let source = "pear\napple\n==\norange\nbanana";
1452+
let msg = remove_trailing(
1453+
Report::build(ReportKind::Error, 0..0)
1454+
.with_config(no_color_and_ascii())
1455+
.with_label(
1456+
Label::new(5..source.len())
1457+
.with_message("illegal comparison")
1458+
.with_collapse_lines_when(LabelCollapseLines::MaxLines(3)),
1459+
)
1460+
.finish()
1461+
.write_to_string(Source::from(source)),
1462+
);
1463+
assert_snapshot!(msg, @r"
1464+
Error:
1465+
,-[ <unknown>:1:1 ]
1466+
|
1467+
2 | ,-> apple
1468+
: :
1469+
5 | |-> banana
1470+
| |
1471+
| `----------- illegal comparison
1472+
---'
1473+
");
1474+
}
1475+
14081476
#[test]
14091477
fn multiline_context_label() {
14101478
let source = "apple\nbanana\ncarrot\ndragonfruit\negg\nfruit\ngrapes";

0 commit comments

Comments
 (0)