conciliator 0.3.10

[WIP] Library for interactive CLI programs
Documentation
//! Multi-line text segments like [`List`]s or [`Tree`]s
mod list;
pub use list::List;
mod tree;
pub use tree::Tree;

use std::marker::PhantomData;
use crate::{
	Buffer,
	Inline,
	Pushable,
	Conciliator
};

/// Printing multi-line text segments
///
/// Similar to [`Inline`], but for multi-line segments like a [`List`] or a [`Tree`].
///
/// It is not necessarily designed for implementors that own the data they are printing.
/// Rather, implementors may be short-lived objects (constructed only to be printed) that are more about the *how* than the *what* to print, holding only references to the data itself.
/// In the case of [`List`] this takes the form of an [`Iterator`] ([`ExactSizeIterator`] to be precise), which is *consumed* when printed.
/// To enable such implementors, the `print()` function takes `self` by value.
pub trait Print {
	/// *Print* `self` using the [`Conciliator`], consuming `self`
	fn print<C: Conciliator + ?Sized>(self, con: &C);
}

/// Format items for printing
///
/// [`Formatter`] is basically the same as [`Inline`], except that the formatting isn't implemented by the *thing-to-be-printed* itself and that this [`Formatter`] may mutate itself.
/// This makes the trait very flexible.
pub trait Formatter<T> {
	/// Format and append the thing into the [`Buffer`]
	fn format(&mut self, buf: &mut Buffer, thing: T);
}

/// Format items using their [`Pushable`] implementation
///
/// This carries the marker type needed by [`Pushable`] to pick the correct blanket implementation.
/// As with other uses of [`Pushable`], the marker type should be inferred automatically, and it's currently not possible to specify it explicitly.
///
/// Used by [`List`] as the "default" [`Formatter`] returned by its constructors.
pub struct PushableFmt<M>(PhantomData<M>);

/// Format items by wrapping them with an [`Inline`] implementor
///
/// Useful with the simple wrapper types [`Wrap`](crate::Wrap) and [`WrapBold`](crate::WrapBold), but can be used with any [`FnMut`] (e.g. a stateful closure) that returns an [`Inline`] implementor.
///
/// Used by [`List::with_wrap`].
pub struct WrapFmt<F>(F);


/*
 *	FORMATTERS
 */

impl<T, F: FnMut(T) -> W, W: Inline> Formatter<T> for WrapFmt<F> {
	fn format(&mut self, buf: &mut Buffer, thing: T) {
		let wrapped = (self.0)(thing);
		buf.push(&wrapped);
	}
}
impl<T, F: FnMut(&mut Buffer, T)> Formatter<T> for F {
	fn format(&mut self, buf: &mut Buffer, thing: T) {
		self(buf, thing)
	}
}
impl<T: Pushable<M>, M> Formatter<T> for PushableFmt<M> {
	fn format(&mut self, buf: &mut Buffer, thing: T) {
		buf.push(thing);
	}
}