etui/text

Types

pub type Alignment {
  Left
  Center
  Right
}

Constructors

  • Left
  • Center
  • Right

Values

pub fn align(
  s: String,
  width: Int,
  alignment: Alignment,
) -> String

Align left/center/right within width cells. Cell-aware.

pub fn cell_width(s: String) -> Int

Cell width of a string (sum of grapheme widths).

pub fn codepoint_cell_width(cp: Int) -> Int

Cell width of a single Unicode codepoint. Returns 0 for control / combining / zero-width, 2 for wide (CJK / emoji / fullwidth), 1 otherwise.

pub fn drop_graphemes(s: String, n: Int) -> String

Return s without its first n graphemes.

Not spelled string.drop_start: on the JavaScript target that function measures the dropped prefix in UTF-8 bytes and then slices the string with that count, while String.slice counts UTF-16 units. The two agree on ASCII and disagree everywhere else — box drawing, CJK, emoji — where the index lands short of or past the end and the wrong remainder comes back (observed with gleam_stdlib 1.0.0). Graphemes in, graphemes out, on every target.

pub fn expand_tabs(s: String, tab_width: Int) -> String

Expand tab characters to spaces, advancing to the next multiple of tab_width cells. Newlines reset the column counter.

text.expand_tabs("a\tb", 4)  // "a   b"
pub fn grapheme_cell_width(g: String) -> Int

Cell width of a single grapheme cluster. Uses the first codepoint’s East Asian Width / emoji classification. Subsequent codepoints in a grapheme (combining, ZWJ, variation selectors) contribute 0, so the first determines the visible cell count.

pub fn graphemes(s: String) -> List(String)

Split a string into grapheme clusters (UAX #29, via Erlang Unicode).

Each element is one user-perceived character: a base letter, a ZWJ sequence, a flag pair, an emoji with modifiers, etc.

graphemes("café") // ["c", "a", "f", "é"]
graphemes("👨‍👩‍👧‍👦") // ["👨‍👩‍👧‍👦"], one cluster
pub fn normalise_newlines(s: String) -> String

Normalise \r\n and lone \r to \n.

No string.contains(s, "\r") fast path: \r\n is a single grapheme cluster, so contains reports False for a \r that is followed by \n, which is exactly the case this needs to catch.

pub fn pad_left(s: String, width: Int) -> String

Pad left with spaces to reach width cells. Cell-aware.

pub fn pad_right(s: String, width: Int) -> String

Pad right with spaces to reach width cells. Cell-aware.

pub fn strip_ansi(s: String) -> String

Strip ANSI escape sequences. Handles CSI (\e[…<final>) and OSC (\e]…ST/\e]…BEL) sequences.

pub fn truncate(
  s: String,
  max_width: Int,
  ellipsis: String,
) -> String

Truncate to max_width cells. Appends ellipsis only if truncation occurs. The ellipsis itself counts toward the budget.

pub fn wrap(s: String, max_width: Int) -> List(String)

Word-wrap to max_width cells.

Line endings are normalised first: \r\n and lone \r both become \n. A raw \r left in the output would occupy zero cells and desynchronise every position after it.

Tabs are expanded to spaces at 8-column tab stops before wrapping, so a tab never reaches the buffer (control characters are dropped there).

Returns a list of lines, each at most max_width cells wide.

✨ Search Document