glam/doc
Types
Constants
pub const empty: Document
An empty document that is printed as an empty string.
Examples
empty |> to_string(80)
// -> ""
pub const flex_space: Document
A document that is rendered as a single whitespace " "
but can be broken
by the pretty printer into newlines instead.
Instead of splitting all spaces or no spaces (like it would do with
space
inside a group), the pretty printer can decide on a space-by-space
basis.
If a flex_space
inside a group needs to be broken to fit it on multiple
lines, following flex_spaces
may end up not being broken.
This is a shorthand for flex_break(" ", "")
.
Examples
let message =
["Gleam", "is", "fun!"]
|> list.map(from_string)
|> join(with: flex_space)
|> group
to_string(message, 80)
// -> "Gleam is fun!"
to_string(message, 10)
// -> "Gleam is
fun!"
to_string(message, 4) // -> “Gleam // is // fun!”
pub const line: Document
A document that is always printed as a single new line.
Examples
line |> to_string(80)
// -> "\n"
pub const soft_break: Document
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
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 new line.
A newline is added after a break
document if the group
it’s 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 second 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 debug(document: Document) -> Document
Returns a debug version of the given document that can be pretty printed to see the structure of a document.
This can help you see how your data structures get turned into documents and check if the document is what you’d expect.
group
s are surrounded by square brackets.nest
s are surrounded by angle brackets and have a smal superscript with the nesting.concat
enated documents are separated by dots.break
s are rendered surrounded by curly brackets and show both the broken and unbroken versions.line
s are rendered as the stringlf
followed by a superscript number of lines.
pub fn flex_break(unbroken: String, broken: String) -> Document
A document after which the pretty printer can insert a new line.
The difference with a simple break
is that, the pretty printer will decide
wether to add a new line or not on a space-by-space basis.
While all the break
inside a group are broken or not, some flex_breaks
may be broken and some not, depending wether the document can fit on a
single line or not. Hence the name flex.
If the pretty printer decides to add a newline after flex_break
it will be
rendered as its first argument, otherwise as its first argument.
Examples
let message =
[from_string("pretty"), from_string("printed"), from_string("string")]
|> join(with: flex_break("•", "↩"))
|> group
message |> to_string(80)
// -> "pretty•printed•string"
message |> to_string(20)
// -> "pretty•printed↩
// string"
pub fn force_break(doc: Document) -> Document
Forces the pretty printer to break all the break
s of the outermost
document. This still has no effect on group
s 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 break
s
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 split, 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 nest_docs(
docs: List(Document),
by indentation: Int,
) -> Document
Joins together a list of documents and increases their nesting level.
This is a shorthand for nest(concat(docs), by: indentation)
.
Examples
[from_string("one"), space, from_string("two")]
|> nest_docs(by: 2)
|> append(space)
|> append(from_string("three"))
|> group
|> to_string(5)
// ->
// 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, limit: Int) -> String
Turns a document into a pretty printed string, trying to fit it into lines
of maximum size specified by limit
.
The pretty printed process can be thought of 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 groups will be split as well
- all of its
Examples
For some examples of 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 zero_width_string(string: String) -> Document
Turns a string into a document whose length is not taken into account when formatting it.
This kind of string can be used to render non-visible characters like ansi color codes.
Examples
// Should break in two lines, but doesn't because of the zero_width_string
// does not contribute to the total line length.
[
zero_width_string("\u{001b}[1;31m"),
from_string("I'm a red"),
break(", ", ","),
from_string("bold text"),
]
|> concat
|> group
|> to_string(20)
// -> "\u{001b}[1;31mI'm a red, bold text"