Skip to content

Commit 353a040

Browse files
committed
feat: Add custom Levels
1 parent ab5ca18 commit 353a040

19 files changed

+352
-263
lines changed

Diff for: benches/bench.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
22

33
#[divan::bench]
44
fn simple() -> String {
@@ -24,7 +24,7 @@ fn simple() -> String {
2424
_ => continue,
2525
}
2626
}"#;
27-
let message = Level::Error.message("mismatched types").id("E0308").group(
27+
let message = Level::ERROR.message("mismatched types").id("E0308").group(
2828
Group::new().element(
2929
Snippet::source(source)
3030
.line_start(51)
@@ -69,7 +69,7 @@ fn fold(bencher: divan::Bencher<'_, '_>, context: usize) {
6969
(input, span)
7070
})
7171
.bench_values(|(input, span)| {
72-
let message = Level::Error.message("mismatched types").id("E0308").group(
72+
let message = Level::ERROR.message("mismatched types").id("E0308").group(
7373
Group::new().element(
7474
Snippet::source(&input)
7575
.fold(true)

Diff for: examples/custom_error.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use annotate_snippets::renderer::OutputTheme;
2-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
2+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
33

44
fn main() {
55
let source = r#"//@ compile-flags: -Ztreat-err-as-bug
@@ -15,8 +15,10 @@ fn main() {
1515
pub static C: u32 = 0 - 1;
1616
//~^ ERROR could not evaluate static initializer
1717
"#;
18-
let message = Level::None
19-
.message("error: internal compiler error[E0080]: could not evaluate static initializer")
18+
let message = Level::ERROR
19+
.text(Some("error: internal compiler error"))
20+
.message("could not evaluate static initializer")
21+
.id("E0080")
2022
.group(
2123
Group::new().element(
2224
Snippet::source(source)

Diff for: examples/custom_error.svg

+3-2
Loading

Diff for: examples/custom_level.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use annotate_snippets::renderer::OutputTheme;
2-
use annotate_snippets::{AnnotationKind, Group, Level, Patch, Renderer, Snippet};
2+
use annotate_snippets::{level::Level, AnnotationKind, Group, Patch, Renderer, Snippet};
33

44
fn main() {
55
let source = r#"// Regression test for issue #114529
@@ -29,7 +29,7 @@ fn main() {
2929
}
3030
}
3131
"#;
32-
let message = Level::Error
32+
let message = Level::ERROR
3333
.message("`break` with value from a `while` loop")
3434
.id("E0571")
3535
.group(
@@ -52,9 +52,11 @@ fn main() {
5252
)
5353
.group(
5454
Group::new()
55-
.element(Level::None.title(
56-
"suggestion: use `break` on its own without a value inside this `while` loop",
57-
))
55+
.element(
56+
Level::HELP
57+
.text(Some("suggestion"))
58+
.title("use `break` on its own without a value inside this `while` loop"),
59+
)
5860
.element(
5961
Snippet::source(source)
6062
.line_start(1)

Diff for: examples/custom_level.svg

+2-1
Loading

Diff for: examples/expected_type.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
22

33
fn main() {
44
let source = r#" annotations: vec![SourceAnnotation {
55
label: "expected struct `annotate_snippets::snippet::Slice`, found reference"
66
,
77
range: <22, 25>,"#;
88
let message =
9-
Level::Error.message("expected type, found `22`").group(
9+
Level::ERROR.message("expected type, found `22`").group(
1010
Group::new().element(
1111
Snippet::source(source)
1212
.line_start(26)

Diff for: examples/footer.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
22

33
fn main() {
4-
let message = Level::Error
4+
let message = Level::ERROR
55
.message("mismatched types")
66
.id("E0308")
77
.group(
@@ -14,7 +14,7 @@ fn main() {
1414
)),
1515
),
1616
)
17-
.group(Group::new().element(Level::Note.title(
17+
.group(Group::new().element(Level::NOTE.title(
1818
"expected type: `snippet::Annotation`\n found type: `__&__snippet::Annotation`",
1919
)));
2020

Diff for: examples/format.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
22

33
fn main() {
44
let source = r#") -> Option<String> {
@@ -23,7 +23,7 @@ fn main() {
2323
_ => continue,
2424
}
2525
}"#;
26-
let message = Level::Error.message("mismatched types").id("E0308").group(
26+
let message = Level::ERROR.message("mismatched types").id("E0308").group(
2727
Group::new().element(
2828
Snippet::source(source)
2929
.line_start(51)

Diff for: examples/highlight_source.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
22

33
fn main() {
44
let source = r#"//@ compile-flags: -Z teach
@@ -9,7 +9,7 @@ const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010
99
//~| ERROR cannot call non-const method
1010
fn main() {}
1111
"#;
12-
let message = Level::Error
12+
let message = Level::ERROR
1313
.message("allocations are not allowed in constants")
1414
.id("E0010")
1515
.group(
@@ -26,7 +26,7 @@ fn main() {}
2626
),
2727
)
2828
.element(
29-
Level::Note.title("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."),
29+
Level::NOTE.title("The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created."),
3030
),
3131
);
3232

Diff for: examples/highlight_title.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, AnnotationKind, Group, Renderer, Snippet};
22
use anstyle::Effects;
33

44
fn main() {
@@ -43,7 +43,7 @@ fn main() {
4343
magenta.render_reset()
4444
);
4545

46-
let message = Level::Error.message("mismatched types").id("E0308").group(
46+
let message = Level::ERROR.message("mismatched types").id("E0308").group(
4747
Group::new()
4848
.element(
4949
Snippet::source(source)
@@ -60,7 +60,7 @@ fn main() {
6060
.label("arguments to this function are incorrect"),
6161
),
6262
)
63-
.element(Level::Note.title(&title)),
63+
.element(Level::NOTE.title(&title)),
6464
);
6565

6666
let renderer = Renderer::styled().anonymized_line_numbers(true);

Diff for: examples/multislice.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use annotate_snippets::{Annotation, Group, Level, Renderer, Snippet};
1+
use annotate_snippets::{level::Level, Annotation, Group, Renderer, Snippet};
22

33
fn main() {
4-
let message = Level::Error.message("mismatched types").group(
4+
let message = Level::ERROR.message("mismatched types").group(
55
Group::new()
66
.element(
77
Snippet::<Annotation<'_>>::source("Foo")

Diff for: src/level.rs

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use crate::renderer::stylesheet::Stylesheet;
2+
use crate::snippet::{ERROR_TXT, HELP_TXT, INFO_TXT, NOTE_TXT, WARNING_TXT};
3+
use crate::{Element, Group, Message, Title};
4+
use anstyle::Style;
5+
6+
pub const ERROR: Level<'_> = Level {
7+
name: None,
8+
level: LevelInner::Error,
9+
};
10+
11+
pub const WARNING: Level<'_> = Level {
12+
name: None,
13+
level: LevelInner::Warning,
14+
};
15+
16+
pub const INFO: Level<'_> = Level {
17+
name: None,
18+
level: LevelInner::Info,
19+
};
20+
21+
pub const NOTE: Level<'_> = Level {
22+
name: None,
23+
level: LevelInner::Note,
24+
};
25+
26+
pub const HELP: Level<'_> = Level {
27+
name: None,
28+
level: LevelInner::Help,
29+
};
30+
31+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
32+
pub struct Level<'a> {
33+
pub(crate) name: Option<Option<&'a str>>,
34+
pub(crate) level: LevelInner,
35+
}
36+
37+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
38+
pub enum Level2<'a> {
39+
Builtin(LevelInner),
40+
Custom {
41+
name: Option<&'a str>,
42+
level: LevelInner,
43+
},
44+
None,
45+
}
46+
47+
impl<'a> Level<'a> {
48+
pub const ERROR: Level<'a> = ERROR;
49+
pub const WARNING: Level<'a> = WARNING;
50+
pub const INFO: Level<'a> = INFO;
51+
pub const NOTE: Level<'a> = NOTE;
52+
pub const HELP: Level<'a> = HELP;
53+
54+
/// Text passed to this function is considered "untrusted input", as such
55+
/// all text is passed through a normalization function. Pre-styled text is
56+
/// not allowed to be passed to this function.
57+
pub fn text(self, text: Option<&'a str>) -> Level<'a> {
58+
Level {
59+
name: Some(text),
60+
level: self.level,
61+
}
62+
}
63+
}
64+
65+
impl<'a> Level<'a> {
66+
/// Text passed to this function is considered "untrusted input", as such
67+
/// all text is passed through a normalization function. Pre-styled text is
68+
/// not allowed to be passed to this function.
69+
pub fn message(self, title: &'a str) -> Message<'a> {
70+
Message {
71+
id: None,
72+
groups: vec![Group::new().element(Element::Title(Title {
73+
level: self,
74+
title,
75+
primary: true,
76+
}))],
77+
}
78+
}
79+
80+
/// Text passed to this function is allowed to be pre-styled, as such all
81+
/// text is considered "trusted input" and has no normalizations applied to
82+
/// it. [`normalize_untrusted_str`](crate::normalize_untrusted_str) can be
83+
/// used to normalize untrusted text before it is passed to this function.
84+
pub fn title(self, title: &'a str) -> Title<'a> {
85+
Title {
86+
level: self,
87+
title,
88+
primary: false,
89+
}
90+
}
91+
92+
pub(crate) fn as_str(&self) -> &'a str {
93+
match (self.name, self.level) {
94+
(Some(Some(name)), _) => name,
95+
(Some(None), _) => "",
96+
(None, LevelInner::Error) => ERROR_TXT,
97+
(None, LevelInner::Warning) => WARNING_TXT,
98+
(None, LevelInner::Info) => INFO_TXT,
99+
(None, LevelInner::Note) => NOTE_TXT,
100+
(None, LevelInner::Help) => HELP_TXT,
101+
}
102+
}
103+
104+
pub(crate) fn style(&self, stylesheet: &Stylesheet) -> Style {
105+
self.level.style(stylesheet)
106+
}
107+
}
108+
109+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
110+
pub enum LevelInner {
111+
Error,
112+
Warning,
113+
Info,
114+
Note,
115+
Help,
116+
}
117+
118+
impl LevelInner {
119+
pub(crate) fn style(self, stylesheet: &Stylesheet) -> Style {
120+
match self {
121+
LevelInner::Error => stylesheet.error,
122+
LevelInner::Warning => stylesheet.warning,
123+
LevelInner::Info => stylesheet.info,
124+
LevelInner::Note => stylesheet.note,
125+
LevelInner::Help => stylesheet.help,
126+
}
127+
}
128+
}

Diff for: src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#![warn(clippy::print_stdout)]
4343
#![warn(missing_debug_implementations)]
4444

45+
pub mod level;
4546
pub mod renderer;
4647
mod snippet;
4748

0 commit comments

Comments
 (0)