Skip to content

stdlib.format

Format: ANSI Escape Codes

Generated from v0.65.7. 12 source files, 240 documented symbols.

ansi.xi

fn ansi_fg(code: Int) -> Str

SGR foreground sequence for a base color code (0-7, clamped): ansi_fg(1) == "\u{001b}[31m" (red). Complexity: O(1).

  • Postcondition: result.byte_at(0) == 27
fn ansi_bg(code: Int) -> Str

SGR background sequence for a base color code (0-7, clamped): ansi_bg(1) == "\u{001b}[41m". Complexity: O(1).

  • Postcondition: result.byte_at(0) == 27
fn ansi_rgb_fg(r: Int, g: Int, b: Int) -> Str

24-bit foreground SGR sequence from RGB channels (0-255 each, clamped). Format: "\u{001b}[38;2;r;g;bm". Complexity: O(1).

  • Postcondition: result.byte_at(0) == 27
fn ansi_rgb_bg(r: Int, g: Int, b: Int) -> Str

24-bit background SGR sequence from RGB channels (0-255 each, clamped). Format: "\u{001b}[48;2;r;g;bm". Complexity: O(1).

  • Postcondition: result.byte_at(0) == 27
fn ansi_256_fg(code: Int) -> Str

256-color foreground SGR sequence for code 0-255 (clamped). Format: "\u{001b}[38;5;Xm". Complexity: O(1).

  • Postcondition: result.byte_at(0) == 27
fn ansi_256_bg(code: Int) -> Str

256-color background SGR sequence for code 0-255 (clamped). Format: "\u{001b}[48;5;Xm". Complexity: O(1).

  • Postcondition: result.byte_at(0) == 27
fn ansi_reset() -> Str

Reset all SGR attributes: "\u{001b}[0m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_bold() -> Str

Enable bold: "\u{001b}[1m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_dim() -> Str

Enable dim intensity: "\u{001b}[2m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_italic() -> Str

Enable italic: "\u{001b}[3m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_underline() -> Str

Enable underline: "\u{001b}[4m".

  • Postcondition: result.byte_at(0) == 27

Enable blink: "\u{001b}[5m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_reverse() -> Str

Enable reverse video: "\u{001b}[7m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_strike() -> Str

Enable strikethrough: "\u{001b}[9m".

  • Postcondition: result.byte_at(0) == 27
fn ansi_cursor_to(row: Int, col: Int) -> Str

Move the cursor to an absolute 1-based (row, column): "\u{001b}[r;cH". Non-positive values clamp to 1.

  • Postcondition: result.byte_at(0) == 27
fn ansi_cursor_up(n: Int) -> Str

Move the cursor up n lines (n clamped >= 0): "\u{001b}[nA".

  • Postcondition: result.byte_at(0) == 27
fn ansi_cursor_down(n: Int) -> Str

Move the cursor down n lines: "\u{001b}[nB".

  • Postcondition: result.byte_at(0) == 27
fn ansi_cursor_right(n: Int) -> Str

Move the cursor right n columns: "\u{001b}[nC".

  • Postcondition: result.byte_at(0) == 27
fn ansi_cursor_left(n: Int) -> Str

Move the cursor left n columns: "\u{001b}[nD".

  • Postcondition: result.byte_at(0) == 27
fn ansi_clear_screen() -> Str

Clear the whole screen and home the cursor: "\u{001b}[2J\u{001b}[H".

  • Postcondition: result.byte_at(0) == 27
fn ansi_clear_line() -> Str

Clear the current line: "\u{001b}[2K".

  • Postcondition: result.byte_at(0) == 27
fn ansi_save_cursor() -> Str

Save the cursor position: "\u{001b}[s".

  • Postcondition: result.byte_at(0) == 27
fn ansi_restore_cursor() -> Str

Restore the saved cursor position: "\u{001b}[u".

  • Postcondition: result.byte_at(0) == 27
fn ansi_hide_cursor() -> Str

Make the cursor invisible: "\u{001b}[?25l".

  • Postcondition: result.byte_at(0) == 27
fn ansi_show_cursor() -> Str

Make the cursor visible: "\u{001b}[?25h".

  • Postcondition: result.byte_at(0) == 27



dump.xi

fn hexdump_line(data: &Vec[UInt8], offset: Int, start: Int, len: Int) -> Str

Formats a single 16-byte hex dump line (same style as xiom.fmt.format_hexdump): 8-digit hex offset, 16 hex bytes grouped 8+8, then the ASCII column. Missing bytes are space-padded. Complexity: O(len).

  • Postcondition: ((len == 0 && offset >= 0 && offset < 100000000) => (result.len() == 14))
fn hexdump(data: &Vec[UInt8]) -> Str

Formats a byte buffer as a classic 16-bytes-per-line hex dump. Each line: 8-digit hex offset, 16 hex bytes grouped 8+8 (lowercase), then the ASCII column (printable characters or '.'). The layout mirrors xiom.fmt.format_hexdump with width 16. Empty input yields "". Complexity: O(n).

  • Postcondition: ((data.len() == 0) => (result.len() == 0)) && ((data.len() > 0) => (result.len() > 0))
fn octal_dump(data: &Vec[UInt8]) -> Str

Formats a byte buffer as an 8-bytes-per-line octal dump. Each line: 8-digit hex offset, 3-digit octal per byte, ASCII column. Empty input yields "". Complexity: O(n).

  • Postcondition: ((data.len() == 0) => (result.len() == 0)) && ((data.len() > 0) => (result.len() > 0))
fn binary_dump(data: &Vec[UInt8]) -> Str

Formats a byte buffer as a 4-bytes-per-line binary dump. Each line: 8-digit hex offset, 8-bit binary per byte, ASCII column. Empty input yields "". Complexity: O(n).

  • Postcondition: ((data.len() == 0) => (result.len() == 0)) && ((data.len() > 0) => (result.len() > 0))



fmt.xi

type Formatter

Accumulates formatted output with width/precision/align options.

Field Type
buf Str
width Int
precision Int
align Int

Derives: Clone

type FmtError

Formatting failure with a message.

Field Type
message Str

Derives: Clone

fn new() -> Formatter

Create an empty formatter.

  • Postcondition: result.buf == ""
  • Postcondition: result.width == 0
  • Postcondition: result.precision == 6

