fmt.oak
// libfmt is the string formatting library for Oak.
{
println: println
default: default
} := import('std')
// format returns the format string `raw`, where each substring of the form
// "{{N}}" has been replaced by the Nth value given in the arguments. Values
// may be referenced zero or more times in the format string.
//
// format is ported from Ink's std.format function.
fn format(raw, values...) {
// parser internal state
// 0 -> normal
// 1 -> seen one {
// 2 -> seen two {
// 3 -> seen a valid }
which := 0
// buffer for currently reading key
key := ''
// result build-up buffer
buf := ''
// non-integer keys will key into this dict
value := values.0 |> default({})
fn sub(idx) if idx < len(raw) {
true -> {
c := raw.(idx)
if which {
0 -> if c {
'{' -> which <- 1
_ -> buf << c
}
1 -> if c {
'{' -> which <- 2
// if it turns out the earlier brace was not a part of a format
// expression, just backtrack
_ -> {
buf << '{' << c
which <- 0
}
}
2 -> if c {
'}' -> {
index := int(key)
buf << if {
key = '' -> ''
index = ? -> value.(key)
_ -> values.(index)
} |> string()
key <- ''
which <- 3
}
// ignore spaces in keys
' ', '\t' -> ?
_ -> key <- key + c
}
3 -> if c {
'}' -> which <- 0
// ignore invalid inputs -- treat them as nonexistent
_ -> ?
}
}
sub(idx + 1)
}
_ -> buf
}
sub(0)
}
// printf prints the result of format(raw, values...) to output
fn printf(raw, values...) println(format(raw, values...))