glam/doc

Types

A document that can be pretty printed with to_string.

pub opaque type Document

Constants

pub const empty: Document = Concat([])

An empty document that is printed as the empty string.

Examples

empty |> to_string(80)
// -> ""
pub const line: Document = Line(1)

A document that is always printed as a single newline.

Examples

line |> to_string(80)
// -> "\n"
pub const soft_break: Document = Break("", "")

A document that is always rendered as an empty string but can act as a breaking point for the pretty printer.

This is a shorthand for break("", "").

Examples

let doc = [from_string("soft"), soft_break, from_string("break")]

doc |> to_string(80)
// -> "softbreak"

doc |> to_string(5)
// -> "soft
// break"
pub const space: Document = Break(" ", "")

A document that is rendered as a single whitespace " " but can be broken by the pretty printer into newlines instead.

This is a shorthand for break(" ", "").

Examples

let doc =
  ["pretty", "printed"]
  |> list.map(from_string)
  |> join(with: space)

doc |> to_string(80)
// -> "pretty printed"

doc |> to_string(10)
// -> "pretty
// printed"

Functions

pub fn append(to first: Document, doc second: Document) -> Document

Joins a document into the end of another.

Examples

from_string("pretty")
|> append(from_string(" printer"))
|> to_string(80)
// -> "pretty printer"
pub fn append_docs(first: Document, docs: List(Document)) -> Document

Joins multiple documents into the end of another.

This is a shorthand for append(to: first, doc: concat(docs)).

Examples

from_string("pretty")
|> append_docs([
  from_string("printing"),
  space,
  from_string("rocks!"),
])
|> to_string(80) 
// -> "pretty printing rocks!"
pub fn break(unbroken: String, broken: String) -> Document

A document after which the pretty printer can insert a newline. A newline is added after a break document if the group it is part of could not be rendered on a single line.

If the pretty printer decides to add a newline after break it will be rendered as its first argument, otherwise as its first argument.

Examples

let message =
  [from_string("pretty"), break("•", "↩"), from_string("printed")]
  |> concat
  |> group

message |> to_string(20)
// -> "pretty•printed"

message |> to_string(10)
// -> "pretty↩
// printed"
pub fn concat(docs: List(Document)) -> Document

Joins a list of documents into a single document.

The resulting pretty printed document would be the same as pretty printing each document separately and concatenating it together with <>:

docs |> concat |> to_string(n) ==
docs |> list.map(to_string(n)) |> string.concat

Examples

["pretty", " ", "printed"]
|> list.map(from_string)
|> concat
|> to_string(80)
// -> "pretty printed"
pub fn concat_join(docs: List(Document), with separators: List(
    Document,
  )) -> Document

Joins a list of documents into a single one by inserting the given separators between each existing document.

This is a shorthand for join(docs, concat(separators)).

Examples

["wow", "so", "many", "commas"]
|> list.map(from_string)
|> concat_join([from_string(","), space])
|> to_string(80)
// -> "wow, so, many, commas"
pub fn force_break(doc: Document) -> Document

Forces the pretty printer to break all the breaks of the outermost document. This still has no effect on groups as the pretty printer will always try to put them on a single line before splitting them.

Examples

[from_string("pretty"), break("•", "↩"), from_string("printed")]
|> concat
|> force_break
|> group
|> to_string(100)
// -> "pretty↩
// printed"
pub fn from_string(string: String) -> Document

Turns a string into a document.

Examples

"doc" |> from_string |> to_string(80)
// -> "doc"
pub fn group(doc: Document) -> Document

Allows the pretty printer to break the break documents inside the given group.

When the pretty printer runs into a group it first tries to render it on a single line, displaying all the breaks as their first argument. If the group fits this is the final pretty printed result.

However, if the group does not fit on a single line all the breaks inside that group are rendered as their second argument and immediately followed by a newline.

Any nested group is considered on its own and may or may not be splitted, depending if it fits on a single line or not. So, even if the outermost group is broken, its nested groups may still end up on a single line.

Examples

let food =
  ["lasagna", "ravioli", "pizza"]
  |> list.map(from_string) |> join(with: space) |> group
let message = 
  [from_string("Food I love:"), space, food] |> concat |> group

message |> to_string(80)
// -> "Food I love: lasagna ravioli pizza"

message |> to_string(30)
// -> "Food I love:
// lasagna ravioli pizza"
// ^-- After splitting the outer group, the inner one can fit
//     on a single line so the pretty printer does not split it

message |> to_string(20)
// "Food I love:
// lasagna
// ravioli
// pizza"
// ^-- Even after splitting the outer group, the inner one wouldn't
//     fit on a single line, so the pretty printer splits that as well
pub fn join(docs: List(Document), with separator: Document) -> Document

Joins a list of documents inserting the given separator between each existing document.

Examples

let message =
  ["Gleam", "is", "fun!"]
  |> list.map(from_string)
  |> join(with: space)

message |> to_string(80)
// -> "Gleam is fun!"
pub fn lines(size: Int) -> Document

A document that is always printed as a series of consecutive newlines.

Examples

lines(3) |> to_string(80)
// -> "\n\n\n"
pub fn nest(doc: Document, by indentation: Int) -> Document

Increases the nesting level of a document by the given amount.

When the pretty printer breaks a group by inserting a newline, it also adds a whitespace padding equal to its nesting level.

Examples

let one = [space, from_string("one")] |> concat |> nest(by: 1)
let two = [space, from_string("two")] |> concat |> nest(by: 2)
let three = [space, from_string("three")] |> concat |> nest(by: 3)
let list = [from_string("list:"), one, two, three] |> concat |> group

list |> to_string(10)
// -> "list:
//  one
//   two
//    three"
pub fn prepend(to first: Document, doc second: Document) -> Document

Prefixes a document to another one.

Examples

from_string("printed!")
|> prepend(from_string("pretty "))
|> to_string(80)
// -> "pretty printed!"
pub fn prepend_docs(first: Document, docs: List(Document)) -> Document

Prefixes multiple documents to another one.

This is a shorthand for prepend(to: first, doc: concat(docs)).

Examples

from_string("fun!")
|> prepend_docs([from_string("Gleam "), from_string("is ")])
|> to_string(80)
// -> "Gleam is fun!"
pub fn to_string(doc: Document, width: Int) -> String

Turns a document into a pretty printed string. The pretty printed process can be thought as follows:

  • the pretty printer first tries to print every group on a single line
  • all the break documents are rendered as their first argument
  • if the string fits on the specified width this is the result
  • if the string does not fit on a single line the outermost group is split:
    • all of its break documents are rendered as their second argument
    • a newline is inserted after every break
    • a padding of the given nesting level is added after every inserted newline
    • all inner groups are then considered on their own: the splitting of the outermost group does not imply that the inner gruops will be split as well

Examples

For some examples on how pretty printing works for each kind of document you can have a look at the package documentation. There’s also a step by step tutorial that will guide you through the implementation of a simple pretty printer, covering most of the glam api.

pub fn to_string_builder(doc: Document, width: Int) -> StringBuilder

This function works like to_string but returns a StringBuilder instead of a String.

Search Document