fn write_str(self: Self, s: Str) -> Result[Unit, FmtError]

Append a string rendering.

  • Postcondition: result.is_ok

fn write_int(self: Self, n: Int) -> Result[Unit, FmtError]

Append an integer rendering.

  • Postcondition: result.is_ok

fn write_float(self: Self, f: Float64) -> Result[Unit, FmtError]

Append a float rendering.

  • Postcondition: result.is_ok

fn write_bool(self: Self, b: Bool) -> Result[Unit, FmtError]

Append a bool rendering.

  • Postcondition: result.is_ok

fn finish(self: Self) -> Str

Consume the formatter and return the accumulated text.

  • Postcondition: result == self.buf@pre

fn to_str() -> Str

=== Display implementations for built-in types ===

  • Postcondition: (self == 0) => (result == "0")

fn to_str() -> Str

String rendering of the Float64.

  • Postcondition: (self == 0) => (result == "0")

fn to_str() -> Str

String rendering of the Bool.

  • Postcondition: result == "true" || result == "false"

fn to_str() -> Str

String rendering of the Str (identity).

  • Postcondition: result.len() == self.len()

fn format1[T](fmt: Str, arg: T) -> Str

=== Format functions ===

  • Postcondition: (fmt == "plain") => (result == "plain")

fn format2[T, U](fmt: Str, arg1: T, arg2: U) -> Str

Format with two generic arguments substituted into {} placeholders.

  • Postcondition: (fmt == "b") => (result == "b")

fn format3[T, U, V](fmt: Str, arg1: T, arg2: U, arg3: V) -> Str

Format with three generic arguments substituted into {} placeholders.

  • Postcondition: (fmt == "c") => (result == "c")

fn print(s: Str)

=== Print functions ===

fn println(s: Str)

Write a line to standard output.

fn format_table(headers: &Vec[Str], cells: &Vec[Str], col_count: Int) -> Str

Formats a simple aligned-column table with | separators. O(r * c). No padding -- cells are left-aligned as-is.

  • Postcondition: (col_count <= 0 || headers.len() == 0) => (result.len() == 0)

fn format_columns(items: &Vec[Str], width: Int) -> Str

Arranges items into multiple columns, wrapping at width. Items are placed column-by-column (top-to-bottom then left-to-right). O(n) where n = items.len().

  • Postcondition: (items.len() == 0) => (result.len() == 0)

fn format_wrap(text: Str, width: Int) -> Str

Wraps text at word boundaries to fit within width characters. Words longer than width are placed on their own line. O(n) where n = |text|.

  • Postcondition: (width <= 0 || text.len() == 0) => (result == text)

fn format_indent(text: Str, spaces: Int) -> Str

Adds spaces spaces at the beginning of each line in text. O(n + lines * spaces).

  • Postcondition: (spaces <= 0) => (result == text)

fn format_hexdump(data: &Vec[UInt8], width: Int) -> Str

Formats a byte buffer as a classic hexdump: offset, hex bytes, ASCII preview. width controls bytes per line (default 16). Returns multi-line string. O(n) where n = data.len().

  • Postcondition: (data.len() == 0) => (result.len() == 0)

fn format_pad_number(n: Int, width: Int) -> Str

Zero-pads integer n to width digits. Negative numbers are handled (the sign is not counted in the width). Returns the string representation.

  • Postcondition: (width <= 0 && n == 0) => (result == "0")
  • Postcondition: (width > 0) => (result.len() >= width)

fn format_float_fixed(f: Float64, decimals: Int) -> Str

Formats a float with decimals decimal places, ROUNDED half away from zero (2026-08-11: previously truncated via the old float_to_string, which itself was fptosi-garbage -- see convert.xi; now delegates to the exact scaled-integer formatter).

  • Postcondition: (decimals < 0 && f == 0) => (result == "0")

fn format_bool(b: Bool) -> Str

Converts a boolean to "true" or "false".

  • Postcondition: (b == true) => (result == "true")
  • Postcondition: (b == false) => (result == "false")

fn format_align_left(s: Str, width: Int) -> Str

Left-aligns s within a field of width characters by right-padding with spaces.

  • Postcondition: result.len() >= s.len()

fn format_align_right(s: Str, width: Int) -> Str

Right-aligns s within a field of width characters by left-padding with spaces.

  • Postcondition: result.len() >= s.len()

fn format_join(items: &Vec[Str], sep: Str) -> Str

Joins items into a single string separated by sep. O(n * |sep|) where n = items.len().

  • Postcondition: (items.len() == 0) => (result.len() == 0)

fn format_repeat(s: Str, n: Int) -> Str

Repeats s n times. Delegates to string.str_repeat.

  • Postcondition: (n <= 0) => (result.len() == 0)
  • Postcondition: (n >= 0) => (result.len() == s.len() * n)

fn format_line(prefix: Str, body: Str) -> Str

Formats a line with a prefix and body, separated by ": ". Useful for key-value display: format_line("Name", "Alice") -> "Name: Alice"

  • Postcondition: result.len() == prefix.len() + body.len() + 2

fn sprintf_i(spec: Str, values: &Vec[Int]) -> Result[Str, Str]

printf-style formatting of an Int-only spec. Supports %d/%i/%u/%x/%X/%o/%b with flags/width/precision. Wrong conversion family or missing values -> Err.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_s(spec: Str, values: &Vec[Str]) -> Result[Str, Str]

printf-style formatting of a Str-only spec. Supports %s with width/ precision. Wrong conversion family or missing values -> Err.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_i1(spec: Str, a: Int) -> Result[Str, Str]

sprintf_i with one Int argument: sprintf_i1("%05d", 42) == "00042".

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_i2(spec: Str, a: Int, b: Int) -> Result[Str, Str]

sprintf_i with two Int arguments.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_f1(spec: Str, a: Float64) -> Result[Str, Str]

sprintf_f with one Float64 argument: sprintf_f1("%.2f", 3.14159) == "3.14". Supports %f/%F/%e/%E/%g/%G with flags/width/precision.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_f2(spec: Str, a: Float64, b: Float64) -> Result[Str, Str]

sprintf_f with two Float64 arguments.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_s1(spec: Str, a: Str) -> Result[Str, Str]

sprintf_s with one Str argument: sprintf_s1("%10s", "hi") == " hi".

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

