Text

Functions for working with text (UTF-8 strings) and character values.

pub fn len(self: text) -> integer

Number of characters (Unicode code points) in the text — the human count, as in every mainstream language. For a byte length (bounds checks, the limit of byte-positioned indexing / slicing) use size.

pub fn size(self: text) -> integer

Number of bytes in the text. This is the bound for byte-positioned operations: s[i], slices s[a..b], and find/rfind all use byte offsets. For the human character count use len.

pub fn len(self: character) -> integer

Byte length of the character's UTF-8 encoding (1–4).

pub operator compare(self: text, other: text) -> Ordering

Where self stands against other, in the order < uses: by bytes, as < compares text.

pub operator compare(self: character, other: character) -> Ordering

Where self stands against other, by code point, in the order < uses.

pub fn split(self: text, separator: character) -> vector<text>

Splits self on every occurrence of separator and returns the parts as a vector. Use to parse CSV lines or space-separated tokens. Every separator ends a part, so a trailing separator leaves an empty last part ("a,".split(',') is ["a", ""]); an empty text has no parts at all.

pub fn split_text(self: text, separator: text) -> vector<text>

Split on a multi-character text separator. "a, b, c".split_text(", ") returns ["a", "b", "c"]. Edge cases: - empty self → empty result - empty separator → returns [self] unchanged (no infinite-split) - separator never matches → returns [self] - separator at start / end → produces empty boundary entries

pub fn starts_with_at(self: text, pos: integer, prefix: text) -> boolean

Functions for searching, transforming, and classifying text and character values. Character classification functions return true only if every character in the text satisfies the condition. The single-character variants test one code point. Returns true if self contains prefix starting at byte position pos. Sugar over self[pos..pos + prefix.size()] == prefix for the common "is this token at this offset?" pattern in scanners / parsers. Returns false (not an error) when pos + prefix.size() exceeds self.size() — same shape as starts_with for the "prefix too long for input" case.

Faster than comparing characters one at a time for a known prefix at pos.

pub fn char_slice(self: text, from: integer, to: integer) -> text

The characters of self from from up to (not including) to — a slice that counts CHARACTERS where self[a..b] counts BYTES.

⚠ **This is the cure for the commonest text bug in this stack.** len(text) counts characters while self[a..b] slices bytes, and loft snaps a byte cut outward to a character boundary — so a count computed from len and applied as a byte range fits FEWER characters than it measured. The failure is not mojibake but something quieter: the text comes back SHORT, silently, and only when it is not ASCII, so every ASCII test stays green. "héllo"[0..4] is "hél"; "héllo".char_slice(0, 4) is "héll".

Use it wherever a character COUNT becomes a cut: fitting a label to a width, wrapping a line, a caret or a selection in a text field, truncating with an ellipsis. Reach for self[a..b] only when the numbers came from a byte source — find, size, byte_at.

Negative bounds count from the end, as a byte slice's do (char_slice(-2, n) is the last two characters); both ends clamp, and a reversed or empty range answers "" rather than failing.

pub fn trim(self: text) -> text[self]

Removes leading and trailing whitespace. Use when processing user input or file content.

pub fn trim_start(self: text) -> text[self]

Removes leading whitespace only.

pub fn trim_end(self: text) -> text[self]

Removes trailing whitespace only.

pub fn find(self: text, value: text) -> integer?

Returns the byte index of the first occurrence of value, or null if not found. Use to locate substrings before slicing. Nullable: null when value is absent (the type is honest about the not-found case).

pub fn rfind(self: text, value: text) -> integer?

Returns the byte index of the last occurrence of value, or null if not found. Use to find file extensions or the last path separator. Nullable: null when value is absent (the type is honest about not-found).

pub fn contains(self: text, value: text) -> boolean

Returns true if value appears anywhere in self. s.contains(v) is s.find(v) != null: find answers the position, contains only whether there is one — the clearer spelling for a membership test.

pub fn replace(self: text, value: text, with: text) -> text

Returns a copy of self with every occurrence of value replaced by with.