Skip to content

Commit 6ec17e2

Browse files
committed
feat: Trim the middle of long spans
1 parent e01f79c commit 6ec17e2

File tree

4 files changed

+57
-9
lines changed

4 files changed

+57
-9
lines changed

src/renderer/margin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub(crate) struct Margin {
1717
/// The end of the line to be displayed.
1818
computed_right: usize,
1919
/// The current width of the terminal. 140 by default and in tests.
20-
term_width: usize,
20+
pub(crate) term_width: usize,
2121
/// The end column of a span label, including the span. Doesn't account for labels not in the
2222
/// same line as the span.
2323
label_right: usize,

src/renderer/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,11 +1122,16 @@ impl Renderer {
11221122
// | x_span
11231123
// <EMPTY LINE>
11241124
//
1125+
let mut overlap = vec![false; annotations.len()];
11251126
let mut annotations_position = vec![];
11261127
let mut line_len: usize = 0;
11271128
let mut p = 0;
11281129
for (i, annotation) in annotations.iter().enumerate() {
11291130
for (j, next) in annotations.iter().enumerate() {
1131+
if overlaps(next, annotation, 0) && j > 1 {
1132+
overlap[i] = true;
1133+
overlap[j] = true;
1134+
}
11301135
if overlaps(next, annotation, 0) // This label overlaps with another one and both
11311136
&& annotation.has_label() // take space (they have text and are not
11321137
&& j > i // multiline lines).
@@ -1474,6 +1479,39 @@ impl Renderer {
14741479
);
14751480
}
14761481
}
1482+
1483+
// We look for individual *long* spans, and we trim the *middle*, so that we render
1484+
// LL | ...= [0, 0, 0, ..., 0, 0];
1485+
// | ^^^^^^^^^^...^^^^^^^ expected `&[u8]`, found `[{integer}; 1680]`
1486+
for (i, (_pos, annotation)) in annotations_position.iter().enumerate() {
1487+
// Skip cases where multiple spans overlap eachother.
1488+
if overlap[i] {
1489+
continue;
1490+
};
1491+
let LineAnnotationType::Singleline = annotation.annotation_type else {
1492+
continue;
1493+
};
1494+
let width = annotation.end.display - annotation.start.display;
1495+
if width > margin.term_width * 2 && width > 10 {
1496+
// If the terminal is *too* small, we keep at least a tiny bit of the span for
1497+
// display.
1498+
let pad = max(margin.term_width / 3, 5);
1499+
// Code line
1500+
buffer.replace(
1501+
line_offset,
1502+
annotation.start.display + pad,
1503+
annotation.end.display - pad,
1504+
self.margin(),
1505+
);
1506+
// Underline line
1507+
buffer.replace(
1508+
line_offset + 1,
1509+
annotation.start.display + pad,
1510+
annotation.end.display - pad,
1511+
self.margin(),
1512+
);
1513+
}
1514+
}
14771515
annotations_position
14781516
.iter()
14791517
.filter_map(|&(_, annotation)| match annotation.annotation_type {

src/renderer/styled_buffer.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ impl StyledBuffer {
9999
}
100100
}
101101

102+
pub(crate) fn replace(&mut self, line: usize, start: usize, end: usize, string: &str) {
103+
if start == end {
104+
return;
105+
}
106+
let _ = self.lines[line].drain(start..(end - string.chars().count()));
107+
for (i, c) in string.chars().enumerate() {
108+
self.lines[line][start + i] = StyledChar::new(c, ElementStyle::LineNumber);
109+
}
110+
}
111+
102112
/// For given `line` inserts `string` with `style` before old content of that line,
103113
/// adding lines if needed
104114
pub(crate) fn prepend(&mut self, line: usize, string: &str, style: ElementStyle) {

tests/rustc_tests.rs

Lines changed: 8 additions & 8 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)