fn sprintf_s2(spec: Str, a: Str, b: Str) -> Result[Str, Str]

sprintf_s with two Str arguments.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

type ScanResult

Captured tokens (parallel arrays: convs 0=int(%d/%i/%u), 1=hex(%x/%X), 2=float(%f/%e/%g), 3=str(%s), 4=char(%c)). Plain struct on purpose: the compiler's generic Result[Vec[struct], _] instantiation collides with Result[Int, _] in mono layout (docs/COMPILER_BUGS.md), so the engine returns a concrete named struct instead.

Field Type
is_ok Bool
convs Vec[Int]
texts Vec[Str]
error Str

fn sscanf(s: Str, spec: Str) -> Result[Vec[Str], Str]

scanf-style scan of s per spec: literal chars match exactly, spec whitespace skips any input whitespace run. Conversions: %d/%i/%u (dec), %x/%X (hex, optional 0x), %f/%e/%g (float, optional exponent), %s (token), %c (exact chars incl. whitespace), width caps, * suppresses, %% literal. Returns the captured token strings in order, Err on any mismatch.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)
  • Postcondition: (s.len() == 0 && spec == "%d") => (result.is_err == true)

fn sscanf_ints(s: Str, spec: Str) -> Result[Vec[Int], Str]

sscanf + typed integer extraction: converts %d/%i/%u (decimal) and %x/%X (hex) tokens to Int with overflow checking. Non-integer conversions in the spec -> Err. The returned Vec is in token order.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)

type FormatFloatScan

Float results of sscanf_floats. Fixed 8 scalar slots instead of a Vec[Float64] (BUG 12: float container element reads broken -- TODO(compiler) restore a Vec-based API once fixed). Specs with more than 8 float conversions -> is_ok = false ("too many float conversions").

Field Type
is_ok Bool
count Int
v0 Float64
v1 Float64
v2 Float64
v3 Float64
v4 Float64
v5 Float64
v6 Float64
v7 Float64
error Str

fn sscanf_floats(s: Str, spec: Str) -> FormatFloatScan

sscanf + typed float extraction: converts %f/%e/%g tokens to Float64 (normalized ".5" -> "0.5" for the builtin parser). Non-float conversions in the spec or more than 8 float conversions -> is_ok = false with error. Values land in v0..v7 in token order; count says how many are valid.

  • Postcondition: (spec.len() == 0) => (result.is_ok == true)


markup.xi

type MarkupNode

An inline markup node. kind: 0 text, 1 bold, 2 italic, 3 code, 4 link, 5 strike.

Field Type
kind Int
text Str
url Str
fn markup_escape(s: Str) -> Str

Escape markup-significant characters with a backslash. Complexity: O(|s|).

  • Postcondition: (s.len() == 0) => (result.len() == 0)
  • Postcondition: result.len() >= s.len()
fn markup_bold(text: Str) -> Str

Wrap text in a bold marker: "text".

  • Postcondition: result.len() == text.len() + 2
fn markup_italic(text: Str) -> Str

Wrap text in an italic marker: "text".

  • Postcondition: result.len() == text.len() + 2
fn markup_code(text: Str) -> Str

Wrap text in a code marker: "text".

  • Postcondition: result.len() == text.len() + 2
fn markup_link(text: Str, url: Str) -> Str

Wrap text in a link marker with a url: "text".

  • Postcondition: result.len() == text.len() + url.len() + 4
fn markup_strike(text: Str) -> Str

Wrap text in a strikethrough marker: "~text~".

  • Postcondition: result.len() == text.len() + 2
fn markup_parse(s: Str) -> Result[Vec[MarkupNode], Str]

Parse a markup string into a node list. Returns Err on unclosed markers. Complexity: O(n), n = string length.

  • Postcondition: (s.len() == 0) => (result.is_ok == true)
  • Postcondition: (s == "*x") => (result.is_err == true)
fn markup_parse_inline(s: Str) -> Vec[MarkupNode]

Parse the first inline span, ignoring trailing content. For this module the whole string is parsed (a trailing run of plain text becomes a text node), matching the documented span semantics for well-formed input.

  • Postcondition: (s.len() == 0) => (result.len() == 0)
fn markup_render(nodes: &Vec[MarkupNode]) -> Str

Render nodes back to the markup syntax (re-escaping text content).

  • Postcondition: (nodes.len() == 0) => (result.len() == 0)
fn markup_render_ansi(nodes: &Vec[MarkupNode]) -> Str

Render nodes with ANSI styling (bold/italic/code/underline/strike).

  • Postcondition: (nodes.len() == 0) => (result.len() == 0)
fn markup_render_html(nodes: &Vec[MarkupNode]) -> Str

Render nodes as HTML (, , , , ).

  • Postcondition: (nodes.len() == 0) => (result.len() == 0)
fn markup_render_plain(nodes: &Vec[MarkupNode]) -> Str

Render nodes as plain text, dropping all styling.

  • Postcondition: (nodes.len() == 0) => (result.len() == 0)
fn markup_strip(s: Str) -> Str

Remove all markup markers from s, returning the plain text. Implemented as a direct scanner (the parse -> node-list -> render pipeline miscompiles for catalog-internal Vec[struct] reads in the current compiler). Unclosed markers are emitted literally.

  • Postcondition: (s.len() == 0) => (result.len() == 0)



number.xi

fn fmt_int_with_separators(n: Int, sep: Str) -> Str

Formats an integer with sep inserted every three digits from the right. The sign is preserved: fmt_int_with_separators(-987654, ",") -> "-987,654". n == 0 -> "0". Complexity: O(digits).

  • Postcondition: (n == 0) => (result == "0")
fn fmt_float_fixed(x: Float64, decimals: Int) -> Str

Formats a float with a fixed number of decimals using integer math. Rounds half away from zero: fmt_float_fixed(3.14159, 2) -> "3.14". Because 2.675 is not exactly representable in binary, its scaled value (267.4999...) rounds to "2.67", not "2.68" -- a documented float-math artifact. Negative values keep their sign. Complexity: O(decimals).

  • Postcondition: ((x == 0 && decimals == 0) => (result == "0")) && ((x == 0 && decimals == 2) => (result == "0.00"))
fn fmt_percent(x: Float64, decimals: Int) -> Str

