4 releases
0.2.1 | Aug 13, 2024 |
---|---|
0.2.0 | Apr 21, 2024 |
0.1.1 | Mar 30, 2024 |
0.1.0 | Mar 26, 2024 |
#304 in Text processing
1,008 downloads per month
Used in 2 crates
(via rsjsonnet-front)
82KB
2K
SLoC
sourceannot
A library to render snippets of source code with annotations.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or https://opensource.org/licenses/MIT)
at your option.
lib.rs
:
A library to render snippets of source code with annotations. It is meant to be used as a building block for compiler diagnostics.
This crate is #![no_std]
, but it depends on alloc
.
Example
// Some source code
let source = indoc::indoc! {r#"
fn main() {
println!("Hello, world!");
}
"#};
// Create the snippet
let snippet = sourceannot::SourceSnippet::build_from_utf8(1, source.as_bytes(), 4);
// Styles are generic over the type of the metadata that accompanies each
// chunk of rendered text. In this example, we will use the following enum:
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Color {
Default,
Red,
Green,
Blue,
}
// If do not you need this per-chunk metadata, you can use `()` instead.
// Define the styles
// Use Unicode box drawing characters
let main_style = sourceannot::MainStyle {
margin: Some(sourceannot::MarginStyle {
line_char: '│',
dot_char: '·',
meta: Color::Blue,
}),
horizontal_char: '─',
vertical_char: '│',
top_vertical_char: '╭',
top_corner_char: '╭',
bottom_corner_char: '╰',
spaces_meta: Color::Default,
text_normal_meta: Color::Default,
text_alt_meta: Color::Default,
};
// You can use a different style for each annotation, but in
// this example we will use the same style for all of them.
let annot_style = sourceannot::AnnotStyle {
caret: '^',
text_normal_meta: Color::Red,
text_alt_meta: Color::Red,
line_meta: Color::Red,
};
// Create the annotations
let mut annotations = sourceannot::Annotations::new(&snippet, main_style);
annotations.add_annotation(
0..44,
annot_style,
vec![("this is the `main` function".into(), Color::Red)],
);
annotations.add_annotation(
16..24,
annot_style,
vec![("this is a macro invocation".into(), Color::Red)],
);
// Render the snippet with annotations
let max_line_no_width = annotations.max_line_no_width();
let rendered = annotations.render(max_line_no_width, 0, 0);
// `rendered` is a `Vec<(String, Color)>`, which you could print with
// your favorite terminal coloring library. In this example, we will
// ignore the colors.
for (chunk, _) in rendered.iter() {
eprint!("{chunk}");
}
The output will look like this:
1 │ ╭ fn main() {
2 │ │ println!(\"Hello, world!\");
│ │ ^^^^^^^^ this is a macro invocation
3 │ │ }
│ ╰─^ this is the `main` function
Dependencies
~1.5MB
~19K SLoC