#annotations #report #error #code

sourceannot

A library to render snippets of source code with annotations

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

Download history 54/week @ 2024-08-17 59/week @ 2024-08-24 42/week @ 2024-08-31 265/week @ 2024-09-07 56/week @ 2024-09-14 23/week @ 2024-09-21 51/week @ 2024-09-28 16/week @ 2024-10-05 120/week @ 2024-10-12 715/week @ 2024-10-19 1026/week @ 2024-10-26 708/week @ 2024-11-02 40/week @ 2024-11-09 266/week @ 2024-11-16 351/week @ 2024-11-23 341/week @ 2024-11-30

1,008 downloads per month
Used in 2 crates (via rsjsonnet-front)

MIT/Apache

82KB
2K SLoC

sourceannot

GitHub Actions Status crates.io Documentation MSRV License

A library to render snippets of source code with annotations.

License

Licensed under either of

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