Formats a fraction (0..1) as a percentage with decimals decimals. fmt_percent(0.125, 1) -> "12.5%". Uses fmt_float_fixed for rounding. Complexity: O(decimals).

  • Postcondition: (x == 0 && decimals == 0) => (result == "0%")
fn fmt_bytes(n: Int) -> Str

Formats a byte count as human-readable text using binary units. Values below 1024 use plain bytes ("512 B"); larger values use one decimal with KiB/MiB/GiB/TiB ("1.5 KiB"). n == 0 -> "0 B". Complexity: O(units).

  • Postcondition: ((n == 0) => (result == "0 B")) && ((n == 1024) => (result == "1.0 KiB")) && ((n == 0 - 512) => (result == "512 B"))
fn fmt_duration_ms(ms: Int) -> Str

Formats a millisecond duration as compact time units, omitting zero units while keeping the largest nonzero component. 0 -> "0ms"; 65000 -> "1m 5s"; 90061000 -> "1d 1h 1m 1s". Complexity: O(1).

  • Postcondition: ((ms == 0) => (result == "0ms")) && ((ms == 65000) => (result == "1m 5s")) && ((ms == 90061000) => (result == "1d 1h 1m 1s")) && ((ms == 0 - 1000) => (result == "-1s"))
fn fmt_ordinal(n: Int) -> Str

Formats an integer with its English ordinal suffix: 1st, 2nd, 3rd, 4th, ..., 11th, 12th, 13th, 21st, 22nd, 23rd, 111th. Complexity: O(1).

  • Postcondition: ((n == 1) => (result == "1st")) && ((n == 2) => (result == "2nd")) && ((n == 3) => (result == "3rd")) && ((n == 11) => (result == "11th")) && ((n == 21) => (result == "21st")) && ((n == 111) => (result == "111th"))



numbering.xi

fn number_to_words(n: Int) -> Str

Spell n in English words using the US short scale (billion = 10^9). "minus" precedes negative values. Complexity: O(log10 n).

  • Postcondition: (n == 0) => (result == "zero")
  • Postcondition: (n == 21) => (result == "twenty-one")
  • Postcondition: (n == -5) => (result == "minus five")
  • Postcondition: (n == 1000000) => (result == "one million")
fn number_to_words_uk(n: Int) -> Str

Spell n in English words using the UK long scale (billion = 10^12, milliard = 10^9). Complexity: O(log10 n).

  • Postcondition: (n == 0) => (result == "zero")
  • Postcondition: (n == 21) => (result == "twenty-one")
  • Postcondition: (n == 1000000000) => (result == "one milliard")
fn number_to_ordinal_words(n: Int) -> Str

Spell n as an English ordinal word ("21" -> "twenty-first").

  • Postcondition: (n == 0) => (result == "zeroth")
  • Postcondition: (n == 1) => (result == "first")
  • Postcondition: (n == 2) => (result == "second")
  • Postcondition: (n == 21) => (result == "twenty-first")
fn number_to_chinese(n: Int) -> Str

Spell n in Chinese numerals (simplified: 一亿零一, 十五, 一百零一).

  • Postcondition: (n == 0) => (result == "零")
  • Postcondition: (n == 15) => (result == "十五")
  • Postcondition: (n == -1) => (result == "负一")
fn number_to_chinese_simplified(n: Int) -> Str

Spell n in simplified Chinese numerals (万/亿).

  • Postcondition: (n == 0) => (result == "零")
  • Postcondition: (n == 15) => (result == "十五")
fn number_to_chinese_traditional(n: Int) -> Str

Spell n in traditional Chinese numerals (萬/億).

  • Postcondition: (n == 0) => (result == "零")
  • Postcondition: (n == 10000) => (result == "一萬")
fn number_to_japanese(n: Int) -> Str

Spell n in Japanese numerals (〇 一 二 三 ... 十 百 千 万 億).

  • Postcondition: (n == 0) => (result == "〇")
  • Postcondition: (n == 15) => (result == "十五")
fn number_to_korean(n: Int) -> Str

Spell n in Sino-Korean numerals (영 일 이 삼 ... 십 백 천 만 억).

  • Postcondition: (n == 0) => (result == "영")
  • Postcondition: (n == 15) => (result == "십오")
fn number_to_indian_words(n: Int) -> Str

Spell n in Indian-system English words (lakh = 10^5, crore = 10^7). Complexity: O(log10 n).

  • Postcondition: (n == 0) => (result == "zero")
  • Postcondition: (n == 21) => (result == "twenty-one")
fn number_to_indian_grouping(n: Int) -> Str

Group n using Indian digit grouping (1234567 -> "12,34,567"). Complexity: O(log10 n).

  • Postcondition: (n == 0) => (result == "0")
  • Postcondition: (n == 1234567) => (result == "12,34,567")
fn money_to_words(amount_cents: Int, currency: Str) -> Str

Spell a money amount in words: amount_cents is the value in the currency's smallest unit (e.g. 12345 cents for $123.45). Known currencies: USD, EUR, GBP, JPY, INR, AUD, CAD; anything else falls back to "unit/cent".

  • Postcondition: (amount_cents == 12345 && currency == "USD") => (result == "one hundred twenty-three dollars and forty-five cents")
  • Postcondition: (amount_cents == 0 && currency == "JPY") => (result == "zero yen")



relative.xi

fn format_relative_future(seconds: Int) -> Str

Format a positive offset as "in N units".

  • Postcondition: ((seconds < 30 && seconds > 0 - 30) => (result == "in a moment"))
fn format_relative_past(seconds: Int) -> Str

Format a negative offset as "N units ago".

  • Postcondition: ((seconds < 30 && seconds > 0 - 30) => (result == "just now"))
fn format_relative_time(seconds: Int) -> Str

Format a signed offset in seconds as a full relative phrase.

  • Postcondition: ((seconds < 30 && seconds > 0 - 30) => (result == "just now"))
fn format_relative_time_short(seconds: Int) -> Str

Format a signed offset using the compact unit form ("5m", "2d", "now").

  • Postcondition: ((seconds < 30 && seconds > 0 - 30) => (result == "now"))
fn format_elapsed(start: Int, end: Int) -> Str

Format the span between two timestamps as elapsed time ("5 minutes").

  • Postcondition: (end == start) => (result == "0 seconds")
fn format_elapsed_ms(ms: Int) -> Str

