2026-01-25 03:58:39 +00:00
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > String - Wren-CLI Manual</ title >
< link rel = "stylesheet" href = "../css/style.css" >
</ head >
< body >
< button class = "mobile-menu-toggle" > Menu</ button >
< div class = "container" >
< aside class = "sidebar" >
< div class = "sidebar-header" >
< h1 >< a href = "../index.html" > Wren-CLI</ a ></ h1 >
< div class = "version" > v0.4.0</ div >
</ div >
< nav class = "sidebar-nav" >
< div class = "section" >
< span class = "section-title" > Getting Started</ span >
< ul >
< li >< a href = "../getting-started/index.html" > Overview</ a ></ li >
< li >< a href = "../getting-started/installation.html" > Installation</ a ></ li >
< li >< a href = "../getting-started/first-script.html" > First Script</ a ></ li >
< li >< a href = "../getting-started/repl.html" > Using the REPL</ a ></ li >
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > Language</ span >
< ul >
< li >< a href = "../language/index.html" > Syntax Overview</ a ></ li >
< li >< a href = "../language/classes.html" > Classes</ a ></ li >
< li >< a href = "../language/methods.html" > Methods</ a ></ li >
< li >< a href = "../language/control-flow.html" > Control Flow</ a ></ li >
< li >< a href = "../language/fibers.html" > Fibers</ a ></ li >
< li >< a href = "../language/modules.html" > Modules</ a ></ li >
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > API Reference</ span >
< ul >
< li >< a href = "index.html" > Overview</ a ></ li >
< li >< a href = "string.html" class = "active" > String</ a ></ li >
2026-01-25 12:09:28 +00:00
< li >< a href = "number.html" > Num</ a ></ li >
2026-01-25 03:58:39 +00:00
< li >< a href = "argparse.html" > argparse</ a ></ li >
2026-01-25 12:09:28 +00:00
< li >< a href = "base64.html" > base64</ a ></ li >
< li >< a href = "crypto.html" > crypto</ a ></ li >
2026-01-25 03:58:39 +00:00
< li >< a href = "dataset.html" > dataset</ a ></ li >
2026-01-25 12:09:28 +00:00
< li >< a href = "datetime.html" > datetime</ a ></ li >
< li >< a href = "dns.html" > dns</ a ></ li >
< li >< a href = "env.html" > env</ a ></ li >
< li >< a href = "fswatch.html" > fswatch</ a ></ li >
< li >< a href = "html.html" > html</ a ></ li >
< li >< a href = "http.html" > http</ a ></ li >
< li >< a href = "io.html" > io</ a ></ li >
< li >< a href = "jinja.html" > jinja</ a ></ li >
< li >< a href = "json.html" > json</ a ></ li >
2026-01-25 03:58:39 +00:00
< li >< a href = "markdown.html" > markdown</ a ></ li >
2026-01-25 12:09:28 +00:00
< li >< a href = "math.html" > math</ a ></ li >
< li >< a href = "net.html" > net</ a ></ li >
< li >< a href = "os.html" > os</ a ></ li >
< li >< a href = "pathlib.html" > pathlib</ a ></ li >
< li >< a href = "regex.html" > regex</ a ></ li >
< li >< a href = "scheduler.html" > scheduler</ a ></ li >
< li >< a href = "signal.html" > signal</ a ></ li >
< li >< a href = "sqlite.html" > sqlite</ a ></ li >
< li >< a href = "subprocess.html" > subprocess</ a ></ li >
< li >< a href = "sysinfo.html" > sysinfo</ a ></ li >
< li >< a href = "tempfile.html" > tempfile</ a ></ li >
< li >< a href = "timer.html" > timer</ a ></ li >
< li >< a href = "tls.html" > tls</ a ></ li >
< li >< a href = "udp.html" > udp</ a ></ li >
< li >< a href = "uuid.html" > uuid</ a ></ li >
< li >< a href = "wdantic.html" > wdantic</ a ></ li >
2026-01-25 03:58:39 +00:00
< li >< a href = "web.html" > web</ a ></ li >
2026-01-25 12:09:28 +00:00
< li >< a href = "websocket.html" > websocket</ a ></ li >
2026-01-25 03:58:39 +00:00
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > Tutorials</ span >
< ul >
< li >< a href = "../tutorials/index.html" > Tutorial List</ a ></ li >
< li >< a href = "../tutorials/http-client.html" > HTTP Client</ a ></ li >
< li >< a href = "../tutorials/websocket-chat.html" > WebSocket Chat</ a ></ li >
< li >< a href = "../tutorials/database-app.html" > Database App</ a ></ li >
< li >< a href = "../tutorials/template-rendering.html" > Templates</ a ></ li >
< li >< a href = "../tutorials/cli-tool.html" > CLI Tool</ a ></ li >
2026-01-25 18:02:02 +00:00
< li >< a href = "../tutorials/web-server.html" > Web Server</ a ></ li >
2026-01-25 03:58:39 +00:00
</ ul >
</ div >
< div class = "section" >
< span class = "section-title" > How-To Guides</ span >
< ul >
< li >< a href = "../howto/index.html" > How-To List</ a ></ li >
< li >< a href = "../howto/http-requests.html" > HTTP Requests</ a ></ li >
< li >< a href = "../howto/json-parsing.html" > JSON Parsing</ a ></ li >
< li >< a href = "../howto/regex-patterns.html" > Regex Patterns</ a ></ li >
< li >< a href = "../howto/file-operations.html" > File Operations</ a ></ li >
< li >< a href = "../howto/async-operations.html" > Async Operations</ a ></ li >
< li >< a href = "../howto/error-handling.html" > Error Handling</ a ></ li >
</ ul >
</ div >
2026-01-25 18:02:02 +00:00
< div class = "section" >
< span class = "section-title" > Contributing</ span >
< ul >
< li >< a href = "../contributing/index.html" > Overview</ a ></ li >
< li >< a href = "../contributing/module-overview.html" > Module Architecture</ a ></ li >
< li >< a href = "../contributing/pure-wren-module.html" > Pure-Wren Modules</ a ></ li >
< li >< a href = "../contributing/c-backed-module.html" > C-Backed Modules</ a ></ li >
< li >< a href = "../contributing/foreign-classes.html" > Foreign Classes</ a ></ li >
< li >< a href = "../contributing/async-patterns.html" > Async Patterns</ a ></ li >
< li >< a href = "../contributing/testing.html" > Writing Tests</ a ></ li >
< li >< a href = "../contributing/documentation.html" > Documentation</ a ></ li >
</ ul >
</ div >
2026-01-25 03:58:39 +00:00
</ nav >
</ aside >
< main class = "content" >
< nav class = "breadcrumb" >
< a href = "../index.html" > Home</ a >
< span class = "separator" > /</ span >
< a href = "index.html" > API Reference</ a >
< span class = "separator" > /</ span >
< span > String</ span >
</ nav >
< article >
< h1 > String</ h1 >
< p > The < code > String</ code > class is a core type available globally without imports. Strings in Wren are immutable sequences of bytes, typically representing UTF-8 encoded text. All methods return new strings rather than modifying the original.</ p >
< pre >< code > var s = "Hello World"
System.print(s.lower) // hello world
System.print(s.upper) // HELLO WORLD
System.print(s.title) // Hello World
System.print(s.reverse) // dlroW olleH</ code ></ pre >
< h2 > Case Conversion</ h2 >
< div class = "method-signature" >
< span class = "method-name" > lower</ span > → < span class = "type" > String</ span >
</ div >
< p > Returns the string with all ASCII uppercase characters converted to lowercase.</ p >
< pre >< code > "Hello World".lower // "hello world"
"ABC 123".lower // "abc 123"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > upper</ span > → < span class = "type" > String</ span >
</ div >
< p > Returns the string with all ASCII lowercase characters converted to uppercase.</ p >
< pre >< code > "Hello World".upper // "HELLO WORLD"
"abc 123".upper // "ABC 123"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > capitalize</ span > → < span class = "type" > String</ span >
</ div >
< p > Returns the string with the first character uppercased and the rest lowercased.</ p >
< pre >< code > "hello world".capitalize // "Hello world"
"HELLO".capitalize // "Hello"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > title</ span > → < span class = "type" > String</ span >
</ div >
< p > Returns the string with the first character of each word capitalized and the rest lowercased. Words are separated by whitespace.</ p >
< pre >< code > "hello world".title // "Hello World"
"HELLO WORLD".title // "Hello World"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > swapCase</ span > → < span class = "type" > String</ span >
</ div >
< p > Returns the string with uppercase characters converted to lowercase and vice versa.</ p >
< pre >< code > "Hello World".swapCase // "hELLO wORLD"</ code ></ pre >
< h2 > Character Testing</ h2 >
< div class = "method-signature" >
< span class = "method-name" > isLower</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if the string contains at least one alphabetic character and all alphabetic characters are lowercase.</ p >
< pre >< code > "hello".isLower // true
"hello1".isLower // true
"Hello".isLower // false
"123".isLower // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > isUpper</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if the string contains at least one alphabetic character and all alphabetic characters are uppercase.</ p >
< pre >< code > "HELLO".isUpper // true
"HELLO1".isUpper // true
"Hello".isUpper // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > isDigit</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if the string is non-empty and all bytes are ASCII digits (0-9).</ p >
< pre >< code > "12345".isDigit // true
"123a5".isDigit // false
"".isDigit // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > isAlpha</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if the string is non-empty and all bytes are ASCII letters (a-z, A-Z).</ p >
< pre >< code > "hello".isAlpha // true
"hello1".isAlpha // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > isAlphaNumeric</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if the string is non-empty and all bytes are ASCII letters or digits.</ p >
< pre >< code > "hello123".isAlphaNumeric // true
"hello!".isAlphaNumeric // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > isSpace</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if the string is non-empty and all bytes are ASCII whitespace (space, tab, newline, carriage return, form feed, vertical tab).</ p >
< pre >< code > " ".isSpace // true
" \t\n".isSpace // true
"hello".isSpace // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > isAscii</ span > → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if all bytes in the string are less than 128. Returns < code > true</ code > for empty strings.</ p >
< pre >< code > "hello".isAscii // true
"".isAscii // true</ code ></ pre >
< h2 > Search</ h2 >
< div class = "method-signature" >
< span class = "method-name" > lastIndexOf</ span > (< span class = "param" > search</ span > ) → < span class = "type" > Num</ span >
</ div >
< p > Returns the byte index of the last occurrence of < code > search</ code > in the string, or < code > -1</ code > if not found.</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > search</ span > < span class = "param-type" > (String)</ span > - The substring to search for</ li >
< li >< span class = "returns" > Returns:</ span > Byte index or -1</ li >
</ ul >
< pre >< code > "hello world hello".lastIndexOf("hello") // 12
"hello".lastIndexOf("x") // -1</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > lastIndexOf</ span > (< span class = "param" > search</ span > , < span class = "param" > start</ span > ) → < span class = "type" > Num</ span >
</ div >
< p > Returns the byte index of the last occurrence of < code > search</ code > at or before < code > start</ code > , or < code > -1</ code > if not found.</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > search</ span > < span class = "param-type" > (String)</ span > - The substring to search for</ li >
< li >< span class = "param-name" > start</ span > < span class = "param-type" > (Num)</ span > - Maximum byte index to search from</ li >
< li >< span class = "returns" > Returns:</ span > Byte index or -1</ li >
</ ul >
< pre >< code > "hello world hello".lastIndexOf("hello", 11) // 0
"hello world hello".lastIndexOf("hello", 12) // 12</ code ></ pre >
< h2 > Transformation</ h2 >
< div class = "method-signature" >
< span class = "method-name" > reverse</ span > → < span class = "type" > String</ span >
</ div >
< p > Returns the string with characters in reverse order. Code point aware for UTF-8 strings.</ p >
< pre >< code > "hello".reverse // "olleh"
"abcde".reverse // "edcba"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > center</ span > (< span class = "param" > width</ span > ) → < span class = "type" > String</ span >
</ div >
< p > Centers the string in a field of < code > width</ code > characters, padded with spaces.</ p >
< pre >< code > "hi".center(10) // " hi "</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > center</ span > (< span class = "param" > width</ span > , < span class = "param" > char</ span > ) → < span class = "type" > String</ span >
</ div >
< p > Centers the string in a field of < code > width</ code > characters, padded with the given fill character.</ p >
< pre >< code > "hi".center(10, "-") // "----hi----"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > lpad</ span > (< span class = "param" > width</ span > , < span class = "param" > char</ span > ) → < span class = "type" > String</ span >
</ div >
< p > Left-pads the string to < code > width</ code > characters using the given fill character.</ p >
< pre >< code > "42".lpad(5, "0") // "00042"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > rpad</ span > (< span class = "param" > width</ span > , < span class = "param" > char</ span > ) → < span class = "type" > String</ span >
</ div >
< p > Right-pads the string to < code > width</ code > characters using the given fill character.</ p >
< pre >< code > "hi".rpad(5, ".") // "hi..."</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > zfill</ span > (< span class = "param" > width</ span > ) → < span class = "type" > String</ span >
</ div >
< p > Pads the string with leading zeros to < code > width</ code > characters. Preserves a leading < code > -</ code > or < code > +</ code > sign.</ p >
< pre >< code > "42".zfill(5) // "00042"
"-42".zfill(6) // "-00042"
"+42".zfill(6) // "+00042"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > removePrefix</ span > (< span class = "param" > prefix</ span > ) → < span class = "type" > String</ span >
</ div >
< p > If the string starts with < code > prefix</ code > , returns the string with the prefix removed. Otherwise returns the original string.</ p >
< pre >< code > "HelloWorld".removePrefix("Hello") // "World"
"HelloWorld".removePrefix("World") // "HelloWorld"</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > removeSuffix</ span > (< span class = "param" > suffix</ span > ) → < span class = "type" > String</ span >
</ div >
< p > If the string ends with < code > suffix</ code > , returns the string with the suffix removed. Otherwise returns the original string.</ p >
< pre >< code > "HelloWorld".removeSuffix("World") // "Hello"
"HelloWorld".removeSuffix("Hello") // "HelloWorld"</ code ></ pre >
< h2 > Splitting & Conversion</ h2 >
< div class = "method-signature" >
< span class = "method-name" > splitLines</ span > → < span class = "type" > List</ span >
</ div >
< p > Splits the string by line endings (< code > \n</ code > , < code > \r\n</ code > , < code > \r</ code > ) and returns a list of strings.</ p >
< pre >< code > "line1\nline2\nline3".splitLines // ["line1", "line2", "line3"]
"a\r\nb\r\nc".splitLines // ["a", "b", "c"]</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > chars</ span > → < span class = "type" > List</ span >
</ div >
< p > Returns a list of individual characters (code points) in the string.</ p >
< pre >< code > "abc".chars // ["a", "b", "c"]
"".chars // []</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > toNum</ span > → < span class = "type" > Num</ span > | < span class = "type" > Null</ span >
</ div >
< p > Parses the string as a number. Returns < code > null</ code > if the string cannot be parsed.</ p >
< pre >< code > "42".toNum // 42
"3.14".toNum // 3.14
"-7".toNum // -7
"abc".toNum // null</ code ></ pre >
< h2 > Comparison</ h2 >
< p > Strings support lexicographic comparison using the standard comparison operators. Comparison is byte-by-byte using the raw byte values, which produces correct results for ASCII and UTF-8 encoded text.</ p >
< div class = "method-signature" >
< span class = "method-name" > < </ span > (< span class = "param" > other</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if this string is lexicographically less than < code > other</ code > .</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > other</ span > < span class = "param-type" > (String)</ span > - The string to compare against</ li >
</ ul >
< pre >< code > "apple" < "banana" // true
"abc" < "abd" // true
"abc" < "abcd" // true (prefix is less than longer string)</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > > </ span > (< span class = "param" > other</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if this string is lexicographically greater than < code > other</ code > .</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > other</ span > < span class = "param-type" > (String)</ span > - The string to compare against</ li >
</ ul >
< pre >< code > "banana" > "apple" // true
"abd" > "abc" // true
"abcd" > "abc" // true</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > < =</ span > (< span class = "param" > other</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if this string is lexicographically less than or equal to < code > other</ code > .</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > other</ span > < span class = "param-type" > (String)</ span > - The string to compare against</ li >
</ ul >
< pre >< code > "abc" < = "abc" // true
"abc" < = "abd" // true
"abd" < = "abc" // false</ code ></ pre >
< div class = "method-signature" >
< span class = "method-name" > > =</ span > (< span class = "param" > other</ span > ) → < span class = "type" > Bool</ span >
</ div >
< p > Returns < code > true</ code > if this string is lexicographically greater than or equal to < code > other</ code > .</ p >
< ul class = "param-list" >
< li >< span class = "param-name" > other</ span > < span class = "param-type" > (String)</ span > - The string to compare against</ li >
</ ul >
< pre >< code > "abc" >= "abc" // true
"abd" >= "abc" // true
"abc" >= "abd" // false</ code ></ pre >
< div class = "admonition tip" >
< div class = "admonition-title" > Tip</ div >
< p > String comparison is byte-based, so uppercase letters sort before lowercase letters in ASCII order (e.g., < code > "Z" < "a"</ code > is < code > true</ code > ). If you need case-insensitive comparison, convert both strings to the same case first using < code > lower</ code > or < code > upper</ code > .</ p >
</ div >
< h2 > Existing Methods</ h2 >
< p > The following methods are also available on all strings as part of the core VM.</ p >
< table >
< tr >
< th > Method</ th >
< th > Description</ th >
</ tr >
< tr >
< td >< code > contains(s)</ code ></ td >
< td > Returns true if the string contains < code > s</ code ></ td >
</ tr >
< tr >
< td >< code > startsWith(s)</ code ></ td >
< td > Returns true if the string starts with < code > s</ code ></ td >
</ tr >
< tr >
< td >< code > endsWith(s)</ code ></ td >
< td > Returns true if the string ends with < code > s</ code ></ td >
</ tr >
< tr >
< td >< code > indexOf(s)</ code ></ td >
< td > Returns the byte index of < code > s</ code > , or -1</ td >
</ tr >
< tr >
< td >< code > indexOf(s, start)</ code ></ td >
< td > Returns the byte index of < code > s</ code > starting from < code > start</ code ></ td >
</ tr >
< tr >
< td >< code > split(delim)</ code ></ td >
< td > Splits by delimiter, returns a list</ td >
</ tr >
< tr >
< td >< code > replace(from, to)</ code ></ td >
< td > Replaces all occurrences of < code > from</ code > with < code > to</ code ></ td >
</ tr >
< tr >
< td >< code > trim()</ code ></ td >
< td > Removes leading and trailing whitespace</ td >
</ tr >
< tr >
< td >< code > trimStart()</ code ></ td >
< td > Removes leading whitespace</ td >
</ tr >
< tr >
< td >< code > trimEnd()</ code ></ td >
< td > Removes trailing whitespace</ td >
</ tr >
< tr >
< td >< code > bytes</ code ></ td >
< td > Returns a sequence of byte values</ td >
</ tr >
< tr >
< td >< code > codePoints</ code ></ td >
< td > Returns a sequence of code point values</ td >
</ tr >
< tr >
< td >< code > count</ code ></ td >
< td > Number of code points in the string</ td >
</ tr >
< tr >
< td >< code > isEmpty</ code ></ td >
< td > Returns true if the string has no characters</ td >
</ tr >
< tr >
< td >< code > *(n)</ code ></ td >
< td > Repeats the string < code > n</ code > times</ td >
</ tr >
</ table >
< div class = "admonition note" >
< div class = "admonition-title" > Note</ div >
< p > String is a core type available globally. No < code > import</ code > statement is needed. All string methods operate on ASCII characters. Multi-byte UTF-8 characters are preserved but case conversion applies only to ASCII letters (a-z, A-Z).</ p >
</ div >
</ article >
< footer class = "page-footer" >
< a href = "index.html" class = "prev" > Overview</ a >
< a href = "http.html" class = "next" > http</ a >
</ footer >
</ main >
</ div >
< script src = "../js/main.js" ></ script >
</ body >
</ html >