Packages
gleam_stdlib
0.50.0
1.0.3
1.0.2
1.0.1
1.0.0
0.71.0
0.70.0
0.69.0
0.68.1
0.68.0
0.67.1
0.67.0
0.65.0
0.64.0
0.63.2
0.63.1
0.63.0
0.62.1
0.62.0
0.61.0
0.60.0
0.59.0
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.1
0.35.0
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.0
0.30.2
0.30.1
0.30.0
0.29.2
0.29.1
0.29.0
0.28.2
0.28.1
0.28.0
0.27.0
0.26.1
0.26.0
0.25.0
0.24.0
0.23.0
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.18.0-rc1
0.17.1
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.4.0-rc1
0.3.1
0.3.0
0.2.0
retired
A standard library for the Gleam programming language
Current section
Files
Jump to
Current section
Files
src/gleam/string.gleam
//// Strings in Gleam are UTF-8 binaries. They can be written in your code as
//// text surrounded by `"double quotes"`.
import gleam/list
import gleam/option.{type Option, None, Some}
import gleam/order
import gleam/string_tree.{type StringTree}
/// Determines if a `String` is empty.
///
/// ## Examples
///
/// ```gleam
/// is_empty("")
/// // -> True
/// ```
///
/// ```gleam
/// is_empty("the world")
/// // -> False
/// ```
///
pub fn is_empty(str: String) -> Bool {
str == ""
}
/// Gets the number of grapheme clusters in a given `String`.
///
/// This function has to iterate across the whole string to count the number of
/// graphemes, so it runs in linear time.
///
/// ## Examples
///
/// ```gleam
/// length("Gleam")
/// // -> 5
/// ```
///
/// ```gleam
/// length("ß↑e̊")
/// // -> 3
/// ```
///
/// ```gleam
/// length("")
/// // -> 0
/// ```
///
@external(erlang, "string", "length")
@external(javascript, "../gleam_stdlib.mjs", "string_length")
pub fn length(string: String) -> Int
/// Reverses a `String`.
///
/// This function has to iterate across the whole `String` so it runs in linear
/// time.
///
/// ## Examples
///
/// ```gleam
/// reverse("stressed")
/// // -> "desserts"
/// ```
///
pub fn reverse(string: String) -> String {
string
|> string_tree.from_string
|> string_tree.reverse
|> string_tree.to_string
}
/// Creates a new `String` by replacing all occurrences of a given substring.
///
/// ## Examples
///
/// ```gleam
/// replace("www.example.com", each: ".", with: "-")
/// // -> "www-example-com"
/// ```
///
/// ```gleam
/// replace("a,b,c,d,e", each: ",", with: "/")
/// // -> "a/b/c/d/e"
/// ```
///
pub fn replace(
in string: String,
each pattern: String,
with substitute: String,
) -> String {
string
|> string_tree.from_string
|> string_tree.replace(each: pattern, with: substitute)
|> string_tree.to_string
}
/// Creates a new `String` with all the graphemes in the input `String` converted to
/// lowercase.
///
/// Useful for case-insensitive comparisons.
///
/// ## Examples
///
/// ```gleam
/// lowercase("X-FILES")
/// // -> "x-files"
/// ```
///
@external(erlang, "string", "lowercase")
@external(javascript, "../gleam_stdlib.mjs", "lowercase")
pub fn lowercase(string: String) -> String
/// Creates a new `String` with all the graphemes in the input `String` converted to
/// uppercase.
///
/// Useful for case-insensitive comparisons and VIRTUAL YELLING.
///
/// ## Examples
///
/// ```gleam
/// uppercase("skinner")
/// // -> "SKINNER"
/// ```
///
@external(erlang, "string", "uppercase")
@external(javascript, "../gleam_stdlib.mjs", "uppercase")
pub fn uppercase(string: String) -> String
/// Compares two `String`s to see which is "larger" by comparing their graphemes.
///
/// This does not compare the size or length of the given `String`s.
///
/// ## Examples
///
/// ```gleam
/// compare("Anthony", "Anthony")
/// // -> order.Eq
/// ```
///
/// ```gleam
/// compare("A", "B")
/// // -> order.Lt
/// ```
///
pub fn compare(a: String, b: String) -> order.Order {
case a == b {
True -> order.Eq
_ ->
case less_than(a, b) {
True -> order.Lt
_ -> order.Gt
}
}
}
@external(erlang, "gleam_stdlib", "less_than")
@external(javascript, "../gleam_stdlib.mjs", "less_than")
fn less_than(a: String, b: String) -> Bool
/// Takes a substring given a start grapheme index and a length. Negative indexes
/// are taken starting from the *end* of the list.
///
/// ## Examples
///
/// ```gleam
/// slice(from: "gleam", at_index: 1, length: 2)
/// // -> "le"
/// ```
///
/// ```gleam
/// slice(from: "gleam", at_index: 1, length: 10)
/// // -> "leam"
/// ```
///
/// ```gleam
/// slice(from: "gleam", at_index: 10, length: 3)
/// // -> ""
/// ```
///
/// ```gleam
/// slice(from: "gleam", at_index: -2, length: 2)
/// // -> "am"
/// ```
///
/// ```gleam
/// slice(from: "gleam", at_index: -12, length: 2)
/// // -> ""
/// ```
///
pub fn slice(from string: String, at_index idx: Int, length len: Int) -> String {
case len < 0 {
True -> ""
False ->
case idx < 0 {
True -> {
let translated_idx = length(string) + idx
case translated_idx < 0 {
True -> ""
False -> do_slice(string, translated_idx, len)
}
}
False -> do_slice(string, idx, len)
}
}
}
@external(erlang, "gleam_stdlib", "slice")
@external(javascript, "../gleam_stdlib.mjs", "string_slice")
fn do_slice(string: String, idx: Int, len: Int) -> String
/// Drops contents of the first `String` that occur before the second `String`.
/// If the `from` string does not contain the `before` string, `from` is returned unchanged.
///
/// ## Examples
///
/// ```gleam
/// crop(from: "The Lone Gunmen", before: "Lone")
/// // -> "Lone Gunmen"
/// ```
///
@external(erlang, "gleam_stdlib", "crop_string")
@external(javascript, "../gleam_stdlib.mjs", "crop_string")
pub fn crop(from string: String, before substring: String) -> String
/// Drops *n* graphemes from the left side of a `String`.
///
/// ## Examples
///
/// ```gleam
/// drop_left(from: "The Lone Gunmen", up_to: 2)
/// // -> "e Lone Gunmen"
/// ```
///
@deprecated("Use `string.drop_start` instead.")
pub fn drop_left(from string: String, up_to num_graphemes: Int) -> String {
drop_start(string, num_graphemes)
}
/// Drops *n* graphemes from the start of a `String`.
///
/// ## Examples
///
/// ```gleam
/// drop_start(from: "The Lone Gunmen", up_to: 2)
/// // -> "e Lone Gunmen"
/// ```
///
pub fn drop_start(from string: String, up_to num_graphemes: Int) -> String {
case num_graphemes > 0 {
False -> string
True ->
case pop_grapheme(string) {
Ok(#(_, string)) -> drop_start(string, num_graphemes - 1)
Error(Nil) -> string
}
}
}
/// Drops *n* graphemes from the right side of a `String`.
///
/// ## Examples
///
/// ```gleam
/// drop_right(from: "Cigarette Smoking Man", up_to: 2)
/// // -> "Cigarette Smoking M"
/// ```
///
@deprecated("Use `string.drop_end` instead.")
pub fn drop_right(from string: String, up_to num_graphemes: Int) -> String {
drop_end(string, num_graphemes)
}
/// Drops *n* graphemes from the end of a `String`.
///
/// ## Examples
///
/// ```gleam
/// drop_end(from: "Cigarette Smoking Man", up_to: 2)
/// // -> "Cigarette Smoking M"
/// ```
///
pub fn drop_end(from string: String, up_to num_graphemes: Int) -> String {
case num_graphemes < 0 {
True -> string
False -> slice(string, 0, length(string) - num_graphemes)
}
}
/// Checks if the first `String` contains the second.
///
/// ## Examples
///
/// ```gleam
/// contains(does: "theory", contain: "ory")
/// // -> True
/// ```
///
/// ```gleam
/// contains(does: "theory", contain: "the")
/// // -> True
/// ```
///
/// ```gleam
/// contains(does: "theory", contain: "THE")
/// // -> False
/// ```
///
@external(erlang, "gleam_stdlib", "contains_string")
@external(javascript, "../gleam_stdlib.mjs", "contains_string")
pub fn contains(does haystack: String, contain needle: String) -> Bool
/// Checks whether the first `String` starts with the second one.
///
/// ## Examples
///
/// ```gleam
/// starts_with("theory", "ory")
/// // -> False
/// ```
///
@external(erlang, "gleam_stdlib", "string_starts_with")
@external(javascript, "../gleam_stdlib.mjs", "starts_with")
pub fn starts_with(string: String, prefix: String) -> Bool
/// Checks whether the first `String` ends with the second one.
///
/// ## Examples
///
/// ```gleam
/// ends_with("theory", "ory")
/// // -> True
/// ```
///
@external(erlang, "gleam_stdlib", "string_ends_with")
@external(javascript, "../gleam_stdlib.mjs", "ends_with")
pub fn ends_with(string: String, suffix: String) -> Bool
/// Creates a list of `String`s by splitting a given string on a given substring.
///
/// ## Examples
///
/// ```gleam
/// split("home/gleam/desktop/", on: "/")
/// // -> ["home", "gleam", "desktop", ""]
/// ```
///
pub fn split(x: String, on substring: String) -> List(String) {
case substring {
"" -> to_graphemes(x)
_ ->
x
|> string_tree.from_string
|> string_tree.split(on: substring)
|> list.map(with: string_tree.to_string)
}
}
/// Splits a `String` a single time on the given substring.
///
/// Returns an `Error` if substring not present.
///
/// ## Examples
///
/// ```gleam
/// split_once("home/gleam/desktop/", on: "/")
/// // -> Ok(#("home", "gleam/desktop/"))
/// ```
///
/// ```gleam
/// split_once("home/gleam/desktop/", on: "?")
/// // -> Error(Nil)
/// ```
///
@external(javascript, "../gleam_stdlib.mjs", "split_once")
pub fn split_once(
string: String,
on substring: String,
) -> Result(#(String, String), Nil) {
case erl_split(string, substring) {
[first, rest] -> Ok(#(first, rest))
_ -> Error(Nil)
}
}
@external(erlang, "string", "split")
fn erl_split(a: String, b: String) -> List(String)
/// Creates a new `String` by joining two `String`s together.
///
/// This function copies both `String`s and runs in linear time. If you find
/// yourself joining `String`s frequently consider using the [`string_tree`](../gleam/string_tree.html)
/// module as it can append `String`s much faster!
///
/// ## Examples
///
/// ```gleam
/// append(to: "butter", suffix: "fly")
/// // -> "butterfly"
/// ```
///
pub fn append(to first: String, suffix second: String) -> String {
first
|> string_tree.from_string
|> string_tree.append(second)
|> string_tree.to_string
}
/// Creates a new `String` by joining many `String`s together.
///
/// This function copies both `String`s and runs in linear time. If you find
/// yourself joining `String`s frequently consider using the [`string_tree`](../gleam/string_tree.html)
/// module as it can append `String`s much faster!
///
/// ## Examples
///
/// ```gleam
/// concat(["never", "the", "less"])
/// // -> "nevertheless"
/// ```
///
pub fn concat(strings: List(String)) -> String {
strings
|> string_tree.from_strings
|> string_tree.to_string
}
/// Creates a new `String` by repeating a `String` a given number of times.
///
/// This function runs in linear time.
///
/// ## Examples
///
/// ```gleam
/// repeat("ha", times: 3)
/// // -> "hahaha"
/// ```
///
pub fn repeat(string: String, times times: Int) -> String {
repeat_loop(string, times, "")
}
fn repeat_loop(string: String, times: Int, acc: String) -> String {
case times <= 0 {
True -> acc
False -> repeat_loop(string, times - 1, acc <> string)
}
}
/// Joins many `String`s together with a given separator.
///
/// This function runs in linear time.
///
/// ## Examples
///
/// ```gleam
/// join(["home","evan","Desktop"], with: "/")
/// // -> "home/evan/Desktop"
/// ```
///
@external(javascript, "../gleam_stdlib.mjs", "join")
pub fn join(strings: List(String), with separator: String) -> String {
strings
|> list.intersperse(with: separator)
|> concat
}
/// Pads a `String` on the left until it has at least given number of graphemes.
///
/// ## Examples
///
/// ```gleam
/// pad_left("121", to: 5, with: ".")
/// // -> "..121"
/// ```
///
/// ```gleam
/// pad_left("121", to: 3, with: ".")
/// // -> "121"
/// ```
///
/// ```gleam
/// pad_left("121", to: 2, with: ".")
/// // -> "121"
/// ```
///
@deprecated("Use `string.pad_start` instead.")
pub fn pad_left(
string: String,
to desired_length: Int,
with pad_string: String,
) -> String {
pad_start(string, desired_length, pad_string)
}
/// Pads the start of a `String` until it has a given length.
///
/// ## Examples
///
/// ```gleam
/// pad_start("121", to: 5, with: ".")
/// // -> "..121"
/// ```
///
/// ```gleam
/// pad_start("121", to: 3, with: ".")
/// // -> "121"
/// ```
///
/// ```gleam
/// pad_start("121", to: 2, with: ".")
/// // -> "121"
/// ```
///
pub fn pad_start(
string: String,
to desired_length: Int,
with pad_string: String,
) -> String {
let current_length = length(string)
let to_pad_length = desired_length - current_length
case to_pad_length <= 0 {
True -> string
False -> padding(to_pad_length, pad_string) <> string
}
}
/// Pads a `String` on the right until it has a given length.
///
/// ## Examples
///
/// ```gleam
/// pad_right("123", to: 5, with: ".")
/// // -> "123.."
/// ```
///
/// ```gleam
/// pad_right("123", to: 3, with: ".")
/// // -> "123"
/// ```
///
/// ```gleam
/// pad_right("123", to: 2, with: ".")
/// // -> "123"
/// ```
///
@deprecated("Use `string.pad_end` instead.")
pub fn pad_right(
string: String,
to desired_length: Int,
with pad_string: String,
) -> String {
pad_end(string, desired_length, pad_string)
}
/// Pads the end of a `String` until it has a given length.
///
/// ## Examples
///
/// ```gleam
/// pad_end("123", to: 5, with: ".")
/// // -> "123.."
/// ```
///
/// ```gleam
/// pad_end("123", to: 3, with: ".")
/// // -> "123"
/// ```
///
/// ```gleam
/// pad_end("123", to: 2, with: ".")
/// // -> "123"
/// ```
///
pub fn pad_end(
string: String,
to desired_length: Int,
with pad_string: String,
) -> String {
let current_length = length(string)
let to_pad_length = desired_length - current_length
case to_pad_length <= 0 {
True -> string
False -> string <> padding(to_pad_length, pad_string)
}
}
fn padding(size: Int, pad_string: String) -> String {
let pad_string_length = length(pad_string)
let num_pads = size / pad_string_length
let extra = size % pad_string_length
repeat(pad_string, num_pads) <> slice(pad_string, 0, extra)
}
/// Removes whitespace on both sides of a `String`.
///
/// Whitespace in this function is the set of nonbreakable whitespace
/// codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1].
///
/// [1]: https://unicode.org/reports/tr31/
///
/// ## Examples
///
/// ```gleam
/// trim(" hats \n")
/// // -> "hats"
/// ```
///
pub fn trim(string: String) -> String {
string |> trim_start |> trim_end
}
@external(erlang, "string", "trim")
fn erl_trim(a: String, b: Direction) -> String
type Direction {
Leading
Trailing
}
/// Removes whitespace on the left of a `String`.
///
/// ## Examples
///
/// ```gleam
/// trim_left(" hats \n")
/// // -> "hats \n"
/// ```
///
@deprecated("Use `string.trim_start` instead")
pub fn trim_left(string: String) -> String {
trim_start(string)
}
/// Removes whitespace at the start of a `String`.
///
/// ## Examples
///
/// ```gleam
/// trim_start(" hats \n")
/// // -> "hats \n"
/// ```
///
@external(javascript, "../gleam_stdlib.mjs", "trim_start")
pub fn trim_start(string: String) -> String {
erl_trim(string, Leading)
}
/// Removes whitespace on the right of a `String`.
///
/// ## Examples
///
/// ```gleam
/// trim_right(" hats \n")
/// // -> " hats"
/// ```
///
@deprecated("Use `string.trim_end` instead")
pub fn trim_right(string: String) -> String {
trim_end(string)
}
/// Removes whitespace at the end of a `String`.
///
/// ## Examples
///
/// ```gleam
/// trim_end(" hats \n")
/// // -> " hats"
/// ```
///
@external(javascript, "../gleam_stdlib.mjs", "trim_end")
pub fn trim_end(string: String) -> String {
erl_trim(string, Trailing)
}
/// Splits a non-empty `String` into its first element (head) and rest (tail).
/// This lets you pattern match on `String`s exactly as you would with lists.
///
/// Note on JavaScript using the function to iterate over a string will likely
/// be slower than using `to_graphemes` due to string slicing being more
/// expensive on JavaScript than Erlang.
///
/// ## Examples
///
/// ```gleam
/// pop_grapheme("gleam")
/// // -> Ok(#("g", "leam"))
/// ```
///
/// ```gleam
/// pop_grapheme("")
/// // -> Error(Nil)
/// ```
///
@external(erlang, "gleam_stdlib", "string_pop_grapheme")
@external(javascript, "../gleam_stdlib.mjs", "pop_grapheme")
pub fn pop_grapheme(string: String) -> Result(#(String, String), Nil)
/// Converts a `String` to a list of
/// [graphemes](https://en.wikipedia.org/wiki/Grapheme).
///
/// ```gleam
/// to_graphemes("abc")
/// // -> ["a", "b", "c"]
/// ```
///
@external(javascript, "../gleam_stdlib.mjs", "graphemes")
pub fn to_graphemes(string: String) -> List(String) {
to_graphemes_loop(string, [])
|> list.reverse
}
fn to_graphemes_loop(string: String, acc: List(String)) -> List(String) {
case pop_grapheme(string) {
Ok(#(grapheme, rest)) -> to_graphemes_loop(rest, [grapheme, ..acc])
_ -> acc
}
}
@external(erlang, "gleam_stdlib", "identity")
@external(javascript, "../gleam_stdlib.mjs", "codepoint")
fn unsafe_int_to_utf_codepoint(a: Int) -> UtfCodepoint
/// Converts a `String` to a `List` of `UtfCodepoint`.
///
/// See <https://en.wikipedia.org/wiki/Code_point> and
/// <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an
/// explanation on code points.
///
/// ## Examples
///
/// ```gleam
/// "a" |> to_utf_codepoints
/// // -> [UtfCodepoint(97)]
/// ```
///
/// ```gleam
/// // Semantically the same as:
/// // ["🏳", "️", "", "🌈"] or:
/// // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow]
/// "🏳️🌈" |> to_utf_codepoints
/// // -> [
/// // UtfCodepoint(127987),
/// // UtfCodepoint(65039),
/// // UtfCodepoint(8205),
/// // UtfCodepoint(127752),
/// // ]
/// ```
///
pub fn to_utf_codepoints(string: String) -> List(UtfCodepoint) {
do_to_utf_codepoints(string)
}
@target(erlang)
fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) {
to_utf_codepoints_loop(<<string:utf8>>, [])
}
@target(erlang)
fn to_utf_codepoints_loop(
bit_array: BitArray,
acc: List(UtfCodepoint),
) -> List(UtfCodepoint) {
case bit_array {
<<first:utf8_codepoint, rest:bytes>> ->
to_utf_codepoints_loop(rest, [first, ..acc])
_ -> list.reverse(acc)
}
}
@target(javascript)
fn do_to_utf_codepoints(string: String) -> List(UtfCodepoint) {
string
|> string_to_codepoint_integer_list
|> list.map(unsafe_int_to_utf_codepoint)
}
@target(javascript)
@external(javascript, "../gleam_stdlib.mjs", "string_to_codepoint_integer_list")
fn string_to_codepoint_integer_list(string: String) -> List(Int)
/// Converts a `List` of `UtfCodepoint`s to a `String`.
///
/// See <https://en.wikipedia.org/wiki/Code_point> and
/// <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an
/// explanation on code points.
///
/// ## Examples
///
/// ```gleam
/// let assert Ok(a) = utf_codepoint(97)
/// let assert Ok(b) = utf_codepoint(98)
/// let assert Ok(c) = utf_codepoint(99)
/// from_utf_codepoints([a, b, c])
/// // -> "abc"
/// ```
///
@external(erlang, "gleam_stdlib", "utf_codepoint_list_to_string")
@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_list_to_string")
pub fn from_utf_codepoints(utf_codepoints: List(UtfCodepoint)) -> String
/// Converts an integer to a `UtfCodepoint`.
///
/// Returns an `Error` if the integer does not represent a valid UTF codepoint.
///
pub fn utf_codepoint(value: Int) -> Result(UtfCodepoint, Nil) {
case value {
i if i > 1_114_111 -> Error(Nil)
65_534 | 65_535 -> Error(Nil)
i if i >= 55_296 && i <= 57_343 -> Error(Nil)
i if i < 0 -> Error(Nil)
i -> Ok(unsafe_int_to_utf_codepoint(i))
}
}
/// Converts an UtfCodepoint to its ordinal code point value.
///
/// ## Examples
///
/// ```gleam
/// let assert [utf_codepoint, ..] = to_utf_codepoints("💜")
/// utf_codepoint_to_int(utf_codepoint)
/// // -> 128156
/// ```
///
@external(erlang, "gleam_stdlib", "identity")
@external(javascript, "../gleam_stdlib.mjs", "utf_codepoint_to_int")
pub fn utf_codepoint_to_int(cp: UtfCodepoint) -> Int
/// Converts a `String` into `Option(String)` where an empty `String` becomes
/// `None`.
///
/// ## Examples
///
/// ```gleam
/// to_option("")
/// // -> None
/// ```
///
/// ```gleam
/// to_option("hats")
/// // -> Some("hats")
/// ```
///
pub fn to_option(string: String) -> Option(String) {
case string {
"" -> None
_ -> Some(string)
}
}
/// Returns the first grapheme cluster in a given `String` and wraps it in a
/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.
/// Otherwise, it returns `Ok(String)`.
///
/// ## Examples
///
/// ```gleam
/// first("")
/// // -> Error(Nil)
/// ```
///
/// ```gleam
/// first("icecream")
/// // -> Ok("i")
/// ```
///
pub fn first(string: String) -> Result(String, Nil) {
case pop_grapheme(string) {
Ok(#(first, _)) -> Ok(first)
Error(e) -> Error(e)
}
}
/// Returns the last grapheme cluster in a given `String` and wraps it in a
/// `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.
/// Otherwise, it returns `Ok(String)`.
///
/// ## Examples
///
/// ```gleam
/// last("")
/// // -> Error(Nil)
/// ```
///
/// ```gleam
/// last("icecream")
/// // -> Ok("m")
/// ```
///
pub fn last(string: String) -> Result(String, Nil) {
case pop_grapheme(string) {
Ok(#(first, "")) -> Ok(first)
Ok(#(_, rest)) -> Ok(slice(rest, -1, 1))
Error(e) -> Error(e)
}
}
/// Creates a new `String` with the first grapheme in the input `String`
/// converted to uppercase and the remaining graphemes to lowercase.
///
/// ## Examples
///
/// ```gleam
/// capitalise("mamouna")
/// // -> "Mamouna"
/// ```
///
pub fn capitalise(string: String) -> String {
case pop_grapheme(string) {
Ok(#(first, rest)) -> append(to: uppercase(first), suffix: lowercase(rest))
_ -> ""
}
}
/// Returns a `String` representation of a term in Gleam syntax.
///
pub fn inspect(term: anything) -> String {
do_inspect(term)
|> string_tree.to_string
}
@external(erlang, "gleam_stdlib", "inspect")
@external(javascript, "../gleam_stdlib.mjs", "inspect")
fn do_inspect(term: anything) -> StringTree
/// Returns the number of bytes in a `String`.
///
/// This function runs in constant time on Erlang and in linear time on
/// JavaScript.
///
/// ## Examples
///
/// ```gleam
/// byte_size("🏳️⚧️🏳️🌈👩🏾❤️👨🏻")
/// // -> 58
/// ```
///
@external(erlang, "erlang", "byte_size")
@external(javascript, "../gleam_stdlib.mjs", "byte_size")
pub fn byte_size(string: String) -> Int