Format a millisecond span as a compact human duration ("1h 2m 3s").

  • Postcondition: (ms == 0) => (result == "0ms")
fn format_ago(timestamp: Int, now: Int) -> Str

Format how long before now the timestamp lies ("5 minutes ago", or the future form when timestamp is after now).

  • Postcondition: (now == timestamp) => (result == "just now")
fn format_until(timestamp: Int, now: Int) -> Str

Format how long after now the timestamp lies ("in 5 minutes", or the past form when timestamp is before now).

  • Postcondition: (now == timestamp) => (result == "in a moment")
fn format_age(days: Int) -> Str

Format an age in days as the largest whole unit ("400 days", "3 months").

  • Postcondition: (days == 0) => (result == "0 seconds")
fn relative_parts(seconds: Int) -> Vec[(Int, Str)]

Decompose seconds into (magnitude, unit name) pairs from largest to smallest, using only the non-zero parts (e.g. 3661 -> hour 1, minute 1, second 1). The sign is ignored; the magnitude is always non-negative.

  • Postcondition: (seconds == 0) => (result.len() == 1)
fn format_seconds(secs: Int) -> Str

Format seconds as a compact human duration ("1h 2m 3s", "2m 5s", "45s").

  • Postcondition: (secs == 0) => (result == "0s")



table.xi

type Table

A table of headers and row-major string cells with computed column widths.

Field Type
headers Vec[Str]
cells Vec[Str]
row_count Int
col_count Int
fn table_new(headers: &Vec[Str]) -> Table

Create an empty table with the given headers.

  • Postcondition: result.row_count == 0 && result.col_count == headers.len() && result.headers.len() == headers.len() && result.cells.len() == 0
fn table_add_row(t: &mut Table, cells: &Vec[Str])

Append a row; extra cells are truncated, missing cells pad empty.

  • Postcondition: t.row_count == t.row_count@pre + 1
fn table_widths(t: &Table) -> Vec[Int]

The display width of each column (max of header and cells, byte length).

  • Postcondition: result.len() == t.col_count
fn table_rows(t: &Table) -> Int

The number of data rows.

  • Postcondition: result == t.row_count
fn table_columns(t: &Table) -> Int

The number of columns.

  • Postcondition: result == t.col_count
fn table_render(t: &Table) -> Str

Render the table as plain aligned text with left-aligned columns: "| a | b |" rows separated by "|---|" under the header.

  • Postcondition: ((t.col_count == 0 && t.row_count == 0) => (result == " "))
fn table_render_aligned(t: &Table, align: &Vec[Int]) -> Str

Render with per-column alignment (0 left, 1 right, 2 center).

  • Postcondition: ((t.col_count == 0 && t.row_count == 0) => (result == " "))
fn table_render_markdown(t: &Table) -> Str

Render the table as a GitHub-flavored markdown table.

  • Postcondition: ((t.col_count == 0 && t.row_count == 0) => (result == " "))
fn table_render_csv(t: &Table) -> Str

Render the table as comma-separated values (RFC 4180 style quoting).

  • Postcondition: ((t.col_count == 0 && t.row_count == 0) => (result.len() == 0))
fn table_render_html(t: &Table) -> Str

Render the table as an HTML table.

  • Postcondition: result.len() > 0
fn table_sort_by(t: &mut Table, col: Int)

Sort rows in place by a column (stable selection sort by byte order).

  • Postcondition: t.row_count == t.row_count@pre && t.col_count == t.col_count@pre
fn table_set_cell(t: &mut Table, row: Int, col: Int, value: Str)

Replace a single cell value. Out-of-range cells are ignored.

  • Postcondition: t.cells.len() == t.cells.len()@pre



terminal.xi

type Progress

A progress bar over total units with ETA tracking.

Field Type
total Int
done Int
started Int
width Int
fn progress_new(total: Int) -> Progress

Create a progress bar over total units (clamped to >= 0).

  • Postcondition: (total < 0) => (result.total == 0)
  • Postcondition: (total >= 0) => (result.total == total)
  • Postcondition: result.done == 0
  • Postcondition: result.width == 40
fn progress_update(p: &mut Progress, done: Int) -> Unit

Advance the bar to done units (clamped to [0, total]).

  • Postcondition: p.done <= p.total
  • Postcondition: p.total >= 0 => p.done >= 0
fn progress_render(p: &Progress) -> Str

Render the bar to a single line string: "[####----] 50%".

  • Postcondition: result.len() >= 3
fn progress_finish(p: &mut Progress) -> Unit

Finalize the bar: mark it complete (done = total). Rendering after this returns a full bar. No terminal I/O is performed.

  • Postcondition: p.done == p.total
fn progress_percent(p: &Progress) -> Int

Percent complete, 0..100.

  • Postcondition: (p.total <= 0) => (result == 100)
fn progress_eta(p: &Progress) -> Int

Estimated seconds remaining, or -1 when unknown (nothing done yet).

  • Postcondition: result >= -1
  • Postcondition: p.done <= 0 => result == -1
type Spinner

A spinner with a frame set and a current frame index.

Field Type
frames Vec[Str]
index Int
fn spinner_new() -> Spinner

Create a new spinner with the default frame set: | / - .

  • Postcondition: result.index == 0
  • Postcondition: result.frames.len() == 4
fn spinner_tick(sp: &mut Spinner) -> Str

Advance the spinner and return its frame string.

  • Postcondition: sp.index == sp.index@pre + 1
fn spinner_frame(sp: &Spinner) -> Int

Current frame index of the spinner.

  • Postcondition: result == sp.index
fn ansi_reset() -> Str

ANSI reset attribute sequence.

  • Postcondition: result == ""
fn ansi_bold() -> Str

ANSI bold attribute sequence.

  • Postcondition: result == ""
fn ansi_dim() -> Str

ANSI dim attribute sequence.

  • Postcondition: result == ""
fn ansi_italic() -> Str

ANSI italic attribute sequence.

  • Postcondition: result == ""
fn ansi_underline() -> Str

ANSI underline attribute sequence.

  • Postcondition: result == ""

ANSI blink attribute sequence.

  • Postcondition: result == ""
fn ansi_reverse() -> Str

ANSI reverse video attribute sequence.

  • Postcondition: result == ""
fn ansi_strike() -> Str

ANSI strikethrough attribute sequence.

  • Postcondition: result == ""
fn ansi_fg_black() -> Str

