Current section
Files
Jump to
Current section
Files
src/string_builder.gleam
import gleam/int as gleam_int
import gleam/string
import gleam/function
import gleam/list
type Callback(next_formatter) =
fn(String) -> next_formatter
type Fn(next_formatter, formatter) =
fn(Callback(next_formatter)) -> formatter
/// Start a new formatter
///
/// ## Example
///
/// let formatter =
/// sb.new
/// ...
///
pub fn new(callback: Callback(formatter)) -> formatter {
callback("")
}
/// Format a String
/// To be used in conjunction with compose
pub fn string_formatter(str: String) -> Fn(formatter, formatter) {
fn(callback: Callback(formatter)) -> formatter { callback(str) }
}
/// Add a string
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello ")
///
pub fn string(previous: Fn(f1, f2), str: String) -> Fn(f1, f2) {
compose(previous, string_formatter(str))
}
/// A placeholder for a string
/// To be used in conjunction with compose
pub fn arg_string_formatter(callback: Callback(formatter)) {
fn(str: String) { callback(str) }
}
/// Add a placeholder for a string
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.arg_string
/// |> ...
///
pub fn arg_string(previous) -> Fn(a, b) {
previous
|> compose(arg_string_formatter)
}
/// Format an Int
/// To be used in conjunction with compose
pub fn int_formatter(n: Int) -> Fn(formatter, formatter) {
fn(callback: Callback(formatter)) -> formatter {
callback(gleam_int.to_string(n))
}
}
/// Add an Int
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.int(12)
/// |> ...
///
pub fn int(previous: Fn(f1, f2), n: Int) -> Fn(f1, f2) {
compose(previous, int_formatter(n))
}
/// A placeholder for an Int
/// To be used in conjunction with compose
pub fn arg_int_formatter(callback: Callback(formatter)) {
fn(int: Int) { callback(gleam_int.to_string(int)) }
}
/// Add a placeholder for an Int
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.arg_int
/// |> ...
///
pub fn arg_int(previous) -> Fn(a, b) {
compose(previous, arg_int_formatter)
}
// List of Int
fn format_int_list(l: List(Int)) -> String {
l
|> list.map(gleam_int.to_string)
|> string.join(", ")
}
/// Format a List(Int)
/// To be used in conjunction with compose
pub fn int_list_formatter(l: List(Int)) -> Fn(formatter, formatter) {
fn(callback: Callback(formatter)) -> formatter {
l
|> format_int_list
|> callback
}
}
/// Add a List(Int)
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.int_list([1,2,3])
/// |> ...
///
pub fn int_list(previous: Fn(f1, f2), l: List(Int)) -> Fn(f1, f2) {
compose(previous, int_list_formatter(l))
}
/// A placeholder for a List(Int)
/// To be used in conjunction with compose
pub fn arg_int_list_formatter(callback: Callback(formatter)) {
fn(l: List(Int)) {
l
|> format_int_list
|> callback
}
}
/// Add a placeholder for a List(Int)
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.arg_int_list
/// |> ...
///
pub fn arg_int_list(previous) -> Fn(a, b) {
compose(previous, arg_int_list_formatter)
}
/// The identity function
/// This is used when calling a formatter using the curried form
pub fn identity(s) {
s
}
/// Compose formatters
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("The current state is ")
/// |> sb.compose(custom_state_formatter)
///
pub fn compose(previous: Fn(f2, f1), next: Fn(f3, f2)) -> Fn(f3, f1) {
// Get the result of the previous and pass to the next
fn(callback: Callback(f3)) {
previous(fn(previous_str: String) {
next(fn(next_str: String) {
callback(string.append(previous_str, next_str))
})
})
}
}
fn uncurry2(fun) {
fn(a, b) { fun(a)(b) }
}
fn uncurry3(fun) {
fn(a, b, c) { fun(a)(b)(c) }
}
fn uncurry4(fun) {
fn(a, b, c, d) { fun(a)(b)(c)(d) }
}
fn uncurry5(fun) {
fn(a, b, c, d, e) { fun(a)(b)(c)(d)(e) }
}
/// End a formatter with 0 arguments
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello")
/// |> sb.end0
///
pub fn end0(formatter) {
fn() { formatter(identity) }
}
/// End a formatter with 1 argument
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello ")
/// |> sb.arg_string
/// |> sb.end1
///
pub fn end1(formatter) {
formatter(identity)
}
/// End a formatter with 2 arguments
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello ")
/// |> sb.arg_string
/// |> sb.arg_int
/// |> sb.end2
///
pub fn end2(formatter) {
formatter(identity)
|> uncurry2
}
/// End a formatter with 3 arguments
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello ")
/// |> sb.arg_string
/// ...
/// |> sb.end3
///
pub fn end3(formatter) {
formatter(identity)
|> uncurry3
}
/// End a formatter with 4 arguments
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello ")
/// |> sb.arg_string
/// ...
/// |> sb.end4
///
pub fn end4(formatter) {
formatter(identity)
|> uncurry4
}
/// End a formatter with 5 arguments
///
/// ## Example
///
/// let formatter =
/// sb.new
/// |> sb.string("Hello ")
/// |> sb.arg_string
/// ...
/// |> sb.end5
///
pub fn end5(formatter) {
formatter(identity)
|> uncurry5
}