diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d10924..6250716 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,21 @@ jobs: - name: Check wasm target run: cargo check --target wasm32-unknown-unknown --features fancy-no-syscall + no-std: + name: Check no-std build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + targets: wasm32-unknown-unknown + - name: Check no-std core build + run: cargo check --target wasm32-unknown-unknown --no-default-features + - name: Check no-std with fancy-no-syscall + run: cargo check --target wasm32-unknown-unknown --no-default-features --features fancy-no-syscall + miri: name: Miri runs-on: ubuntu-latest diff --git a/src/diagnostic_impls.rs b/src/diagnostic_impls.rs index 07391a4..5a9a65d 100644 --- a/src/diagnostic_impls.rs +++ b/src/diagnostic_impls.rs @@ -8,6 +8,9 @@ use core::{convert::Infallible, fmt::Display}; use crate::{Diagnostic, LabeledSpan, Severity, SourceCode}; +#[cfg(not(feature = "std"))] +impl crate::StdError for Infallible {} + impl Diagnostic for Infallible { fn code<'a>(&'a self) -> Option> { match *self {} diff --git a/src/eyreish/wrapper.rs b/src/eyreish/wrapper.rs index 73c6a2e..0b0ac73 100644 --- a/src/eyreish/wrapper.rs +++ b/src/eyreish/wrapper.rs @@ -209,13 +209,16 @@ impl StdError for WithSourceCode { } } -#[cfg(test)] +#[cfg(all(test, feature = "std"))] mod tests { - + #[cfg(feature = "fancy")] + use std::format; use std::{ boxed::Box, string::{String, ToString}, }; + #[cfg(feature = "fancy")] + use std::{vec, vec::Vec}; use thiserror::Error; use crate::{Diagnostic, LabeledSpan, Report, SourceCode, SourceSpan}; diff --git a/src/handler.rs b/src/handler.rs index 1efec17..6dc2df1 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -345,15 +345,27 @@ impl MietteHandlerOpts { } } + #[allow(clippy::manual_unwrap_or)] pub(crate) fn is_graphical(&self) -> bool { if let Some(force_narrated) = self.force_narrated { !force_narrated } else if let Some(force_graphical) = self.force_graphical { force_graphical - } else if let Ok(env) = std::env::var("NO_GRAPHICS") { - env == "0" } else { - true + #[cfg(feature = "fancy-no-syscall")] + { + // In no-std environment, assume graphics are available + true + } + #[cfg(not(feature = "fancy-no-syscall"))] + { + // In std environment, check NO_GRAPHICS env var + if let Ok(env) = std::env::var("NO_GRAPHICS") { + env == "0" + } else { + true + } + } } } @@ -501,7 +513,7 @@ mod syscall { // In no-std environment without color support, default to no color support false } else { - supports_color::on(supports_color::Stream::Stderr).is_some() + true // Fallback to assuming color support } } } @@ -515,7 +527,7 @@ mod syscall { // In no-std environment without color support, default to no RGB color support Some(false) } else { - supports_color::on(supports_color::Stream::Stderr).map(|color| color.has_16m) + Some(true) // Fallback to assuming RGB support } } } diff --git a/src/handlers/graphical.rs b/src/handlers/graphical.rs index 3b66aa4..74fb261 100644 --- a/src/handlers/graphical.rs +++ b/src/handlers/graphical.rs @@ -588,7 +588,7 @@ impl GraphicalReportHandler { // The snippets will overlap, so we create one Big Chunky Boi let left_end = left.offset() + left.len(); let right_end = right.offset() + right.len(); - let new_end = std::cmp::max(left_end, right_end); + let new_end = core::cmp::max(left_end, right_end); let new_span = LabeledSpan::new( left.label().map(String::from), @@ -655,7 +655,7 @@ impl GraphicalReportHandler { num_highlights += 1; } } - max_gutter = std::cmp::max(max_gutter, num_highlights); + max_gutter = core::cmp::max(max_gutter, num_highlights); } // Oh and one more thing: We need to figure out how much room our line @@ -1179,7 +1179,7 @@ impl GraphicalReportHandler { .style(hl.style) .to_string(), ); - highest = std::cmp::max(highest, end); + highest = core::cmp::max(highest, end); (hl, vbar_offset) }) diff --git a/src/handlers/theme.rs b/src/handlers/theme.rs index 64980d8..168ff89 100644 --- a/src/handlers/theme.rs +++ b/src/handlers/theme.rs @@ -71,12 +71,20 @@ impl GraphicalTheme { 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::none() + #[cfg(feature = "fancy-no-syscall")] + { + // In no-std environments, default to no-color mode + Self::unicode_nocolor() + } + #[cfg(not(feature = "fancy-no-syscall"))] + { + match std::env::var("NO_COLOR") { + _ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => { + Self::none() + } + Ok(string) if string != "0" => Self::unicode_nocolor(), + _ => Self::unicode(), } - Ok(string) if string != "0" => Self::unicode_nocolor(), - _ => Self::unicode(), } } } diff --git a/src/highlighters/mod.rs b/src/highlighters/mod.rs index 5f95836..398ad36 100644 --- a/src/highlighters/mod.rs +++ b/src/highlighters/mod.rs @@ -11,7 +11,7 @@ //! * `syntect-highlighter` - Enables [`syntect`](https://docs.rs/syntect/latest/syntect/) syntax highlighting support via the [`SyntectHighlighter`] //! -use std::{ops::Deref, sync::Arc}; +use core::ops::Deref; extern crate alloc; use alloc::boxed::Box; @@ -83,21 +83,28 @@ impl MietteHighlighter { } impl Default for MietteHighlighter { - #[cfg(feature = "syntect-highlighter")] fn default() -> Self { - use std::io::IsTerminal; - match std::env::var("NO_COLOR") { - _ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => { - //TODO: should use ANSI styling instead of 24-bit truecolor here - Self(Arc::new(SyntectHighlighter::default())) + #[cfg(all(feature = "syntect-highlighter", not(feature = "fancy-no-syscall")))] + { + use std::io::IsTerminal; + match std::env::var("NO_COLOR") { + _ if !std::io::stdout().is_terminal() || !std::io::stderr().is_terminal() => { + //TODO: should use ANSI styling instead of 24-bit truecolor here + Self(Arc::new(SyntectHighlighter::default())) + } + Ok(string) if string != "0" => MietteHighlighter::nocolor(), + _ => Self(Arc::new(SyntectHighlighter::default())), } - Ok(string) if string != "0" => MietteHighlighter::nocolor(), - _ => Self(Arc::new(SyntectHighlighter::default())), } - } - #[cfg(not(feature = "syntect-highlighter"))] - fn default() -> Self { - MietteHighlighter::nocolor() + #[cfg(all(feature = "syntect-highlighter", feature = "fancy-no-syscall"))] + { + // In no-std environment, use syntect but without terminal detection + Self(Arc::new(SyntectHighlighter::default())) + } + #[cfg(not(feature = "syntect-highlighter"))] + { + MietteHighlighter::nocolor() + } } } @@ -107,8 +114,8 @@ impl From for MietteHighlighter { } } -impl std::fmt::Debug for MietteHighlighter { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Debug for MietteHighlighter { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "MietteHighlighter(...)") } } diff --git a/src/protocol.rs b/src/protocol.rs index 636aefa..ef6f7e0 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -9,6 +9,7 @@ use alloc::boxed::Box; use alloc::string::String; use core::fmt::{self, Display}; use core::ops; +#[cfg(feature = "std")] use core::panic::Location; #[cfg(feature = "std")] use std::fs; @@ -16,7 +17,7 @@ use std::fs; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -use crate::{DiagnosticError, MietteError}; +use crate::MietteError; /// Adds rich metadata to your Error that can be used by /// [`Report`](crate::Report) to print really nice and human-friendly error @@ -172,6 +173,9 @@ impl From for Box { } } +#[cfg(feature = "std")] +use crate::DiagnosticError; + #[cfg(feature = "std")] impl From> for Box { fn from(s: Box) -> Self {