Strings
Tova provides a rich set of string manipulation functions. All string functions are non-mutating -- they return new strings.
Method Syntax
String functions can be called in two ways:
// Standalone function call
upper("hello") // "HELLO"
// Method call on a string
"hello".upper() // "HELLO"Both forms are equivalent. The method syntax is often more readable when chaining operations.
String Interpolation
Tova strings support interpolation with {}:
name = "Alice"
age = 30
print("Hello, {name}! You are {age} years old.")
// Hello, Alice! You are 30 years old.
print("2 + 2 = {2 + 2}")
// 2 + 2 = 4String Repetition
The * operator repeats a string:
"-" * 40
// "----------------------------------------"
"ha" * 3
// "hahaha"Trimming & Splitting
trim
trim(s) -> StringRemoves whitespace from both ends of a string.
trim(" hello ") // "hello"
trim("\n\thello\n") // "hello"trim_start
trim_start(s) -> StringRemoves whitespace from the beginning of a string.
trim_start(" hello ") // "hello "trim_end
trim_end(s) -> StringRemoves whitespace from the end of a string.
trim_end(" hello ") // " hello"split
split(s, sep) -> List[String]Splits a string by a separator and returns an array of parts.
split("a,b,c", ",") // ["a", "b", "c"]
split("hello world", " ") // ["hello", "world"]
split("one::two::three", "::") // ["one", "two", "three"]join
join(arr, sep) -> StringJoins an array of strings with a separator.
join(["a", "b", "c"], ", ") // "a, b, c"
join(["hello", "world"], " ") // "hello world"
join(["one", "two"], "") // "onetwo"words
words(s) -> List[String]Splits a string by whitespace, filtering out empty strings.
words("hello world") // ["hello", "world"]
words(" spaced out ") // ["spaced", "out"]lines
lines(s) -> List[String]Splits a string by newline characters.
lines("line1\nline2\nline3") // ["line1", "line2", "line3"]chars
chars(s) -> List[String]Splits a string into an array of individual characters.
chars("hello") // ["h", "e", "l", "l", "o"]
chars("abc") |> reversed() |> join("") // "cba"Search & Test
contains
contains(s, sub) -> BoolReturns true if the string contains the given substring.
contains("hello world", "world") // true
contains("hello world", "xyz") // false
// Method syntax
"hello world".contains("ell") // truestarts_with
starts_with(s, prefix) -> BoolReturns true if the string starts with the given prefix.
starts_with("hello", "hel") // true
starts_with("hello", "world") // false
"hello".starts_with("hel") // trueends_with
ends_with(s, suffix) -> BoolReturns true if the string ends with the given suffix.
ends_with("hello.tova", ".tova") // true
ends_with("hello.tova", ".js") // false
"photo.png".ends_with(".png") // trueReplacing
replace
replace(s, from, to) -> StringReplaces occurrences in a string. When from is a plain string, all occurrences are replaced. When from is a regex, the first match is replaced.
replace("hello world", "world", "Tova")
// "hello Tova"
replace("aabbcc", "b", "x")
// "aaxxcc"replace_first
replace_first(s, from, to) -> StringReplaces only the first occurrence of from with to.
replace_first("aabb", "a", "x") // "xabb"
replace_first("hello hello", "hello", "hi") // "hi hello"repeat
repeat(s, n) -> StringRepeats a string n times.
repeat("ha", 3) // "hahaha"
repeat("-", 20) // "--------------------"
repeat("ab", 0) // ""Padding
pad_start
pad_start(s, n, fill?) -> StringPads the beginning of a string to reach length n. Uses spaces by default, or the optional fill character.
pad_start("5", 3, "0") // "005"
pad_start("hi", 5) // " hi"
pad_start("42", 5, ".") // "...42"pad_end
pad_end(s, n, fill?) -> StringPads the end of a string to reach length n.
pad_end("5", 3, "0") // "500"
pad_end("hi", 5) // "hi "Character Access
char_at
char_at(s, i) -> String | NilReturns the character at position i, or nil if out of bounds.
char_at("hello", 0) // "h"
char_at("hello", 4) // "o"
char_at("hello", 10) // nilCase Conversion
upper
upper(s) -> StringConverts a string to uppercase.
upper("hello") // "HELLO"
"hello".upper() // "HELLO"lower
lower(s) -> StringConverts a string to lowercase.
lower("HELLO") // "hello"
"HELLO".lower() // "hello"capitalize
capitalize(s) -> StringUppercases the first letter of the string.
capitalize("hello") // "Hello"
capitalize("hello world") // "Hello world"title_case
title_case(s) -> StringUppercases the first letter of each word.
title_case("hello world") // "Hello World"
title_case("the quick brown fox") // "The Quick Brown Fox"snake_case
snake_case(s) -> StringConverts a string to snake_case. Handles camelCase, spaces, and hyphens.
snake_case("helloWorld") // "hello_world"
snake_case("Hello World") // "hello_world"
snake_case("some-thing") // "some_thing"
snake_case("XMLParser") // "xml_parser"camel_case
camel_case(s) -> StringConverts a string to camelCase. Handles snake_case, spaces, and hyphens.
camel_case("hello_world") // "helloWorld"
camel_case("Hello World") // "helloWorld"
camel_case("some-thing") // "someThing"kebab_case
kebab_case(s) -> StringConverts a string to kebab-case. Handles camelCase, spaces, and underscores.
kebab_case("helloWorld") // "hello-world"
kebab_case("Hello World") // "hello-world"
kebab_case("some_thing") // "some-thing"Searching & Counting
index_of
index_of(s, sub) -> Int | NilReturns the position of the first occurrence of sub in s. Returns nil if not found.
index_of("hello world", "world") // 6
index_of("abcabc", "bc") // 1
index_of("hello", "xyz") // nillast_index_of
last_index_of(s, sub) -> Int | NilReturns the position of the last occurrence of sub in s. Returns nil if not found.
last_index_of("abcabc", "bc") // 4
last_index_of("hello", "l") // 3
last_index_of("hello", "xyz") // nilcount_of
count_of(s, sub) -> IntCounts the number of non-overlapping occurrences of sub in s.
count_of("banana", "an") // 2
count_of("mississippi", "s") // 4
count_of("hello", "xyz") // 0Substrings & Transformation
substr
substr(s, start, end?) -> StringExtracts a portion of the string from start to end (exclusive). If end is omitted, extracts to the end of the string. Supports negative indices.
substr("hello world", 6) // "world"
substr("hello world", 0, 5) // "hello"
substr("hello", -3) // "llo"reverse_str
reverse_str(s) -> StringReverses a string.
reverse_str("hello") // "olleh"
reverse_str("racecar") // "racecar"
reverse_str("") // ""center
center(s, n, fill?) -> StringCenter-pads a string to width n. Uses spaces by default, or the optional fill character. Returns the string unchanged if already wider.
center("hi", 6) // " hi "
center("hi", 7) // " hi "
center("hi", 6, "*") // "**hi**"
center("hello", 3) // "hello"is_empty
is_empty(v) -> BoolReturns true if a value is empty. Works for strings, arrays, objects, and nil.
is_empty("") // true
is_empty("hello") // false
is_empty([]) // true
is_empty({}) // true
is_empty(nil) // trueText Processing
truncate
truncate(s, n, suffix?) -> StringTruncates a string to at most n characters, appending suffix (default "...") if truncated.
truncate("Hello World", 8) // "Hello..."
truncate("Hi", 10) // "Hi"
truncate("Hello World", 8, "..") // "Hello .."word_wrap
word_wrap(s, width) -> StringWraps text at word boundaries to fit within width characters per line.
word_wrap("one two three four", 10)
// "one two\nthree four"
word_wrap("the quick brown fox", 12)
// "the quick\nbrown fox"dedent
dedent(s) -> StringRemoves common leading whitespace from all lines. Useful for cleaning up indented multi-line strings.
dedent(" hello\n world") // "hello\nworld"
dedent(" line1\n line2") // " line1\nline2"indent_str
indent_str(s, n, ch?) -> StringAdds n repetitions of ch (default: space) to the beginning of each line.
indent_str("hello\nworld", 2) // " hello\n world"
indent_str("a\nb", 1, ">") // ">a\n>b"slugify
slugify(s) -> StringConverts a string to a URL-friendly slug: lowercased, special characters removed, spaces replaced with hyphens.
slugify("Hello World!") // "hello-world"
slugify("A & B @ C") // "a-b-c"
slugify(" My Blog Post ") // "my-blog-post"escape_html
escape_html(s) -> StringEscapes HTML special characters (<, >, &, ", ').
escape_html("<b>Hello</b>")
// "<b>Hello</b>"
escape_html("a > b & c < d")
// "a > b & c < d"unescape_html
unescape_html(s) -> StringReverses HTML entity escaping.
unescape_html("<b>Hello</b>")
// "<b>Hello</b>"fmt
fmt(template, ...args) -> StringSimple placeholder formatting. Replaces {} placeholders with arguments in order.
fmt("Hello, {}!", "world") // "Hello, world!"
fmt("{} + {} = {}", 1, 2, 3) // "1 + 2 = 3"
fmt("{} items at ${}", 3, 9.99) // "3 items at $9.99"Pipeline Examples
String functions work naturally with the pipe operator |>:
// Clean and normalize user input
input
|> trim()
|> lower()
|> replace(" ", " ")
// Parse CSV line
"Alice,30,Engineer"
|> split(",")
|> enumerate()
// [[0, "Alice"], [1, "30"], [2, "Engineer"]]
// Build a slug from a title
"Hello World! This is Tova."
|> slugify()
// "hello-world-this-is-tova"
// Count vowels
"hello world"
|> chars()
|> filter(fn(c) contains("aeiou", c))
|> len()
// 3
// Escape user input for HTML
user_input
|> trim()
|> escape_html()String Concatenation
Use string interpolation or the + operator for concatenation:
// Interpolation (preferred)
greeting = "Hello, {name}!"
// Plus operator
"hello" + " " + "world" // "hello world"The ++ operator is available in match patterns for string prefix matching:
match url {
"/api/" ++ rest => handle_api(rest)
_ => not_found()
}Terminal Formatting
Functions for styling text output in the terminal.
color
color(text, colorName) -> StringWraps text with ANSI color codes for terminal output. Supported colors include "red", "green", "blue", "yellow", "cyan", "magenta", "white", "gray".
print(color("Error!", "red"))
print(color("Success", "green"))
print(color("Warning", "yellow"))bold
bold(text) -> StringWraps text with ANSI bold codes for terminal output.
print(bold("Important message"))
print(bold(color("Error!", "red")))dim
dim(text) -> StringWraps text with ANSI dim codes for terminal output.
print(dim("Less important info"))
print(dim("(optional)"))