docsplay 0.1.3

A derive macro for implementing the display Trait via a doc comment and string interpolation. Fork of displaydoc
Documentation
//! This library is a fork of [displaydoc](https://crates.io/crates/displaydoc) that provides a
//! convenient derive macro for the standard library's [`core::fmt::Display`] trait.
//!
//! ```toml
//! [dependencies]
//! docsplay = "0.1"
//! ```
//!
//! *Compiler support: requires rustc 1.56+*
//!
//! ## Example
//!
//! *Demonstration alongside the [`Error`] derive macro from [`thiserror`](https://docs.rs/thiserror/1.0.25/thiserror/index.html),
//! to propagate source locations from [`io::Error`] with the `#[source]` attribute:*
//! ```rust
//! use std::io;
//! use docsplay::Display;
//! use thiserror::Error;
//!
//! #[derive(Display, Error, Debug)]
//! pub enum DataStoreError {
//!     /// data store disconnected
//!     Disconnect(#[source] io::Error),
//!     /// the data for key `{0}` is not available
//!     Redaction(String),
//!     /// invalid header (expected {expected:?}, found {found:?})
//!     InvalidHeader {
//!         expected: String,
//!         found: String,
//!     },
//!     /// unknown data store error
//!     Unknown,
//! }
//!
//! let error = DataStoreError::Redaction("CLASSIFIED CONTENT".to_string());
//! assert!("the data for key `CLASSIFIED CONTENT` is not available" == &format!("{}", error));
//! ```
//! *Note that although [`io::Error`] implements `Display`, we do not add it to the
//! generated message for `DataStoreError::Disconnect`, since it is already made available via
//! `#[source]`. See further context on avoiding duplication in error reports at the rust blog
//! [here](https://github.com/yaahc/blog.rust-lang.org/blob/master/posts/inside-rust/2021-05-15-What-the-error-handling-project-group-is-working-towards.md#duplicate-information-issue).*
//!
//! ## Details
//!
//! - A `fmt::Display` impl is generated for your enum if you provide
//!   a docstring comment on each variant as shown above in the example. The
//!   `Display` derive macro supports a shorthand for interpolating fields from
//!   the error:
//!     - `/// {var}` ⟶ `write!("{}", self.var)`
//!     - `/// {0}` ⟶ `write!("{}", self.0)`
//!     - `/// {var:?}` ⟶ `write!("{:?}", self.var)`
//!     - `/// {0:?}` ⟶ `write!("{:?}", self.0)`
//!     - `/// {0.foo()}` ⟶ `write!("{}", self.0.foo())`
//!     - `/// {0.foo():?}` ⟶ `write!("{:?}", self.0.foo())`
//! - This also works with structs and [generic types]:
//! ```rust
//! # use docsplay::Display;
//! /// oh no, an error: {0}
//! #[derive(Display)]
//! pub struct Error<E>(pub E);
//!
//! let error: Error<&str> = Error("muahaha i am an error");
//! assert!("oh no, an error: muahaha i am an error" == &format!("{}", error));
//! ```
//!
//! - Two optional attributes can be added to your types next to the derive:
//!
//!     - `#[ignore_extra_doc_attributes]` makes the macro ignore any doc
//!       comment attributes (or `///` lines) after the first.
//!
//!     - `#[prefix_enum_doc_attributes]` combines the doc comment message on
//!       your enum itself with the messages for each variant, in the format
//!       `enum: variant`. When added to an enum, the doc comment on the enum
//!       becomes mandatory. When added to any other type, it has no effect.
//!
//! - In case you want to have an independent doc comment, the
//!   `#[display("...")` attribute may be used on the variant or struct to
//!   override it.
//!
//! ## FAQ
//!
//! 1. **Is this crate `no_std` compatible?**
//!    Yes! This crate implements the [`core::fmt::Display`] trait, not the [`std::fmt::Display`] trait, so it should work in `std` and `no_std` environments. Just add `default-features = false`.
//!
//! 2. **Does this crate work with `Path` and `PathBuf` via the `Display` trait?**
//!    Yuuup. This crate uses @dtolnay's [autoref specialization technique](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md)
//!    to add a special trait for types to get the display impl. It then specializes for `Path` and
//!    `PathBuf`, and when either of these types are found, it calls `self.display()` to get a
//!    `std::path::Display<'_>` type which can be used with the `Display` format specifier!
//!
//! [`core::fmt::Display`]: https://doc.rust-lang.org/core/fmt/trait.Display.html
//! [`std::fmt::Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
//! [`Error`]: https://doc.rust-lang.org/std/error/trait.Error.html
//! [`io::Error`]: https://doc.rust-lang.org/std/io/struct.Error.html
//! [generic types]: https://doc.rust-lang.org/core/fmt/trait.Display.html#generic-type-parameters
#![doc(html_root_url = "https://docs.rs/docsplay/0.1.0")]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]

pub use docsplay_macros::Display;

#[cfg(feature = "std")]
#[doc(hidden)]
pub trait DisplayToDisplayDoc {
    fn __displaydoc_display(&self) -> Self;
}

#[cfg(feature = "std")]
impl<T: ::core::fmt::Display> DisplayToDisplayDoc for &T {
    fn __displaydoc_display(&self) -> Self {
        self
    }
}

#[cfg(feature = "std")]
pub trait PathToDisplayDoc {
    fn __displaydoc_display(&self) -> ::std::path::Display<'_>;
}

#[cfg(feature = "std")]
impl PathToDisplayDoc for &::std::path::Path {
    fn __displaydoc_display(&self) -> ::std::path::Display<'_> {
        self.display()
    }
}

#[cfg(feature = "std")]
impl PathToDisplayDoc for &::std::path::PathBuf {
    fn __displaydoc_display(&self) -> ::std::path::Display<'_> {
        self.display()
    }
}