#![doc = include_str!("../README.md")] #![forbid(unsafe_code)] #![warn( clippy::missing_const_for_fn, clippy::redundant_pub_crate, clippy::imprecise_flops, clippy::dbg_macro, missing_docs )] use anstream::adapter::strip_str; use comat::{cwrite, cwriteln}; use config::Charset; use std::{fmt::Write, ops::Range}; use unicode_width::UnicodeWidthStr; pub mod config; /// Span of bytes in the source pub type Span = Range; /// Label around a [`Span`] #[derive(Debug, Clone)] pub struct Label { /// The span that this label will draw at pub span: Span, /// The message this label will draw with pub message: String, } impl From<(Span, S)> for Label { fn from((span, m): (Span, S)) -> Self { Self { span, message: m.to_string(), } } } impl From<(&Span, S)> for Label { fn from((span, m): (&Span, S)) -> Self { Self { span: span.clone(), message: m.to_string(), } } } /// A note at the end of the diagnostic #[derive(Debug)] pub struct Note { /// The note pub message: String, } /// The source text that the spans "reference" #[derive(Debug)] pub struct Source<'s>(&'s str); impl<'s> Source<'s> { fn spans(&self) -> impl Iterator { self.0.split_inclusive('\n').scan(0, |s, x| { let pos = *s; *s += x.as_bytes().len(); let s = x.trim_matches('\n'); Some((s, pos..pos + s.len())) }) } } /// The error builder that this crate is all about #[derive(Debug)] #[non_exhaustive] pub struct Error<'s> { /// The message pub message: String, /// Source text pub source: Source<'s>, /// Labels we hold pub labels: Vec