#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

#467 in Text processing

Download history 225/week @ 2024-09-09 31/week @ 2024-09-16 22/week @ 2024-09-23 64/week @ 2024-09-30 2/week @ 2024-10-07 363/week @ 2024-10-14 929/week @ 2024-10-21 792/week @ 2024-10-28 494/week @ 2024-11-04 38/week @ 2024-11-11 365/week @ 2024-11-18 344/week @ 2024-11-25 277/week @ 2024-12-02 140/week @ 2024-12-09 15/week @ 2024-12-16 17/week @ 2024-12-23

524 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