///|
pub fn Doc::from_line(line : Line) -> Doc {
@immut_deque.singleton(line)
}
///|
pub fn Doc::from_string(str : &IsString) -> Doc {
Line::from_string(str) |> Doc::from_line
}
///|
pub fn Doc::new(deque : Deque[Line]) -> Doc {
deque
}
///|
pub fn Doc::from_iter(iter : Iter[Line]) -> Doc {
Deque::from_iter(iter)
}
///|
pub fn Doc::empty() -> Doc {
@immut_deque.empty()
}
///|
pub fn Doc::envelop(self : Doc, left~ : &IsString, right~ : &IsString) -> Doc {
match self.inner().uncons() {
None => @immut_deque.empty()
Some((top, t)) =>
match t.unsnoc() {
Some((bot, mid)) => mid.cons(top.cons(left)).snoc(bot.snoc(right))
None => @immut_deque.singleton(top.cons(left).snoc(right))
}
}
}
///|
pub fn Doc::joinline(
self : Doc,
separator? : &IsString? = None,
bot : Doc,
) -> Doc {
let top = self
match top.inner().unsnoc() {
None => bot
Some((top_last, top_init)) =>
match bot.inner().uncons() {
None => top
Some((bot_head, bot_tail)) => {
let bot_head = match separator {
None => bot_head
Some(sep) => bot_head.cons(sep)
}
let mid = top_last.append(bot_head)
top_init.snoc(mid).append(bot_tail)
}
}
}
}
///|
pub fn Doc::height(self : Doc) -> Int {
self.inner().foldl(0, fn(acc, _) { acc + 1 })
}
///|
pub fn Doc::lastline_width(self : Doc) -> Int {
match self.inner().unsnoc() {
None => 0
Some((last, _)) => last.width()
}
}
///|
fn[T : Compare] maximum(iter : Iter[T]) -> T? {
let mut res = None
for x in iter {
match res {
None => res = Some(x)
Some(max) => if x > max { res = Some(x) }
}
}
res
}
///|
pub fn Doc::width(self : Doc) -> Int {
(self.inner().iter().map(Line::width) |> maximum).unwrap()
}
///|
pub fn Doc::join(self : Doc, separator~ : &IsString) -> Line {
match self.inner().uncons() {
None => Line::empty()
Some((x, xs)) =>
xs.foldl(x, fn(acc, line) { acc.append(line.cons(separator)) })
}
}
///|
pub fn Doc::indent(self : Doc, n : Int) -> Doc {
self.inner().map(fn(line) { line.indent(n) })
}
///|
pub fn Doc::indent_rest(self : Doc, n : Int) -> Doc {
match self.inner().uncons() {
None => @immut_deque.empty()
Some((x, xs)) => xs.map(fn(line) { line.indent(n) }).cons(x)
}
}
///|
pub impl Show for Doc with output(self, logger) {
for line in self.inner() {
for text in line {
text.write_string(logger)
}
logger.write_char('\n')
}
}
///|
pub impl Show for Doc with to_string(self) {
let size_hint = self
.inner()
.foldl(0, fn(acc, line) {
line.texts.foldl(acc, fn(acc, text) { acc + text.length() })
})
let builder = StringBuilder::new(size_hint~)
self.output(builder)
builder.to_string()
}
///|
pub fn Doc::vertical_concat(self : Doc, other : Doc) -> Doc {
self.inner().append(other.inner())
}