ANSI black foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_red() -> Str

ANSI red foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_green() -> Str

ANSI green foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_yellow() -> Str

ANSI yellow foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_blue() -> Str

ANSI blue foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_magenta() -> Str

ANSI magenta foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_cyan() -> Str

ANSI cyan foreground sequence.

  • Postcondition: result == ""
fn ansi_fg_white() -> Str

ANSI white foreground sequence.

  • Postcondition: result == ""
fn ansi_bg_black() -> Str

ANSI black background sequence.

  • Postcondition: result == ""
fn ansi_bg_red() -> Str

ANSI red background sequence.

  • Postcondition: result == ""
fn ansi_bg_green() -> Str

ANSI green background sequence.

  • Postcondition: result == ""
fn ansi_bg_yellow() -> Str

ANSI yellow background sequence.

  • Postcondition: result == ""
fn ansi_bg_blue() -> Str

ANSI blue background sequence.

  • Postcondition: result == ""
fn ansi_bg_magenta() -> Str

ANSI magenta background sequence.

  • Postcondition: result == ""
fn ansi_bg_cyan() -> Str

ANSI cyan background sequence.

  • Postcondition: result == ""
fn ansi_bg_white() -> Str

ANSI white background sequence.

  • Postcondition: result == ""
fn ansi_fg_256(code: Int) -> Str

ANSI 256-color foreground escape for code 0..255 (clamped).

  • Postcondition: code < 0 => result == ""
  • Postcondition: code > 255 => result == ""
fn ansi_bg_256(code: Int) -> Str

ANSI 256-color background escape for code 0..255 (clamped).

  • Postcondition: code < 0 => result == ""
  • Postcondition: code > 255 => result == ""
fn ansi_fg_rgb(r: Int, g: Int, b: Int) -> Str

ANSI 24-bit foreground escape from RGB channels (0-255 each).

  • Postcondition: (r < 0 && g < 0 && b < 0) => result == ""
  • Postcondition: (r > 255 && g > 255 && b > 255) => result == ""
fn ansi_bg_rgb(r: Int, g: Int, b: Int) -> Str

ANSI 24-bit background escape from RGB channels (0-255 each).

  • Postcondition: (r < 0 && g < 0 && b < 0) => result == ""
  • Postcondition: (r > 255 && g > 255 && b > 255) => result == ""
fn ansi_cursor_up(n: Int) -> Str

Move the cursor up n rows (n clamped >= 0).

  • Postcondition: n < 0 => result == ""
fn ansi_cursor_down(n: Int) -> Str

Move the cursor down n rows.

  • Postcondition: n < 0 => result == ""
fn ansi_cursor_forward(n: Int) -> Str

Move the cursor right n columns.

  • Postcondition: n < 0 => result == ""
fn ansi_cursor_back(n: Int) -> Str

Move the cursor left n columns.

  • Postcondition: n < 0 => result == ""
fn ansi_cursor_home() -> Str

Move the cursor to the home position (1, 1).

  • Postcondition: result == ""
fn ansi_cursor_to(row: Int, col: Int) -> Str

Move the cursor to the given 1-based row, col.

  • Postcondition: (row < 1 && col < 1) => result == ""
fn ansi_clear_screen() -> Str

Clear the whole screen and home the cursor.

  • Postcondition: result == ""
fn ansi_clear_line() -> Str

Clear the current line.

  • Postcondition: result == ""
fn ansi_erase_above() -> Str

Erase from the cursor up to the top of the screen.

  • Postcondition: result == ""
fn ansi_erase_below() -> Str

Erase from the cursor down to the bottom of the screen.

  • Postcondition: result == ""
fn ansi_show_cursor() -> Str

Make the cursor visible again.

  • Postcondition: result == "[?25h"
fn ansi_hide_cursor() -> Str

Hide the cursor.

  • Postcondition: result == "[?25l"
fn ansi_save_cursor() -> Str

Save the current cursor position.

  • Postcondition: result == ""
fn ansi_restore_cursor() -> Str

Restore the last saved cursor position.

  • Postcondition: result == ""
fn color_256_to_rgb(code: Int) -> (Int, Int, Int)

Convert an xterm-256 index (0..255) to its RGB triple (r, g, b). The 16 base colors use the standard palette, 16..231 the 6x6x6 cube, and 232..255 the grayscale ramp.

  • Postcondition: result._0 >= 0 && result._0 <= 255
  • Postcondition: result._1 >= 0 && result._1 <= 255
  • Postcondition: result._2 >= 0 && result._2 <= 255
  • Postcondition: code < 0 => result._0 == 0 && result._1 == 0 && result._2 == 0
  • Postcondition: code > 255 => result._0 == 238 && result._1 == 238 && result._2 == 238
fn rgb_to_ansi256(r: Int, g: Int, b: Int) -> Int

Quantize an RGB triple to the nearest xterm-256 index. Uses the 6-level color cube (index 16..231); the grayscale ramp is not considered.

  • Postcondition: result >= 16 && result <= 231



text.xi

fn text_center(s: Str, width: Int) -> Str

Center s in a field of width bytes.

  • Postcondition: result.len() >= s.len()
fn text_left(s: Str, width: Int) -> Str

Left-align s in a field of width bytes.

  • Postcondition: result.len() >= s.len()
fn text_right(s: Str, width: Int) -> Str

Right-align s in a field of width bytes.

  • Postcondition: result.len() >= s.len()
fn text_justify(s: Str, width: Int) -> Str

Justify s to fill width by distributing extra spaces between words. Single-word or already-too-long text is returned unchanged. Complexity: O(|s|).

  • Postcondition: (s.len() == 0) => (result.len() == 0)
fn text_wrap(s: Str, width: Int) -> Vec[Str]

Wrap s into lines no longer than width at word boundaries. Complexity: O(|s|).

  • Postcondition: (s.len() == 0) => (result.len() == 1)
fn text_flow(words: &Vec[Str], width: Int) -> Vec[Str]

Pack words greedily into lines of at most width bytes. The input Vec is read directly; callers should prefer text_wrap (string-based) where the input is already a string.

  • Postcondition: (words.len() == 0) => (result.len() == 1)
fn text_indent(s: Str, n: Int) -> Str

