@eryx/text Module

Text-processing helpers for everyday string manipulation.

This module provides a small set of "boring but useful" text utilities: indentation helpers, wrapping and truncation, prefix/suffix checks, simple literal substring counting, and configurable trimming.

The functions in this module operate on Lua strings as byte sequences. They do not perform Unicode-aware grapheme segmentation, display-width calculation, locale-sensitive casing, or language-aware hyphenation. That makes them a good fit for:

Line-oriented helpers normalize output line breaks to \n. Where wrapping or truncation takes a width, that width is measured using Lua's #string length.

Summary

Functions

text.unindent(value: string, columns: number?)string
text.indent(value: string, columns: number)string
text.wrap(value: string, width: number, breakWordThreshold: number?, breakWordMarker: string?)string
text.truncate(value: string, width: number, suffix: string?)string
text.count(value: string, needle: string)number
text.startsWith(value: string, prefix: string)boolean
text.endsWith(value: string, suffix: string)boolean
text.removeStart(value: string, prefix: string)string
text.removeEnd(value: string, suffix: string)string
text.trim(value: string, side: ("start" | "end" | "both")?, trimCharacters: { string }?)string

API Reference

Functions

text.unindent

Removes shared leading indentation from lines in a string.

When columns is omitted, the smallest indentation shared by all non-blank lines is removed. When columns is provided, up to that many leading spaces or tabs are removed from each line. Blank lines do not contribute to the inferred indentation level. Output uses \n line endings.

text.unindent(value: string, columns: number?)string

Parameters

value: string

The string whose lines should be unindented.

columns: number?

Optional explicit number of leading columns to remove.

Returns

The unindented string.

text.indent

Prefixes each line in a string with spaces.

Blank lines are indented too. Output uses \n as the line separator.

text.indent(value: string, columns: number)string

Parameters

value: string

The string whose lines should be indented.

columns: number

Number of spaces to insert at the start of each line.

Returns

The indented string.

text.wrap

Wraps text to a target width.

Wrapping prefers whitespace boundaries. breakWordThreshold controls when word-breaking is allowed or preferred:

  • nil or 0: never break words
  • 1 or 2: break only words that are themselves longer than width
  • 3+: also prefer word-breaking when a whitespace wrap would leave at least that many unused columns at the end of the line

When a word is broken, breakWordMarker is appended to the broken fragment and its width counts against width. The marker defaults to "-". Use "" to break without a marker.

Lines are measured in bytes and output uses \n line endings.

text.wrap(value: string, width: number, breakWordThreshold: number?, breakWordMarker: string?)string

Parameters

value: string

The string to wrap.

width: number

Maximum width of each output line, measured in bytes.

breakWordThreshold: number?

Controls when word-breaking is allowed or preferred.

breakWordMarker: string?

Marker appended to broken word fragments.

Returns

The wrapped string.

text.truncate

Shortens a string to a maximum width, optionally appending a marker.

The marker counts against the width budget. If the marker itself is wider than width, the marker is returned unchanged.

text.truncate(value: string, width: number, suffix: string?)string

Parameters

value: string

The string to truncate.

width: number

Maximum output width, measured in bytes.

suffix: string?

Optional marker appended to truncated output.

Returns

The original or truncated string.

text.count

Counts non-overlapping literal occurrences of a substring.

This uses plain substring matching rather than Lua patterns.

text.count(value: string, needle: string)number

Parameters

value: string

The string to search within.

needle: string

The literal substring to count.

Returns

Number of non-overlapping matches.

text.startsWith

Returns whether a string begins with the given prefix.

text.startsWith(value: string, prefix: string)boolean

Parameters

value: string

The string to inspect.

prefix: string

The prefix to test for.

Returns

true when value starts with prefix.

text.endsWith

Returns whether a string ends with the given suffix.

text.endsWith(value: string, suffix: string)boolean

Parameters

value: string

The string to inspect.

suffix: string

The suffix to test for.

Returns

true when value ends with suffix.

text.removeStart

Removes a prefix when it is present.

If value does not start with prefix, the original string is returned.

text.removeStart(value: string, prefix: string)string

Parameters

value: string

The string to inspect.

prefix: string

The prefix to remove.

Returns

The string without the prefix, or the original string.

text.removeEnd

Removes a suffix when it is present.

If value does not end with suffix, the original string is returned.

text.removeEnd(value: string, suffix: string)string

Parameters

value: string

The string to inspect.

suffix: string

The suffix to remove.

Returns

The string without the suffix, or the original string.

text.trim

Trims characters from one or both sides of a string.

When trimCharacters is omitted, ASCII whitespace characters are removed: space, tab, line feed, carriage return, vertical tab, and form feed. Characters are matched literally and individually rather than as Lua patterns.

text.trim(value: string, side: ("start" | "end" | "both")?, trimCharacters: { string }?)string

Parameters

value: string

The string to trim.

side: ("start" | "end" | "both")?

Which side to trim: "start", "end", or "both".

trimCharacters: { string }?

Characters that should be removed while scanning inward.

Returns

The trimmed string.