Sindarin provides powerful string manipulation with string interpolation, comprehensive methods, and escape sequences.
Basic string literals use double quotes:
var greeting: str = "Hello, World!"
var empty: str = ""
For multi-line strings, use the pipe block syntax with |:
var sql: str = |
SELECT *
FROM users
WHERE active = true
print(sql)
Output:
SELECT *
FROM users
WHERE active = true
- The
|character introduces a multi-line string block - Content starts on the line after
| - Leading whitespace is automatically stripped based on the minimum indentation
- The string ends when a line with less indentation than the starting
|is encountered
Inner indentation relative to the first line is preserved:
var code: str = |
fn main():
print("Hello")
if true:
print("World")
print(code)
Output:
fn main():
print("Hello")
if true:
print("World")
Use $| for multi-line strings with interpolation:
var name: str = "Alice"
var age: int = 30
var greeting: str = $|
Hello {name}!
You are {age} years old.
Next year you'll be {age + 1}.
print(greeting)
Output:
Hello Alice!
You are 30 years old.
Next year you'll be 31.
SQL Queries:
var table: str = "users"
var query: str = $|
SELECT id, name, email
FROM {table}
WHERE created_at > '2024-01-01'
ORDER BY name ASC
HTML Templates:
var title: str = "Welcome"
var html: str = $|
<!DOCTYPE html>
<html>
<head><title>{title}</title></head>
<body>
<h1>{title}</h1>
</body>
</html>
JSON Data:
var name: str = "test"
var value: int = 42
var json: str = $|
{
"name": "{name}",
"value": {value}
}
Use the $ prefix to embed expressions in strings:
var name: str = "World"
var count: int = 42
print($"Hello, {name}! The answer is {count}.\n")
Works with all types:
var pi: double = 3.14
var flag: bool = true
print($"Pi is {pi}, flag is {flag}\n")
Expressions inside {} are evaluated and converted to strings:
var a: int = 5
var b: int = 3
print($"Sum: {a + b}, Product: {a * b}\n") // "Sum: 8, Product: 15"
The following escape sequences are supported in string literals:
| Escape | Character |
|---|---|
\n |
Newline |
\t |
Tab |
\r |
Carriage return |
\\ |
Backslash |
\" |
Double quote |
\' |
Single quote |
\0 |
Null character |
Example:
print("Line 1\nLine 2\n")
print("Column1\tColumn2\tColumn3\n")
print("She said \"Hello!\"\n")
print("Path: C:\\Users\\name\n")
Returns the number of characters in the string:
var size: int = "hello".length // 5
var empty: int = "".length // 0
Converts all characters to uppercase:
var text: str = "Hello World"
var upper: str = text.toUpper() // "HELLO WORLD"
Converts all characters to lowercase:
var text: str = "Hello World"
var lower: str = text.toLower() // "hello world"
Removes whitespace from both ends:
var text: str = " Hello World "
var trimmed: str = text.trim() // "Hello World"
Extracts a portion of the string from start (inclusive) to end (exclusive):
var text: str = "Hello World"
var sub: str = text.substring(0, 5) // "Hello"
var sub2: str = text.substring(6, 11) // "World"
Returns the character at the specified index:
var ch: char = "Hello".charAt(0) // 'H'
var ch2: char = "Hello".charAt(4) // 'o'
Returns the index of the first occurrence of a substring, or -1 if not found:
var idx: int = "hello".indexOf("ll") // 2
var notFound: int = "hello".indexOf("x") // -1
Returns true if the string contains the substring:
var has: bool = "hello".contains("ell") // true
var no: bool = "hello".contains("xyz") // false
Returns true if the string starts with the prefix:
var starts: bool = "hello".startsWith("he") // true
var no: bool = "hello".startsWith("lo") // false
Returns true if the string ends with the suffix:
var ends: bool = "hello".endsWith("lo") // true
var no: bool = "hello".endsWith("he") // false
Replaces all occurrences of a substring:
var replaced: str = "hello".replace("l", "L") // "heLLo"
var updated: str = "foo bar foo".replace("foo", "baz") // "baz bar baz"
Appends a string to the end of the current string, modifying it in place. Returns the string (which must be reassigned as the pointer may change due to reallocation):
var text: str = "Hello"
text = text.append(" World") // "Hello World"
text = text.append("!") // "Hello World!"
The append method is optimized for efficient string building with amortized O(1) performance. When building strings incrementally, prefer append over repeated concatenation:
// Efficient: uses append for incremental building
var result: str = ""
for i in 0..10 =>
result = result.append($"{i} ")
// Less efficient: creates intermediate strings
var result2: str = ""
for i in 0..10 =>
result2 = result2 + $"{i} " // Creates new string each iteration
Important: Always reassign the result of append back to the variable, as the underlying buffer may be reallocated:
var s: str = "start"
s = s.append(" middle") // Correct: reassign the result
s = s.append(" end")
Splits a string by a delimiter and returns an array:
var parts: str[] = "a,b,c".split(",") // {"a", "b", "c"}
var words: str[] = "one two three".split(" ") // {"one", "two", "three"}
Splits on any whitespace (spaces, tabs, newlines):
var words: str[] = "hello world\tfoo".splitWhitespace() // {"hello", "world", "foo"}
Splits on newline characters (\n, \r\n, \r):
var lines: str[] = "line1\nline2\nline3".splitLines() // {"line1", "line2", "line3"}
Returns true if the string is empty or contains only whitespace:
var blank: bool = " ".isBlank() // true
var empty: bool = "".isBlank() // true
var notBlank: bool = "hi".isBlank() // false
var withText: bool = " x ".isBlank() // false
Converts the string to a byte array (UTF-8 encoding):
var bytes: byte[] = "Hello".toBytes() // {72, 101, 108, 108, 111}
String methods can be chained together:
var result: str = " HELLO ".trim().toLower() // "hello"
var words: str[] = " One Two Three ".trim().toLower().split(" ") // {"one", "two", "three"}
var content: str = TextFile.readAll("data.txt")
var lines: str[] = content.splitLines()
for line in lines =>
if !line.isBlank() =>
print($"Processing: {line}\n")
var text: str = TextFile.readAll("document.txt")
var words: str[] = text.splitWhitespace()
print($"Word count: {words.length}\n")
var line: str = "name,age,city"
var fields: str[] = line.split(",")
for field in fields =>
print($"Field: {field.trim()}\n")
fn equalsIgnoreCase(a: str, b: str): bool =>
return a.toLower() == b.toLower()
var same: bool = equalsIgnoreCase("Hello", "HELLO") // true
var parts: str[] = {"apple", "banana", "cherry"}
var csv: str = parts.join(",") // "apple,banana,cherry"
var sentence: str = parts.join(" and ") // "apple and banana and cherry"
- Arrays - Array operations including string arrays
- SDK I/O documentation - File I/O for reading and writing text files