Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 11a8e92

Browse files
authored
Merge pull request #230 from Muscraft/hyperlink-support
Add suppost for Hyperlinks on IDs
2 parents 24c8eaa + bff9dd5 commit 11a8e92

File tree

6 files changed

+124
-17
lines changed

6 files changed

+124
-17
lines changed

‎Cargo.lock‎

Lines changed: 7 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎examples/id_hyperlink.rs‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use annotate_snippets::renderer::OutputTheme;
2+
use annotate_snippets::{AnnotationKind, Group, Level, Renderer, Snippet};
3+
4+
fn main() {
5+
let source = r#"//@ compile-flags: -Zterminal-urls=yes
6+
fn main() {
7+
let () = 4; //~ ERROR
8+
}
9+
"#;
10+
let message = Level::ERROR
11+
.header("mismatched types")
12+
.id("E0308")
13+
.id_url("https://doc.rust-lang.org/error_codes/E0308.html")
14+
.group(
15+
Group::new().element(
16+
Snippet::source(source)
17+
.line_start(1)
18+
.path("$DIR/terminal_urls.rs")
19+
.fold(true)
20+
.annotation(
21+
AnnotationKind::Primary
22+
.span(59..61)
23+
.label("expected integer, found `()`"),
24+
)
25+
.annotation(
26+
AnnotationKind::Context
27+
.span(64..65)
28+
.label("this expression has type `{integer}`"),
29+
),
30+
),
31+
);
32+
33+
let renderer = Renderer::styled().theme(OutputTheme::Unicode);
34+
anstream::println!("{}", renderer.render(message));
35+
}

‎examples/id_hyperlink.svg‎

Lines changed: 40 additions & 0 deletions
Loading[フレーム]

‎src/renderer/mod.rs‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use crate::renderer::source_map::{
4646
AnnotatedLineInfo, LineInfo, Loc, SourceMap, SubstitutionHighlight,
4747
};
4848
use crate::renderer::styled_buffer::StyledBuffer;
49+
use crate::snippet::Id;
4950
use crate::{Annotation, AnnotationKind, Element, Group, Message, Origin, Patch, Snippet, Title};
5051
pub use anstyle::*;
5152
use margin::Margin;
@@ -545,7 +546,7 @@ impl Renderer {
545546
title: &Title<'_>,
546547
max_line_num_len: usize,
547548
title_style: TitleStyle,
548-
id: Option<&&str>,
549+
id: Option<&Id<'_>>,
549550
is_cont: bool,
550551
buffer_msg_line_offset: usize,
551552
) {
@@ -620,17 +621,31 @@ impl Renderer {
620621
);
621622
}
622623
label_width += title.level.as_str().len();
623-
if let Some(id) = id {
624+
if let Some(Id{id:Some(id), url }) = id {
624625
buffer.append(
625626
buffer_msg_line_offset,
626627
"[",
627628
ElementStyle::Level(title.level.level),
628629
);
630+
if let Some(url) = url.as_ref() {
631+
buffer.append(
632+
buffer_msg_line_offset,
633+
&format!("\x1B]8;;{url}\x1B\\"),
634+
ElementStyle::Level(title.level.level),
635+
);
636+
}
629637
buffer.append(
630638
buffer_msg_line_offset,
631639
id,
632640
ElementStyle::Level(title.level.level),
633641
);
642+
if url.is_some() {
643+
buffer.append(
644+
buffer_msg_line_offset,
645+
"\x1B]8;;\x1B\\",
646+
ElementStyle::Level(title.level.level),
647+
);
648+
}
634649
buffer.append(
635650
buffer_msg_line_offset,
636651
"]",

‎src/snippet.rs‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub(crate) const WARNING_TXT: &str = "warning";
1313
/// Top-level user message
1414
#[derive(Clone, Debug)]
1515
pub struct Message<'a> {
16-
pub(crate) id: Option<&'astr>, // for "correctness", could be sloppy and be on Title
16+
pub(crate) id: Option<Id<'a>>, // for "correctness", could be sloppy and be on Title
1717
pub(crate) groups: Vec<Group<'a>>,
1818
}
1919

@@ -26,7 +26,17 @@ impl<'a> Message<'a> {
2626
///
2727
/// </div>
2828
pub fn id(mut self, id: &'a str) -> Self {
29-
self.id = Some(id);
29+
self.id.get_or_insert(Id::default()).id = Some(id);
30+
self
31+
}
32+
33+
/// <div class="warning">
34+
///
35+
/// This is only relevant if the `id` present
36+
///
37+
/// </div>
38+
pub fn id_url(mut self, url: &'a str) -> Self {
39+
self.id.get_or_insert(Id::default()).url = Some(url);
3040
self
3141
}
3242

@@ -75,6 +85,12 @@ impl<'a> Message<'a> {
7585
}
7686
}
7787

88+
#[derive(Clone, Debug, Default)]
89+
pub(crate) struct Id<'a> {
90+
pub(crate) id: Option<&'a str>,
91+
pub(crate) url: Option<&'a str>,
92+
}
93+
7894
/// An [`Element`] container
7995
#[derive(Clone, Debug)]
8096
pub struct Group<'a> {

‎tests/examples.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ fn highlight_title() {
4949
assert_example(target, expected);
5050
}
5151

52+
#[test]
53+
fn id_hyperlink() {
54+
let target = "id_hyperlink";
55+
let expected = snapbox::file!["../examples/id_hyperlink.svg": TermSvg];
56+
assert_example(target, expected);
57+
}
58+
5259
#[test]
5360
fn multislice() {
5461
let target = "multislice";

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /