jjpwrgem-ui 0.3.2

renders jjpwrgem diagnostics
Documentation
mod diagnostic {
    use annotate_snippets::{Annotation, AnnotationKind, Group, Level, Snippet};
    use jjpwrgem_parse::diagnostics::{Context, Diagnostic, Patch, Source};
    fn patch_to_patch(patch: Patch<'_>) -> annotate_snippets::Patch<'_> {
        annotate_snippets::Patch::new(patch.span.into(), patch.replacement)
    }

    fn source_to_snippet<T: Clone>(val: Source<'_>) -> Snippet<'_, T> {
        let (source, path) = match val {
            Source::Stdin(src) => (src, "stdin"),
            Source::File { source, path } => (
                source,
                path.to_str()
                    .expect("diagnostic paths should be valid utf8"),
            ),
        };
        Snippet::source(source).path(path)
    }

    fn context_to_annotation(ctx: Context<'_>) -> Annotation<'_> {
        let Context { message, span, .. } = ctx;
        AnnotationKind::Context.span(span.into()).label(message)
    }

    pub(crate) fn report_diagnostic(
        Diagnostic {
            message,
            context,
            patches,
            source,
            range,
        }: Diagnostic<'_>,
    ) -> Vec<Group<'_>> {
        let annotations = if let Some(range) = range {
            std::iter::once(AnnotationKind::Primary.span(range.into()))
                .chain(context.into_iter().map(context_to_annotation))
                .collect()
        } else {
            vec![]
        };

        let error_group = Level::ERROR
            .primary_title(message)
            .element(source_to_snippet(source).annotations(annotations));
        let patch_group = patches.into_iter().map(|patch| {
            Level::HELP
                .primary_title(patch.message.clone())
                .element(source_to_snippet(source).patches(vec![patch_to_patch(patch)]))
        });

        std::iter::once(error_group).chain(patch_group).collect()
    }
}

mod message {
    use annotate_snippets::{Group, Level};

    use crate::BasicErrorMessage;

    pub(crate) fn report_message<'a>(message: BasicErrorMessage) -> Vec<Group<'a>> {
        let error = Some(Level::ERROR.primary_title(message.error));
        let help = message.help.map(|x| Level::HELP.primary_title(x));

        [error, help]
            .into_iter()
            .flatten()
            .map(Group::with_title)
            .collect()
    }
}

pub(crate) use diagnostic::report_diagnostic;
pub(crate) use message::report_message;