#![doc = r#"
<pre>
<span style="color:#DD3311;"><b>unable to load configuration</b></span>
├╴at <span style="color:#888888;">crates/reportify/examples/config.rs:18:10</span>
├╴path: config.toml
├╴suggestion: <span style="color:#0099DD;">create one by copying `config.example.toml` to `config.toml`</span>
│
╰─▶ cause: <span style="color:#DD3311;"><b>file not found</b></span>
╰╴at <span style="color:#888888;">crates/reportify/examples/config.rs:17:5</span>
</pre>
"#]
#![doc = r#"
<pre>
<span style="color:#DD3311;"><b>configuration is invalid</b></span>
├╴at <span style="color:#888888;">crates/reportify/examples/config.rs:27:5</span>
├╴path: config.toml
│
├─▶ factor: <span style="color:#DD3311;"><b>port must be between 1 and 65535</b></span>
│ ╰╴at <span style="color:#888888;">crates/reportify/examples/config.rs:30:13</span>
│
╰─▶ factor: <span style="color:#DD3311;"><b>unknown log level `verbos`</b></span>
╰╴at <span style="color:#888888;">crates/reportify/examples/config.rs:31:13</span>
</pre>
"#]
#![doc = r"
<pre>
configuration is invalid
|-at crates/reportify/examples/config.rs:27:5
|-path: config.toml
|
|-> factor: port must be between 1 and 65535
| \-at crates/reportify/examples/config.rs:30:13
|
\-> factor: unknown log level `verbos`
\-at crates/reportify/examples/config.rs:31:13
</pre>
"]
#![doc = r#"
<pre>
<span style="color:#DD3311;"><b>configuration is invalid</b></span>
├╴path: config.toml
│
├─▶ factor: <span style="color:#DD3311;"><b>port must be between 1 and 65535</b></span>
│
╰─▶ factor: <span style="color:#DD3311;"><b>unknown log level `verbos`</b></span>
</pre>
"#]
#![doc = r#"
<pre>
<span style="color:#DD3311;"><b>unable to load configuration</b></span>
├╴at <span style="color:#888888;">crates/reportify/examples/config.rs:36:5</span>
╰╴BACKTRACE (1)
━━━━ BACKTRACE (1)
⋮ skipped 3 frames
4: <span style="color:#0099DD;">config::load_config</span> <span style="color:#888888;">(0x74178)</span>
at crates/reportify/examples/config.rs:36:5
5: <span style="color:#0099DD;">config::run</span> <span style="color:#888888;">(0x74405)</span>
at crates/reportify/examples/config.rs:40:5
6: <span style="color:#0099DD;">config::main</span> <span style="color:#888888;">(0x74db1)</span>
at crates/reportify/examples/config.rs:71:9
7: <span style="color:#0099DD;">core::ops::function::FnOnce::call_once</span> <span style="color:#888888;">(0x7336a)</span>
at /home/develop/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:250:5
⋮ skipped 9 frames
</pre>
"#]
mod trailer;
mod tree;
use std::fmt::Display;
use crate::context::Context;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct RenderOptions {
pub charset: Charset,
pub color: ColorMode,
pub detail: Detail,
pub wrap: WrapMode,
}
impl Default for RenderOptions {
fn default() -> Self {
Self {
charset: Charset::Unicode,
color: ColorMode::AutoStderr,
detail: Detail::Full,
wrap: WrapMode::Never,
}
}
}
impl RenderOptions {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn ascii(mut self) -> Self {
self.charset = Charset::Ascii;
self
}
#[must_use]
pub fn unicode(mut self) -> Self {
self.charset = Charset::Unicode;
self
}
#[must_use]
pub fn charset(mut self, charset: Charset) -> Self {
self.charset = charset;
self
}
#[must_use]
pub fn color(mut self, mode: ColorMode) -> Self {
self.color = mode;
self
}
#[must_use]
pub fn for_stdout(mut self) -> Self {
if matches!(self.color, ColorMode::AutoStdout | ColorMode::AutoStderr) {
self.color = ColorMode::AutoStdout;
}
if matches!(self.wrap, WrapMode::AutoStdout | WrapMode::AutoStderr) {
self.wrap = WrapMode::AutoStdout;
}
self
}
#[must_use]
pub fn for_stderr(mut self) -> Self {
if matches!(self.color, ColorMode::AutoStdout | ColorMode::AutoStderr) {
self.color = ColorMode::AutoStderr;
}
if matches!(self.wrap, WrapMode::AutoStdout | WrapMode::AutoStderr) {
self.wrap = WrapMode::AutoStderr;
}
self
}
#[must_use]
pub fn compact(mut self) -> Self {
self.detail = Detail::Compact;
self
}
#[must_use]
pub fn full(mut self) -> Self {
self.detail = Detail::Full;
self
}
#[must_use]
pub fn verbose(mut self) -> Self {
self.detail = Detail::Verbose;
self
}
#[must_use]
pub fn detail(mut self, detail: Detail) -> Self {
self.detail = detail;
self
}
#[must_use]
pub fn wrap(mut self, mode: WrapMode) -> Self {
self.wrap = mode;
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Charset {
Unicode,
Ascii,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ColorMode {
AutoStdout,
AutoStderr,
Always,
Never,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Detail {
Compact,
Full,
Verbose,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum WrapMode {
Never,
Fixed(usize),
AutoStdout,
AutoStderr,
}
pub(crate) fn render(
type_name: &'static str,
message: Option<&dyn Display>,
code: Option<&'static str>,
context: &Context,
options: RenderOptions,
) -> String {
tree::render(type_name, message, code, context, options)
}
#[cfg(feature = "color")]
pub(crate) fn styled<D: Display>(
styled: console::StyledObject<D>,
color: ColorMode,
) -> console::StyledObject<D> {
match color {
ColorMode::AutoStdout => styled.for_stdout(),
ColorMode::AutoStderr => styled.for_stderr(),
ColorMode::Always => styled.force_styling(true),
ColorMode::Never => styled.force_styling(false),
}
}
#[cfg(feature = "color")]
pub(crate) fn resolve_wrap_width(wrap: WrapMode) -> Option<usize> {
match wrap {
WrapMode::Never => None,
WrapMode::Fixed(width) => Some(width),
WrapMode::AutoStdout => console::Term::stdout()
.size_checked()
.map(|(_rows, columns)| columns as usize),
WrapMode::AutoStderr => console::Term::stderr()
.size_checked()
.map(|(_rows, columns)| columns as usize),
}
}
#[cfg(not(feature = "color"))]
pub(crate) fn resolve_wrap_width(wrap: WrapMode) -> Option<usize> {
match wrap {
WrapMode::Fixed(width) => Some(width),
WrapMode::Never | WrapMode::AutoStdout | WrapMode::AutoStderr => None,
}
}