Prefix every line of s with n spaces.

  • Postcondition: (n <= 0) => (result == s)
  • Postcondition: (n > 0) => (result.len() >= s.len())
fn text_hanging_indent(s: Str, n: Int) -> Str

Indent every line except the first by n spaces.

  • Postcondition: (n <= 0) => (result == s)
  • Postcondition: (n > 0) => (result.len() >= s.len())
fn text_columns(items: &Vec[Str], cols: Int) -> Vec[Str]

Lay items out in cols columns, row-major, padded to the widest item.

  • Postcondition: (items.len() == 0) => (result.len() == 0)
  • Postcondition: (items.len() > 0 && cols >= 1) => (result.len() == (items.len() + cols - 1) / cols)
  • Postcondition: (items.len() > 0 && cols < 1) => (result.len() == items.len())
fn text_ellipsis(s: Str, max_len: Int) -> Str

Truncate s to max_len bytes with a trailing "..." (at least 3 bytes).

  • Postcondition: (max_len >= 3 && s.len() <= max_len) => (result == s)
  • Postcondition: (max_len >= 3 && s.len() > max_len) => (result.len() == max_len)
fn text_overline(s: Str) -> Str

Apply an overline decoration: a dash line above the text.

  • Postcondition: result.len() == 2 * s.len() + 1
fn text_underline(s: Str) -> Str

Apply an underline decoration: a dash line below the text.

  • Postcondition: result.len() == 2 * s.len() + 1
fn text_strikethrough(s: Str) -> Str

Apply a strikethrough decoration: each character followed by the combining long stroke overlay (U+0336).

  • Postcondition: result.len() == 3 * s.len()
fn text_quote(s: Str) -> Str

Wrap s in quotation marks.

  • Postcondition: result.len() == s.len() + 2
fn text_blockquote(lines: &Vec[Str]) -> Str

Join lines into a blockquote, prefixing each with "> ".

  • Postcondition: (lines.len() == 0) => (result.len() == 0)
  • Postcondition: (lines.len() > 0) => (result.len() >= 2 * lines.len())
fn text_paragraph(s: Str, width: Int) -> Str

Wrap s into a single justified paragraph of width columns.

  • Postcondition: (s.len() == 0) => (result.len() == 0)
fn text_reflow(s: Str, width: Int) -> Str

Reflow s to width: words are repacked into lines of at most width.

  • Postcondition: (s.len() == 0) => (result.len() == 0)
fn text_measure(s: Str) -> Int

The display width of s: ASCII bytes count 1, 3-byte (CJK) characters count 2. Complexity: O(|s|).

  • Postcondition: (s.len() == 0) => (result == 0)
  • Postcondition: result <= s.len()



textual.xi

fn box_around(lines: &Vec[Str], width: Int) -> Str

Wrap lines in a plain ASCII box of the given width.

  • Postcondition: (lines.len() == 0 && width >= 2) => (result.len() == 2 * width + 1)
fn box_rounded(lines: &Vec[Str], width: Int) -> Str

Wrap lines in a rounded-corner box of the given width.

  • Postcondition: (lines.len() == 0 && width >= 2) => (result.len() == 6 * width + 1)
fn box_double(lines: &Vec[Str], width: Int) -> Str

Wrap lines in a double-line box of the given width.

  • Postcondition: (lines.len() == 0 && width >= 2) => (result.len() == 6 * width + 1)
fn border_top(width: Int, style: Int) -> Str

Render a top border line; style selects the character set (0 plain, 1 rounded, 2 double).

  • Postcondition: (width >= 2 && style != 1 && style != 2) => (result.len() == width)
  • Postcondition: (width >= 2 && style == 1) => (result.len() == 3 * width)
  • Postcondition: (width >= 2 && style == 2) => (result.len() == 3 * width)
fn border_bottom(width: Int, style: Int) -> Str

Render a bottom border line; style selects the character set.

  • Postcondition: (width >= 2 && style != 1 && style != 2) => (result.len() == width)
  • Postcondition: (width >= 2 && style == 1) => (result.len() == 3 * width)
  • Postcondition: (width >= 2 && style == 2) => (result.len() == 3 * width)
fn separator_line(ch: Char, width: Int) -> Str

Repeat ch width times as a horizontal separator.

  • Postcondition: (ch == '=' && width >= 0) => (result.len() == width)
  • Postcondition: (width <= 0) => (result.len() == 0)
fn separator_double(width: Int) -> Str

Render a double-line horizontal separator.

  • Postcondition: (width >= 0) => (result.len() == 3 * width)
  • Postcondition: (width <= 0) => (result.len() == 0)
fn separator_dashed(width: Int) -> Str

Render a dashed horizontal separator.

  • Postcondition: (width >= 0) => (result.len() == width)
  • Postcondition: (width <= 0) => (result.len() == 0)
fn header_block(title: Str, width: Int) -> Str

Render a multi-line block header with the title centered inside a box.

  • Postcondition: (width >= 2) => (result.len() == 3 * width + 2)
fn header_bar(title: Str, width: Int) -> Str

Render a one-line bar header: a horizontal rule above the centered title.

  • Postcondition: (title.len() <= width && width >= 0) => (result.len() == 2 * width + 1)

Render a multi-line footer block with the text centered inside a box.

  • Postcondition: (width >= 2) => (result.len() == 3 * width + 2)
fn title_center(title: Str, width: Int) -> Str

Center the title within width columns.

  • Postcondition: result.len() >= title.len()
fn title_overline(title: Str, width: Int) -> Str

Render the title with an overline and underline.

  • Postcondition: (title.len() <= width && width >= 0) => (result.len() == 3 * width + 2)
fn title_underline(title: Str, width: Int) -> Str

Render the title with an underline.

  • Postcondition: (title.len() <= width && width >= 0) => (result.len() == 2 * width + 1)
fn section_header(title: Str, width: Int) -> Str

Render a section header with rule lines above and below.

  • Postcondition: (title.len() <= width && width >= 0) => (result.len() == 3 * width + 2)
fn section_number(n: Int, title: Str) -> Str

Render a numbered section heading such as "3. title".

  • Postcondition: (n == 0) => (result.len() == title.len() + 3)
fn bullet_list(items: &Vec[Str], bullet: Str) -> Str

Render each item prefixed by the bullet marker.

  • Postcondition: (items.len() == 0) => (result.len() == 0)
fn numbered_list(items: &Vec[Str]) -> Str

