use crate::PrettyPrint;
use alloc::borrow::Cow;
use core::fmt::{Debug, Formatter};
use pretty::{
termcolor::{Color, ColorSpec},
Arena, DocAllocator, DocBuilder, Pretty,
};
pub type PrettyTree<'a> = DocBuilder<'a, Arena<'a, ColorSpec>, ColorSpec>;
pub struct PrettyProvider<'a> {
arena: Arena<'a, ColorSpec>,
keyword: ColorSpec,
string: ColorSpec,
number: ColorSpec,
macros: ColorSpec,
argument: ColorSpec,
argument_mut: ColorSpec,
local: ColorSpec,
local_mut: ColorSpec,
operator: ColorSpec,
structure: ColorSpec,
interface: ColorSpec,
}
impl<'a> Debug for PrettyProvider<'a> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("PrettyProvider").finish()
}
}
impl<'a> PrettyProvider<'a> {
pub fn new() -> Self {
let argument = Color::Rgb(239, 112, 117);
let purple = Color::Rgb(197, 119, 207);
let local = Color::Rgb(152, 195, 121);
let green = Color::Rgb(152, 195, 121);
PrettyProvider {
arena: Arena::new(),
keyword: ColorSpec::new().set_fg(Some(purple)).clone(),
string: ColorSpec::new().set_fg(Some(green)).clone(),
number: ColorSpec::new().set_fg(Some(Color::Rgb(206, 153, 100))).clone(),
macros: ColorSpec::new().set_fg(Some(Color::Rgb(87, 182, 194))).clone(),
argument: ColorSpec::new().set_fg(Some(argument)).clone(),
argument_mut: ColorSpec::new().set_fg(Some(argument)).set_underline(true).clone(),
local: ColorSpec::new().set_fg(Some(local)).clone(),
local_mut: ColorSpec::new().set_fg(Some(local)).set_underline(true).clone(),
operator: ColorSpec::new().set_fg(Some(Color::Rgb(90, 173, 238))).clone(),
structure: ColorSpec::new().set_fg(Some(Color::Rgb(197, 119, 207))).clone(),
interface: ColorSpec::new().set_fg(Some(Color::Rgb(197, 119, 207))).clone(),
}
}
}
impl<'a> PrettyProvider<'a> {
pub fn nil(&'a self) -> PrettyTree<'a> {
self.arena.nil()
}
pub fn space(&'a self) -> PrettyTree<'a> {
self.arena.space()
}
pub fn hardline(&'a self) -> PrettyTree<'a> {
self.arena.hardline()
}
pub fn text<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.arena.text(text.into())
}
pub fn keyword<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.keyword.clone())
}
pub fn identifier<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.operator(text)
}
pub fn generic<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.macros.clone())
}
pub fn variable<'i, S>(&'a self, text: S, mutable: bool) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
if mutable { self.text(text).annotate(self.local_mut.clone()) } else { self.text(text).annotate(self.local.clone()) }
}
pub fn argument<'i, S>(&'a self, text: S, mutable: bool) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
if mutable {
self.text(text).annotate(self.argument_mut.clone())
}
else {
self.text(text).annotate(self.argument.clone())
}
}
pub fn operator<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.operator.clone())
}
pub fn string<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.string.clone())
}
pub fn metadata<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.macros.clone())
}
pub fn number<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.number.clone())
}
pub fn structure<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.structure.clone())
}
pub fn interface<'i, S>(&'a self, text: S) -> PrettyTree<'a>
where
S: Into<Cow<'i, str>>,
'i: 'a,
{
self.text(text).annotate(self.interface.clone())
}
}
impl<'a> PrettyProvider<'a> {
#[inline]
pub fn concat<I>(&'a self, docs: I) -> PrettyTree<'a>
where
I: IntoIterator,
I::Item: Pretty<'a, Arena<'a, ColorSpec>, ColorSpec>,
{
self.arena.concat(docs)
}
#[inline]
pub fn intersperse<T, S>(&'a self, terms: &[T], joint: S) -> PrettyTree<'a>
where
T: PrettyPrint,
S: Pretty<'a, Arena<'a, ColorSpec>, ColorSpec> + Clone,
{
self.arena.intersperse(terms.iter().map(|x| x.build(self)), joint)
}
#[inline]
pub fn join<T>(&'a self, terms: &[T], joint: &'static str) -> PrettyTree<'a>
where
T: PrettyPrint,
{
self.arena.intersperse(terms.iter().map(|x| x.build(self)), self.arena.text(joint))
}
}