use crate::concat;
use crate::Doclike;
use crate::DocPtr;
use crate::StrOrDoc;
use crate::HasPrinter;
use crate::Renderable;
use BracketPrio::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Brackets<'p> {
pub doc : StrOrDoc<'p>,
pub prio : BracketPrio,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum BracketPrio {
Always,
Never,
Num(u16)
}
pub trait Bracketable<'p> : Sized {
fn bracket(self, prio : u16) -> Brackets<'p>;
fn bracket_never(self) -> Brackets<'p> {
let mut b = self.bracket(0);
b.prio = Never;
b
}
fn bracket_always(self) -> Brackets<'p> {
let mut b = self.bracket(0);
b.prio = Always;
b
}
}
impl<'p, A> Bracketable<'p> for A
where StrOrDoc<'p> : From<A> {
fn bracket(self, prio : u16) -> Brackets<'p> {
Brackets {
doc : self.into(),
prio : Num(prio),
}
}
}
impl<'x, 'p : 'x> Brackets<'p> {
pub fn paren_upto(self, upto : u16, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.bracket_upto(upto, "(", ")", pr)
}
pub fn squre_upto(self, upto : u16, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.bracket_upto(upto, "[", "]", pr)
}
pub fn wave_upto(self, upto : u16, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.bracket_upto(upto, "{", "}", pr)
}
pub fn bracket_upto(
self,
upto : u16,
open : &'p str,
close : &'p str,
pr : &mut impl HasPrinter<'p>
) -> DocPtr<'p> {
match self.prio {
Never => self.doc.alloc(pr),
Always => concat!([open, self.doc, close], pr),
Num(n) => {
if n <= upto {
concat!([open, self.doc, close], pr)
} else {
self.doc.alloc(pr)
}
}
}
}
pub fn wo_brackets(self, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.doc.alloc(pr)
}
pub fn w_parens(self, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.w_brackets("(", ")", pr)
}
pub fn w_square(self, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.w_brackets("[", "]", pr)
}
pub fn w_wave(self, pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
self.w_brackets("{", "}", pr)
}
pub fn w_brackets(
self,
open : &'p str,
close : &'p str,
pr : &mut impl HasPrinter<'p>) -> DocPtr<'p> {
concat!([open, self.doc, close], pr)
}
pub fn render<P>(self, line_width : u16, pr : &'x mut P) -> Renderable<'x, 'p, P>
where P : HasPrinter<'p> {
self.doc.alloc(pr).render(line_width, pr)
}
}