docsrs
only.Expand description
§Writing Custom Formatters
How to write custom formatters, either for formatting output from your own matchers, or for changing the formatting of the provided matchers.
§Writing a formatter
Most of the time, when writing matchers, you should be able to reuse existing
formatters in crate::format
. However, if you want to write a formatter for
your custom matcher, or even to change the formatting of an existing matcher,
here’s how to do it.
Matcher formatters are types that implement the MatcherFormat
trait.
However, you can instead implement the more generic Format
trait, which will
implement MatcherFormat
via a blanket impl.
Let’s write a simple formatter that accepts a Mismatch
and prints that the
two values are not equal. This is an example; in practice, you can just use
MismatchFormat
for this.
We’ll also need to write our own equal
function that calls our formatter
instead of the provided one. Notice that we don’t need to reimplement me logic
of the matcher; we can just reuse the existing EqualMatcher
and plug in our
custom formatter.
use std::fmt;
use std::marker::PhantomData;
use xpct::core::{whitespace, Format, Formatter, MatchFailure, Matcher};
use xpct::matchers::equal::EqualMatcher;
use xpct::matchers::Mismatch;
#[derive(Debug)]
pub struct NotEqualFormat<Actual, Expected> {
marker: PhantomData<(Actual, Expected)>,
}
impl<Actual, Expected> NotEqualFormat<Actual, Expected> {
pub fn new() -> Self {
Self {
marker: PhantomData,
}
}
}
impl<Actual, Expected> Format for NotEqualFormat<Actual, Expected>
where
Actual: fmt::Debug,
Expected: fmt::Debug,
{
type Value = MatchFailure<Mismatch<Actual, Expected>>;
fn fmt(&self, f: &mut Formatter, value: Self::Value) -> xpct::Result<()> {
let mismatch = value.unwrap();
f.write_str("Expected:\n");
f.indented(whitespace(4), |f| {
f.write_str(format!("{:?}", mismatch.actual));
Ok(())
})?;
if value.is_pos() {
f.write_str("to equal:\n");
} else {
f.write_str("to not equal:\n");
}
f.indented(whitespace(4), |f| {
f.write_str(format!("{:?}", mismatch.expected));
Ok(())
})?;
Ok(())
}
}
pub fn equal<'a, Actual, Expected>(expected: Expected) -> Matcher<'a, Actual, Actual>
where
Actual: fmt::Debug + PartialEq<Expected> + Eq + 'a,
Expected: fmt::Debug + 'a,
{
Matcher::new(EqualMatcher::new(expected), NotEqualFormat::new())
}
§Colors and text styles
Formatters also support styling the output with colors and text styles using the
Formatter::set_style
and Formatter::reset_style
methods.
Colors and text styles are never emitted when stderr is not a tty or when the
NO_COLOR
environment variable is set. You can also
remove support for colors and text styles by disabling the default color
Cargo
feature. See Cargo Features for information.
Colors and text styles can be useful to make the output easier to read, but they should not convey any information that’s not already in the text. Some developers don’t experience color the same way you do, some developers use screen readers, and some developers just prefer to have colors disabled.
§Composing formatters
If your matcher composes other matchers, it will likely pass a
FormattedFailure
to the formatter, which represents the formatted output of
those matchers. You can use Formatter::write_fmt
to efficiently pass this
through to your formatter’s output.