feat(diagnostics): change color displays

related #203
This commit is contained in:
Boshen 2023-03-26 21:20:54 +08:00
parent 366dc3037a
commit b65e8397de
No known key found for this signature in database
GPG key ID: 9C7A8C8AB22BEBD1
6 changed files with 275 additions and 28 deletions

1
Cargo.lock generated
View file

@ -910,6 +910,7 @@ dependencies = [
name = "oxc_diagnostics"
version = "0.0.0"
dependencies = [
"is-terminal",
"miette",
"owo-colors",
"oxc_ast",

View file

@ -9,14 +9,8 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
use oxc_cli::{command, CliRunResult, LintOptions, LintRunner};
use oxc_diagnostics::miette;
fn main() -> CliRunResult {
// convert source code with hard tabs into 4 spaces,
// otherwise error label spans will have a wrong offset.
miette::set_hook(Box::new(|_| Box::new(miette::MietteHandlerOpts::new().tab_width(4).build())))
.unwrap();
let matches = command().get_matches();
let Some((subcommand, matches)) = matches.subcommand() else {
return CliRunResult::None

View file

@ -18,3 +18,4 @@ miette = { workspace = true }
unicode-width = "0.1.10"
owo-colors = { version = "3.5.0" }
textwrap = { version = "0.16.0" }
is-terminal = { version = "0.4.0" }

View file

@ -3,19 +3,19 @@
#![allow(clippy::nursery)]
#![allow(dead_code)]
/**
* origin file: https://github.com/zkat/miette/blob/78fe18e6990feacc8bdaeeb10e1439a12c111e6e/src/handlers/graphical.rs
*/
/// origin file: https://github.com/zkat/miette/blob/78fe18e6990feacc8bdaeeb10e1439a12c111e6e/src/handlers/graphical.rs
use std::fmt::{self, Write};
// use miette::diagnostic_chain::DiagnosticChain;
use miette::{
Diagnostic, GraphicalTheme, LabeledSpan, MietteError, ReportHandler, Severity, SourceCode,
SourceSpan, SpanContents,
Diagnostic, LabeledSpan, MietteError, ReportHandler, Severity, SourceCode, SourceSpan,
SpanContents,
};
use owo_colors::{OwoColorize, Style};
use unicode_width::UnicodeWidthChar;
use crate::graphical_theme::GraphicalTheme;
/**
A [`ReportHandler`] that displays a given [`Report`](crate::Report) in a
quasi-graphical way, using terminal colors, unicode drawing characters, and
@ -43,6 +43,9 @@ pub(crate) enum LinkStyle {
Link,
Text,
}
fn style() -> Style {
Style::new()
}
impl GraphicalReportHandler {
/// Create a new `GraphicalReportHandler` with the default
@ -50,7 +53,7 @@ impl GraphicalReportHandler {
pub fn new() -> Self {
Self {
links: LinkStyle::Link,
termwidth: 200,
termwidth: 600, // Changed: origin: 200
theme: GraphicalTheme::default(),
footer: None,
context_lines: 1,
@ -59,19 +62,6 @@ impl GraphicalReportHandler {
}
}
///Create a new `GraphicalReportHandler` with a given [`GraphicalTheme`].
pub fn new_themed(theme: GraphicalTheme) -> Self {
Self {
links: LinkStyle::Link,
termwidth: 200,
theme,
footer: None,
context_lines: 1,
tab_width: 4,
with_cause_chain: true,
}
}
/// Set the displayed tab width in spaces.
pub fn tab_width(mut self, width: usize) -> Self {
self.tab_width = width;
@ -214,7 +204,9 @@ impl GraphicalReportHandler {
.initial_indent(&initial_indent)
.subsequent_indent(&rest_indent);
writeln!(f, "{}", textwrap::fill(&diagnostic.to_string(), opts))?;
let title = format!("{}", diagnostic.to_string().style(severity_style));
let title = textwrap::fill(&title, opts);
writeln!(f, "{}", title)?;
// CHANGED: REMOVED
// if !self.with_cause_chain {
@ -361,10 +353,10 @@ impl GraphicalReportHandler {
Ok(())
}
fn render_context<'a>(
fn render_context(
&self,
f: &mut impl fmt::Write,
source: &'a dyn SourceCode,
source: &dyn SourceCode,
context: &LabeledSpan,
labels: &[LabeledSpan],
) -> fmt::Result {

View file

@ -0,0 +1,258 @@
#![allow(clippy::must_use_candidate)]
#![allow(clippy::pedantic)]
#![allow(clippy::nursery)]
#![allow(dead_code)]
/// origin file: https://github.com/zkat/miette/blob/78fe18e6990feacc8bdaeeb10e1439a12c111e6e/src/handlers/theme.rs
use is_terminal::IsTerminal;
use owo_colors::{style, Style};
/**
Theme used by [`GraphicalReportHandler`](crate::GraphicalReportHandler) to
render fancy [`Diagnostic`](crate::Diagnostic) reports.
A theme consists of two things: the set of characters to be used for drawing,
and the
[`owo_colors::Style`](https://docs.rs/owo-colors/latest/owo_colors/struct.Style.html)s to be used to paint various items.
You can create your own custom graphical theme using this type, or you can use
one of the predefined ones using the methods below.
*/
#[derive(Debug, Clone)]
pub struct GraphicalTheme {
/// Characters to be used for drawing.
pub characters: ThemeCharacters,
/// Styles to be used for painting.
pub styles: ThemeStyles,
}
impl GraphicalTheme {
/// ASCII-art-based graphical drawing, with ANSI styling.
pub fn ascii() -> Self {
Self { characters: ThemeCharacters::ascii(), styles: ThemeStyles::ansi() }
}
/// Graphical theme that draws using both ansi colors and unicode
/// characters.
pub fn unicode() -> Self {
Self { characters: ThemeCharacters::unicode(), styles: ThemeStyles::rgb() }
}
/// Graphical theme that draws in monochrome, while still using unicode
/// characters.
pub fn unicode_nocolor() -> Self {
Self { characters: ThemeCharacters::unicode(), styles: ThemeStyles::none() }
}
/// A "basic" graphical theme that skips colors and unicode characters and
/// just does monochrome ascii art. If you want a completely non-graphical
/// rendering of your `Diagnostic`s, check out
/// [crate::NarratableReportHandler], or write your own
/// [crate::ReportHandler]!
pub fn none() -> Self {
Self { characters: ThemeCharacters::ascii(), styles: ThemeStyles::none() }
}
}
impl Default for GraphicalTheme {
fn default() -> Self {
match std::env::var("NO_COLOR") {
_ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => {
Self::ascii()
}
Ok(string) if string != "0" => Self::unicode_nocolor(),
_ => Self::unicode(),
}
}
}
/**
Styles for various parts of graphical rendering for the [crate::GraphicalReportHandler].
*/
#[derive(Debug, Clone)]
pub struct ThemeStyles {
/// Style to apply to things highlighted as "error".
pub error: Style,
/// Style to apply to things highlighted as "warning".
pub warning: Style,
/// Style to apply to things highlighted as "advice".
pub advice: Style,
/// Style to apply to the help text.
pub help: Style,
/// Style to apply to filenames/links/URLs.
pub link: Style,
/// Style to apply to line numbers.
pub linum: Style,
/// Styles to cycle through (using `.iter().cycle()`), to render the lines
/// and text for diagnostic highlights.
pub highlights: Vec<Style>,
}
impl ThemeStyles {
/// Nice RGB colors.
/// [Credit](http://terminal.sexy/#FRUV0NDQFRUVrEFCkKlZ9L91ap-1qnWfdbWq0NDQUFBQrEFCkKlZ9L91ap-1qnWfdbWq9fX1).
pub fn rgb() -> Self {
Self {
error: style().fg_rgb::<225, 80, 80>().bold(), // CHANGED: <255, 30, 30>
warning: style().fg_rgb::<244, 191, 117>(),
advice: style().fg_rgb::<106, 159, 181>(),
help: style().fg_rgb::<106, 159, 181>(),
link: style().fg_rgb::<92, 157, 255>().bold(),
linum: style().dimmed(),
highlights: vec![
style().fg_rgb::<246, 87, 248>(),
style().fg_rgb::<30, 201, 212>(),
style().fg_rgb::<145, 246, 111>(),
],
}
}
/// ANSI color-based styles.
pub fn ansi() -> Self {
Self {
error: style().red(),
warning: style().yellow(),
advice: style().cyan(),
help: style().cyan(),
link: style().bold(),
linum: style().dimmed(),
highlights: vec![
style().magenta().bold(),
style().yellow().bold(),
style().green().bold(),
],
}
}
/// No styling. Just regular ol' monochrome.
pub fn none() -> Self {
Self {
error: style(),
warning: style(),
advice: style(),
help: style(),
link: style(),
linum: style(),
highlights: vec![style()],
}
}
}
// ----------------------------------------
// Most of these characters were taken from
// https://github.com/zesterer/ariadne/blob/e3cb394cb56ecda116a0a1caecd385a49e7f6662/src/draw.rs
/// Characters to be used when drawing when using
/// [crate::GraphicalReportHandler].
#[allow(missing_docs)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ThemeCharacters {
pub hbar: char,
pub vbar: char,
pub xbar: char,
pub vbar_break: char,
pub uarrow: char,
pub rarrow: char,
pub ltop: char,
pub mtop: char,
pub rtop: char,
pub lbot: char,
pub rbot: char,
pub mbot: char,
pub lbox: char,
pub rbox: char,
pub lcross: char,
pub rcross: char,
pub underbar: char,
pub underline: char,
pub error: String,
pub warning: String,
pub advice: String,
}
impl ThemeCharacters {
/// Fancy unicode-based graphical elements.
pub fn unicode() -> Self {
Self {
hbar: '',
vbar: '',
xbar: '',
vbar_break: '·',
uarrow: '',
rarrow: '',
ltop: '',
mtop: '',
rtop: '',
lbot: '',
mbot: '',
rbot: '',
lbox: '[',
rbox: ']',
lcross: '',
rcross: '',
underbar: '',
underline: '',
error: "×".into(),
warning: "".into(),
advice: "".into(),
}
}
/// Emoji-heavy unicode characters.
pub fn emoji() -> Self {
Self {
hbar: '',
vbar: '',
xbar: '',
vbar_break: '·',
uarrow: '',
rarrow: '',
ltop: '',
mtop: '',
rtop: '',
lbot: '',
mbot: '',
rbot: '',
lbox: '[',
rbox: ']',
lcross: '',
rcross: '',
underbar: '',
underline: '',
error: "💥".into(),
warning: "⚠️".into(),
advice: "💡".into(),
}
}
/// ASCII-art-based graphical elements. Works well on older terminals.
pub fn ascii() -> Self {
Self {
hbar: '-',
vbar: '|',
xbar: '+',
vbar_break: ':',
uarrow: '^',
rarrow: '>',
ltop: ',',
mtop: 'v',
rtop: '.',
lbot: '`',
mbot: '^',
rbot: '\'',
lbox: '[',
rbox: ']',
lcross: '|',
rcross: '|',
underbar: '|',
underline: '^',
error: "x".into(),
warning: "!".into(),
advice: ">".into(),
}
}
}

View file

@ -2,6 +2,7 @@
//! Exports `thiserror` and `miette`
mod graphic_reporter;
mod graphical_theme;
use std::{cell::RefCell, ops::Deref, path::PathBuf, rc::Rc};