Render each item prefixed by its 1-based number.

  • Postcondition: (items.len() == 0) => (result.len() == 0)
fn definition_list(terms: &Vec[Str], definitions: &Vec[Str]) -> Str

Render term/definition pairs, one per line.

  • Postcondition: (terms.len() == 0 || definitions.len() == 0) => (result.len() == 0)
fn toc(headings: &Vec[Str], pages: &Vec[Int]) -> Str

Render a table of contents with dot leaders and page numbers. Each line: heading, dots to fill to width, then the page number.

  • Postcondition: (headings.len() == 0 || pages.len() == 0) => (result.len() == 0)
fn toc_indent(level: Int) -> Str

Return the indentation prefix for a TOC entry at the given level (two spaces per level).

  • Postcondition: (level <= 0) => (result.len() == 0)
  • Postcondition: (level > 0) => (result.len() == 2 * level)
fn text_wrap_center(s: Str, width: Int) -> Str

Wrap s to width columns and center each line.

  • Postcondition: (s.len() == 0 && width >= 0) => (result.len() == width)
fn text_justify(s: Str, width: Int) -> Str

Wrap s to width columns with justified alignment.

  • Postcondition: (s.len() == 0) => (result.len() == 0)
fn text_columns(items: &Vec[Str], cols: Int) -> Str

Lay out items in the given number of equal columns (row-major), each line joined with two spaces between padded columns.

  • Postcondition: (items.len() == 0) => (result.len() == 0)



units.xi

fn format_bytes(bytes: Int) -> Str

Format a byte count with a decimal unit suffix (B, KB, MB, GB, TB).

  • Postcondition: (bytes == 0) => (result == "0 B")
  • Postcondition: (bytes == 1500) => (result == "1.5 KB")
  • Postcondition: (bytes == -1000) => (result == "1.0 KB")
fn format_bytes_binary(bytes: Int) -> Str

Format a byte count with a binary unit suffix (B, KiB, MiB, GiB, TiB).

  • Postcondition: (bytes == 0) => (result == "0 B")
  • Postcondition: (bytes == 1024) => (result == "1.0 KiB")
fn format_bits(bits: Int) -> Str

Format a bit count with a decimal unit suffix (b, Kb, Mb, Gb, Tb).

  • Postcondition: (bits == 1500) => (result == "1.5 Kb")
fn format_percent(f: Float64, decimals: Int) -> Str

Format a fraction in [0,1] as a percentage with decimals places.

  • Postcondition: (f == 0.5 && decimals == 1) => (result == "50.0%")
  • Postcondition: (f == 0.5 && decimals == -3) => (result == "50%")
fn format_percent_sign(f: Float64) -> Str

Format a percentage with a percent sign and no decimals.

  • Postcondition: (f == 0.25) => (result == "25%")
fn format_ratio(num: Int, den: Int) -> Str

Format num/den as a ratio, handling zero denominators ("inf", "NaN", "-inf").

  • Postcondition: (num == 1 && den == 0) => (result == "inf")
  • Postcondition: (num == 0 && den == 0) => (result == "NaN")
  • Postcondition: (num == -1 && den == 0) => (result == "-inf")
  • Postcondition: (num == 3 && den == 4) => (result == "3/4")
fn format_scientific(f: Float64, prec: Int) -> Str

Scientific notation with the given precision ("1.23e+04").

  • Postcondition: (f == 1.5 && prec == 1) => (result == "1.5e+00")
  • Postcondition: (f == 0 && prec == 2) => (result == "0.00")
fn format_engineering(f: Float64) -> Str

Engineering notation: exponent is a multiple of three, mantissa has 2 decimals ("1.23e+03").

  • Postcondition: (f == 0) => (result == "0.00e+00")
  • Postcondition: (f == 1500) => (result == "1.50e+03")
  • Postcondition: (f == -1500) => (result == "-1.50e+03")
fn format_si(f: Float64, unit: Str) -> Str

Value with an SI prefix (k, M, G, T; m, u, n) and unit.

  • Postcondition: (f == 1500 && unit == "Hz") => (result == "1.5 kHz")
  • Postcondition: (f == 0.5 && unit == "s") => (result == "500.0 ms")
fn format_binary_prefix(f: Float64, unit: Str) -> Str

Value with a binary prefix (Ki, Mi, Gi, Ti) and unit.

  • Postcondition: (f == 2048 && unit == "B") => (result == "2.0 KiB")
fn format_temperature_celsius(c: Float64) -> Str

Degrees Celsius with the degree sign and C suffix ("21.5degC").

  • Postcondition: (c == 21.5) => (result == "21.5°C")
fn format_temperature_fahrenheit(f: Float64) -> Str

Degrees Fahrenheit with the degree sign and F suffix ("72.0degF").

  • Postcondition: (f == 72) => (result == "72.0°F")
fn format_currency(amount_cents: Int, currency: Str) -> Str

Integer cents as a localized currency string ("$1,234.56"). JPY drops the decimals. Negative amounts get a leading minus sign.

  • Postcondition: (amount_cents == 123456 && currency == "USD") => (result == "$1,234.56")
  • Postcondition: (amount_cents == -123456 && currency == "USD") => (result == "-$1,234.56")
  • Postcondition: (amount_cents == 100 && currency == "JPY") => (result == "¥1")
fn format_seconds(secs: Int) -> Str

Seconds as a compact human duration ("1h 2m 3s", "2m 5s", "45s").

  • Postcondition: (secs == 0) => (result == "0s")
  • Postcondition: (secs == 3661) => (result == "1h 1m 1s")
  • Postcondition: (secs == -61) => (result == "1m 1s")
fn format_ms(ms: Int) -> Str

Milliseconds as a compact human duration ("1h 2m 3s 500ms", "500ms").

  • Postcondition: (ms == 500) => (result == "500ms")
  • Postcondition: (ms == 1500) => (result == "1s 500ms")
  • Postcondition: (ms == 1000) => (result == "1s")
fn format_hertz(hz: Float64) -> Str

Frequency with a unit suffix (Hz, kHz, MHz, GHz).

  • Postcondition: (hz == 999) => (result == "999.0 Hz")
  • Postcondition: (hz == 1500) => (result == "1.5 kHz")
  • Postcondition: (hz == 1500000000) => (result == "1.5 GHz")