Oak

fmt.oak

← Standard library See on GitHub ↗

// 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...))