Skip to content

Commit d3751d8

Browse files
committed
fix: Make Message a distinct type
This makes it clearer that we shouldn't set `id` on this. If someone wants to set an `id`, they should create a new `Group` which will have a `Title`.
1 parent 169d8e2 commit d3751d8

File tree

3 files changed

+96
-21
lines changed

3 files changed

+96
-21
lines changed

src/level.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::renderer::stylesheet::Stylesheet;
44
use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT};
5-
use crate::{OptionCow, Title};
5+
use crate::{Message, OptionCow, Title};
66
use anstyle::Style;
77
use std::borrow::Cow;
88

@@ -89,7 +89,6 @@ impl<'a> Level<'a> {
8989
level: self,
9090
id: None,
9191
text: text.into(),
92-
is_pre_styled: false,
9392
}
9493
}
9594

@@ -103,12 +102,10 @@ impl<'a> Level<'a> {
103102
/// used to normalize untrusted text before it is passed to this function.
104103
///
105104
/// </div>
106-
pub fn message(self, text: impl Into<Cow<'a, str>>) -> Title<'a> {
107-
Title {
105+
pub fn message(self, text: impl Into<Cow<'a, str>>) -> Message<'a> {
106+
Message {
108107
level: self,
109-
id: None,
110108
text: text.into(),
111-
is_pre_styled: true,
112109
}
113110
}
114111

src/renderer/mod.rs

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use crate::renderer::source_map::{
4848
};
4949
use crate::renderer::styled_buffer::StyledBuffer;
5050
use crate::snippet::Id;
51-
use crate::{Annotation, AnnotationKind, Element, Group, Origin, Patch, Snippet, Title};
51+
use crate::{Annotation, AnnotationKind, Element, Group, Message, Origin, Patch, Snippet, Title};
5252
pub use anstyle::*;
5353
use margin::Margin;
5454
use std::borrow::Cow;
@@ -303,7 +303,20 @@ impl Renderer {
303303
title,
304304
max_line_num_len,
305305
title_style,
306-
matches!(peek, Some(Element::Title(_))),
306+
matches!(peek, Some(Element::Title(_) | Element::Message(_))),
307+
buffer_msg_line_offset,
308+
);
309+
last_was_suggestion = false;
310+
}
311+
Element::Message(title) => {
312+
let title_style = TitleStyle::Secondary;
313+
let buffer_msg_line_offset = buffer.num_lines();
314+
self.render_title(
315+
&mut buffer,
316+
title,
317+
max_line_num_len,
318+
title_style,
319+
matches!(peek, Some(Element::Title(_) | Element::Message(_))),
307320
buffer_msg_line_offset,
308321
);
309322
last_was_suggestion = false;
@@ -336,6 +349,16 @@ impl Renderer {
336349
);
337350
}
338351

352+
Some(Element::Message(level))
353+
if level.level.name != Some(None) =>
354+
{
355+
self.draw_col_separator_no_space(
356+
&mut buffer,
357+
current_line,
358+
max_line_num_len + 1,
359+
);
360+
}
361+
339362
None if group_len > 1 => self.draw_col_separator_end(
340363
&mut buffer,
341364
current_line,
@@ -503,23 +526,23 @@ impl Renderer {
503526
fn render_title(
504527
&self,
505528
buffer: &mut StyledBuffer,
506-
title: &Title<'_>,
529+
title: &dyn MessageOrTitle,
507530
max_line_num_len: usize,
508531
title_style: TitleStyle,
509532
is_cont: bool,
510533
buffer_msg_line_offset: usize,
511534
) {
512535
let (label_style, title_element_style) = match title_style {
513536
TitleStyle::MainHeader => (
514-
ElementStyle::Level(title.level.level),
537+
ElementStyle::Level(title.level().level),
515538
if self.short_message {
516539
ElementStyle::NoStyle
517540
} else {
518541
ElementStyle::MainHeaderMsg
519542
},
520543
),
521544
TitleStyle::Header => (
522-
ElementStyle::Level(title.level.level),
545+
ElementStyle::Level(title.level().level),
523546
ElementStyle::HeaderMsg,
524547
),
525548
TitleStyle::Secondary => {
@@ -538,10 +561,10 @@ impl Renderer {
538561
};
539562
let mut label_width = 0;
540563

541-
if title.level.name != Some(None) {
542-
buffer.append(buffer_msg_line_offset, title.level.as_str(), label_style);
543-
label_width += title.level.as_str().len();
544-
if let Some(Id { id: Some(id), url }) = &title.id {
564+
if title.level().name != Some(None) {
565+
buffer.append(buffer_msg_line_offset, title.level().as_str(), label_style);
566+
label_width += title.level().as_str().len();
567+
if let Some(Id { id: Some(id), url }) = &title.id() {
545568
buffer.append(buffer_msg_line_offset, "[", label_style);
546569
if let Some(url) = url.as_ref() {
547570
buffer.append(
@@ -584,10 +607,10 @@ impl Renderer {
584607
label_width
585608
});
586609

587-
let (title_str, style) = if title.is_pre_styled {
588-
(title.text.to_string(), ElementStyle::NoStyle)
610+
let (title_str, style) = if title.is_pre_styled() {
611+
(title.text().to_owned(), ElementStyle::NoStyle)
589612
} else {
590-
(normalize_whitespace(&title.text), title_element_style)
613+
(normalize_whitespace(title.text()), title_element_style)
591614
};
592615
for (i, text) in title_str.lines().enumerate() {
593616
if i != 0 {
@@ -2532,6 +2555,43 @@ impl Renderer {
25322555
}
25332556
}
25342557

2558+
trait MessageOrTitle {
2559+
fn level(&self) -> &Level<'_>;
2560+
fn id(&self) -> Option<&Id<'_>>;
2561+
fn text(&self) -> &str;
2562+
fn is_pre_styled(&self) -> bool;
2563+
}
2564+
2565+
impl MessageOrTitle for Title<'_> {
2566+
fn level(&self) -> &Level<'_> {
2567+
&self.level
2568+
}
2569+
fn id(&self) -> Option<&Id<'_>> {
2570+
self.id.as_ref()
2571+
}
2572+
fn text(&self) -> &str {
2573+
self.text.as_ref()
2574+
}
2575+
fn is_pre_styled(&self) -> bool {
2576+
false
2577+
}
2578+
}
2579+
2580+
impl MessageOrTitle for Message<'_> {
2581+
fn level(&self) -> &Level<'_> {
2582+
&self.level
2583+
}
2584+
fn id(&self) -> Option<&Id<'_>> {
2585+
None
2586+
}
2587+
fn text(&self) -> &str {
2588+
self.text.as_ref()
2589+
}
2590+
fn is_pre_styled(&self) -> bool {
2591+
true
2592+
}
2593+
}
2594+
25352595
// instead of taking the String length or dividing by 10 while > 0, we multiply a limit by 10 until
25362596
// we're higher. If the loop isn't exited by the `return`, the last multiplication will wrap, which
25372597
// is OK, because while we cannot fit a higher power of 10 in a usize, the loop will end anyway.
@@ -2846,7 +2906,10 @@ fn max_line_number(groups: &[Group<'_>]) -> usize {
28462906
v.elements
28472907
.iter()
28482908
.map(|s| match s {
2849-
Element::Title(_) | Element::Origin(_) | Element::Padding(_) => 0,
2909+
Element::Title(_)
2910+
| Element::Message(_)
2911+
| Element::Origin(_)
2912+
| Element::Padding(_) => 0,
28502913
Element::Cause(cause) => {
28512914
let end = cause
28522915
.markers

src/snippet.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ impl<'a> Group<'a> {
6363
#[non_exhaustive]
6464
pub enum Element<'a> {
6565
Title(Title<'a>),
66+
Message(Message<'a>),
6667
Cause(Snippet<'a, Annotation<'a>>),
6768
Suggestion(Snippet<'a, Patch<'a>>),
6869
Origin(Origin<'a>),
@@ -75,6 +76,12 @@ impl<'a> From<Title<'a>> for Element<'a> {
7576
}
7677
}
7778

79+
impl<'a> From<Message<'a>> for Element<'a> {
80+
fn from(value: Message<'a>) -> Self {
81+
Element::Message(value)
82+
}
83+
}
84+
7885
impl<'a> From<Snippet<'a, Annotation<'a>>> for Element<'a> {
7986
fn from(value: Snippet<'a, Annotation<'a>>) -> Self {
8087
Element::Cause(value)
@@ -103,15 +110,14 @@ impl From<Padding> for Element<'_> {
103110
#[derive(Clone, Debug)]
104111
pub struct Padding;
105112

106-
/// A text [`Element`] in a [`Group`]
113+
/// A text [`Element`] to start a [`Group`]
107114
///
108115
/// See [`Level::title`] to create this.
109116
#[derive(Clone, Debug)]
110117
pub struct Title<'a> {
111118
pub(crate) level: Level<'a>,
112119
pub(crate) id: Option<Id<'a>>,
113120
pub(crate) text: Cow<'a, str>,
114-
pub(crate) is_pre_styled: bool,
115121
}
116122

117123
impl<'a> Title<'a> {
@@ -144,6 +150,15 @@ impl<'a> Title<'a> {
144150
}
145151
}
146152

153+
/// A text [`Element`] in a [`Group`]
154+
///
155+
/// See [`Level::message`] to create this.
156+
#[derive(Clone, Debug)]
157+
pub struct Message<'a> {
158+
pub(crate) level: Level<'a>,
159+
pub(crate) text: Cow<'a, str>,
160+
}
161+
147162
/// A source view [`Element`] in a [`Group`]
148163
///
149164
/// If you do not have [source][Snippet::source] available, see instead [`Origin`]

0 commit comments

Comments
 (0)