#!/usr/bin/env dub
/+ dub.sdl:
name "table"
dependency "sparkles:core-cli" path="../../.."
targetPath "build"
// Optimised, assertions live, `debug {}` blocks out — the build every nix
// artifact uses. Neither `debug` (which compiles those blocks in) nor
// `release` (which deletes assert *expressions*, side effects included).
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
+/
// A gallery of every `drawTable` feature: spans, sparse placement, per-column
// horizontal & vertical alignment, glyph presets & custom glyphs, separator
// toggles, width caps & wrapping, and the `validateTable` error posture.
//
// Every section deliberately mixes ANSI-styled text (`styledText`), wide/CJK
// glyphs, and emoji + combining marks, so each feature simultaneously proves it
// measures content in *terminal cells* (via `sparkles.base.text`) rather than
// bytes — a misaligned column would be immediately visible.
import (package) sparklessparkles.(package) sparkles.uiui.(package) sparkles.ui.componentscomponents.(module) sparkles.ui.components.demoDemo runner utilities for showcasing UI components.
Provides a structured way to display multiple sections with headers,
useful for examples and demonstrations.
demo : (struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section, (alias) table.runDemo = void sparkles.ui.components.demo.runDemo(string header, sparkles.ui.components.demo.Section[] content, sparkles.ui.components.demo.DemoProps props = DemoProps(67LU, "Demo Complete")) @safeRuns a demo by printing a header banner, sections, and closing banner.
Example
runDemo(
header: "My Demo",
content: [
Section(header: "First", content: "Some content here"),
Section(header: "Second", content: "More content"),
],
);
runDemo;
import (package) sparklessparkles.(package) sparkles.uiui.(package) sparkles.ui.componentscomponents.(module) sparkles.ui.components.tableThe span-capable table: pure model resolution in
sparkles.ui.components.table.grid, the content-agnostic layout core
(configuration, width/height solving, junction glyphs, line ordering) in
sparkles.ui.components.table.layout, and the string view in
sparkles.ui.components.table.render, re-exported here under the historical
module name. Nothing else lives in this file — the test runner does not
discover unittests in package.d modules.
The widget view (sparkles.ui.components.table.widgets) is deliberately
not re-exported: it imports the whole toolkit — canvas, chrome, state,
widget, wrap — where the three modules above reach no further than
sparkles:base. Re-exporting it would put that closure on every consumer of
drawTable, including the wasm playground, which compiles a hand-listed set
of source directories and fails outright when the closure widens. Import it by
its own module path where the widget view is actually wanted.
table :
(alias) table.drawTable = string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable, (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell, (struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps, (struct) sparkles.ui.components.table.layout.TableGlyphsThe configurable box-drawing glyph set. Defaults are the rounded frame plus the
square interior corners spans create; every field is a caller-overridable dchar.
TableGlyphs, (enum) sparkles.ui.components.table.grid.VAlignVertical alignment of a cell's content within its (possibly multi-line or
rowspan) height. inherit defers to the column/table default. (Model-side
so per-cell overrides can carry it; the renderer applies it.)
VAlign, (alias thread local global) table.stylePresets = sparkles.ui.components.table.layout.TableGlyphs[string] sparkles.ui.components.table.layout.stylePresetsNamed glyph presets, selectable as TableProps(glyphs: stylePresets["ascii"]).
Seeded from presetGlyphs with rounded (the default, == TableGlyphs.init),
square, ascii, double, and heavy; callers may register or override their
own entries. Thread local (each thread gets the built-ins), so reads stay @safe.
Prefer presetGlyphs(name) where a pure lookup that needs no module ctor helps
(e.g. a wasm build).
stylePresets,
(alias template) table.validateTable = sparkles.ui.components.table.grid.validateTable(T)(in T[] cells) if (is(T == Cell[]) || is(T == Placement))Validate a table's cell placement, returning the first table-model error (overlap
or an over-long rowspan) or true when the table is well-formed. drawTable
renders either way; call this first when a malformed table should be rejected.
Works with the dense Cell[][] or sparse Placement[] form.
validateTable, (struct) sparkles.ui.components.table.grid.TableErrorA table-model error. drawTable renders a malformed table deterministically anyway
(first-writer-wins on overlap, rowspans clamped); validateTable surfaces these for
callers that want to reject one. row/col locate the offending slot or anchor.
TableError;
import (package) sparklessparkles.(package) sparkles.basebase.(module) sparkles.base.styled_templateStyle template processing for IES (Interpolated Expression Sequences).
Provides a template syntax for applying terminal styles to IES strings:
import sparkles.base.styled_template;
int cpu = 75;
styledWriteln(i"CPU: {red $(cpu)%} Status: {green OK}");
Supported syntax:
{red text} — Apply single style
{bold.red text} — Chain multiple styles
{bold outer {red nested}} — Nested blocks (inner inherits outer)
{red text {~red normal}} — Negation with ~ removes a style
#{ — Escaped literal {
#} — Escaped literal }
styled_template : (alias template) table.styledText = sparkles.base.styled_template.styledText(Args...)(ColorDepth depth, InterpolationHeader header, Args args, InterpolationFooter footer)Returns styled IES as a string; depth folds colors to the terminal's tier.
styledText;
import (package) sparklessparkles.(package) sparkles.basebase.(package) sparkles.base.texttext.(module) sparkles.base.text.widthDisplay (terminal cell) width of code points and grapheme clusters.
Width follows the kitty Text Sizing Protocol
(the modern terminal consensus; see docs/specs/base/text/), not legacy
wcwidth. codepointWidth assigns, in decreasing priority: regional
indicators 2 (EAW marks them neutral, but a flag half is 2); noncharacters and
controls 0; all Marks (Mn | Mc | Me) and Cf 0; East-Asian Wide/Fullwidth
(UAX #11) 2 (this also covers emoji-presentation bases and skin-tone
modifiers); everything else (incl. ambiguous) 1.
The crucial rule: codepointWidth is the width of a code point in isolation
and must NOT be summed across a cluster. A grapheme cluster occupies one cell
whose width is that of its leading code point, adjusted only by the UTS #51
variation selectors (VS16 promotes an emoji base to 2, VS15 demotes it to 1);
combining members never add width. So a flag (two regional indicators), a ZWJ
sequence, or base+VS16 each occupy one cell. Use graphemeClusterWidth (or
visibleWidth, in sparkles.base.text.grapheme) for strings.
The East-Asian-Width and emoji-VS-base tables live in the generated
sparkles.base.text.unicode_tables; the zero-width set is built from
std.uni's Mn | Mc | Me | Cf plus the few conjoining ranges Phobos's
categories miss. Pinned to Unicode 17.0 (see the generator).
width : (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align;
void void D main()main()
{
// Shared samples reused across the preset and toggle galleries.
(alias) object.string = stringstring[][] (local variable) string[][] samplesample = [
[string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Node}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Node}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold Node}"i"{bold Node}"), string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold \xe5\x9c\xb0\xe5\x9f\x9f}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold \xe5\x9c\xb0\xe5\x9f\x9f}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold \xe5\x9c\xb0\xe5\x9f\x9f}"i"{bold 地域}"), string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Status}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Status}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold Status}"i"{bold Status}")],
["api", "日本 🇯🇵", string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}"i"{green ✅ up}")],
["web", "eu-west", string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}"i"{yellow ⚠ warn}")],
];
(alias) object.string = stringstring[][] (local variable) string[][] toggleSampletoggleSample = [
["a", "日本"],
["b", "🚀"],
["c", "café"],
];
// Preset helper: render `sample` under a named glyph set from `stylePresets`.
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section sparkles.ui.components.demo.Section table.main.preset(string name) @systempreset((alias) object.string = stringstring (parameter) string namename) => (struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: `Preset: "` ~ (parameter) string namename ~ `"`,
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] samplesample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(glyphs: (local variable) sparkles.ui.components.table.layout.TableGlyphs* __aaget507stylePresets[(parameter) string namename])),
);
// A deliberately malformed layout for the validation section: cell B lands on
// a slot already covered by A's colspan.
(struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement[] (local variable) sparkles.ui.components.table.grid.Placement[] overlappingoverlapping = [
(struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement(0, 0, string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold A}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold A}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold A}"i"{bold A}"), colSpan: 2),
(struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement(0, 1, string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{red B}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{red B}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{red B}"i"{red B}")), // overlaps A's second slot
];
auto (local variable) expected.Expected!(bool, TableError, Abort) validationvalidation = expected.Expected!(bool, TableError, Abort) sparkles.ui.components.table.grid.validateTable!(sparkles.ui.components.table.grid.Placement)(in sparkles.ui.components.table.grid.Placement[] cells) pure nothrow @safeValidate a table's cell placement, returning the first table-model error (overlap
or an over-long rowspan) or true when the table is well-formed. drawTable
renders either way; call this first when a malformed table should be rejected.
Works with the dense Cell[][] or sparse Placement[] form.
validateTable((local variable) sparkles.ui.components.table.grid.Placement[] overlappingoverlapping);
const (local variable) const(string) validationNotevalidationNote = (local variable) expected.Expected!(bool, TableError, Abort) validationvalidation.bool expected.Expected!(bool, sparkles.ui.components.table.grid.TableError, expected.Abort).hasError!()() const pure nothrow @nogc @property @safeChecks if Expected has error
hasError
? "⚠ validateTable: " ~ (local variable) expected.Expected!(bool, TableError, Abort) validationvalidation.inout(sparkles.ui.components.table.grid.TableError) expected.Expected!(bool, sparkles.ui.components.table.grid.TableError, expected.Abort).error() inout nothrow @nogc @property ref @safeReturns the error value. May only be called when hasValue returns false.
If there is no error value, it calls hook's onAccessEmptyError.
It returns E.init when hook doesn't provide onAccessEmptyError.
error.(field) string sparkles.ui.components.table.grid.TableError.messagemessage
: "✓ validateTable: no model errors";
void sparkles.ui.components.demo.runDemo(string header, sparkles.ui.components.demo.Section[] content, sparkles.ui.components.demo.DemoProps props = DemoProps(67LU, "Demo Complete")) @safeRuns a demo by printing a header banner, sections, and closing banner.
Example
runDemo(
header: "My Demo",
content: [
Section(header: "First", content: "Some content here"),
Section(header: "Second", content: "More content"),
],
);
Examples
Section initialization
const section = Section(header: "Title", content: "Body text");
assert(section.header == "Title");
assert(section.content == "Body text");
DemoProps defaults
const props = DemoProps.init;
assert(props.width == 67);
assert(props.endTitle == "Demo Complete");
runDemo(
header: "drawTable Demo — Every Feature",
content: [
//
// 1. Basics — backward-compatible string[][]
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Basic table (plain string[][], byte-identical baseline)",
content: [
["Service", "Region", "Status"],
["api", "us-east", "up"],
["web", "eu-west", "up"],
["db", "ap-south", "down"],
].string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable,
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Styled + i18n content (ANSI SGR, CJK, emoji, flags)",
content: [
[string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Service}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Service}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold Service}"i"{bold Service}"), string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold \xe5\x9c\xb0\xe5\x9f\x9f}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold \xe5\x9c\xb0\xe5\x9f\x9f}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold \xe5\x9c\xb0\xe5\x9f\x9f}"i"{bold 地域}"), string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Status}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Status}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold Status}"i"{bold Status}")],
["api 🚀", "us-east", string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}"i"{green ✅ up}")],
["web", "日本 🇯🇵", string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}"i"{yellow ⚠ warn}")],
["db", "eu-west", string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{red \xe2\x9c\x97 down}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{red \xe2\x9c\x97 down}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{red \xe2\x9c\x97 down}"i"{red ✗ down}")],
].string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable,
),
//
// 2. Column spans
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Column span (colSpan banner; right-aligned numeric columns)",
content: string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Cell[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a dense Cell[][] (cells may carry colSpan/rowSpan) as a boxed table.
Covered slots are omitted from the following cells (rows may be ragged); the
placement cursor recovers their positions. Malformed tables (overlap, over-long
rowspans) still render deterministically — use validateTable to detect them.
See Cell.
drawTable([
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold.underline \xe5\x9b\x9b\xe5\x8d\x8a\xe6\x9c\x9f\xe5\xa3\xb2\xe4\xb8\x8a (Quarterly Sales)}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold.underline \xe5\x9b\x9b\xe5\x8d\x8a\xe6\x9c\x9f\xe5\xa3\xb2\xe4\xb8\x8a (Quarterly Sales)}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold.underline \xe5\x9b\x9b\xe5\x8d\x8a\xe6\x9c\x9f\xe5\xa3\xb2\xe4\xb8\x8a (Quarterly Sales)}"i"{bold.underline 四半期売上 (Quarterly Sales)}"), colSpan: 3)],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("Region"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("Q1"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("Q2")],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("North 🌎"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("1200"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("1350")],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("日本"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("980"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("1100")],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnAligns: [(enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.left = 1left, (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right, (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right])),
),
//
// 3. Row spans (with row separators)
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Row span (rowSpan label + rowSeparators → rule breaks, ┌┐└┘ corners)",
content: string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Cell[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a dense Cell[][] (cells may carry colSpan/rowSpan) as a boxed table.
Covered slots are omitted from the following cells (rows may be ragged); the
placement cursor recovers their positions. Malformed tables (overlap, over-long
rowspans) still render deterministically — use validateTable to detect them.
See Cell.
drawTable([
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("地域\nAsia", rowSpan: 2), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("Tokyo"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85 up}"i"{green ✅ up}"))],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("Osaka"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{yellow \xe2\x9a\xa0 warn}"i"{yellow ⚠ warn}"))],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(rowSeparators: true)),
),
//
// 4. Row × column block span
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Block span (colSpan: 2, rowSpan: 2)",
content: string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Cell[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a dense Cell[][] (cells may carry colSpan/rowSpan) as a boxed table.
Covered slots are omitted from the following cells (rows may be ragged); the
placement cursor recovers their positions. Malformed tables (overlap, over-long
rowspans) still render deterministically — use validateTable to detect them.
See Cell.
drawTable([
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold.inverse CORE}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold.inverse CORE}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold.inverse CORE}"i"{bold.inverse CORE}"), colSpan: 2, rowSpan: 2), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("edge-1")],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("edge-2")],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("a"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("b"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("c 🚀")],
]),
),
//
// 5. Sparse Placement[] (order-independent)
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Sparse Placement[] (out-of-order; uncovered slots blank)",
content: string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Placement[] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a sparse Placement[] (order-independent cells naming their own
(row, col) and extent) as a boxed table. Lowers to the same slot grid as the
dense forms, so it renders identically. See Placement.
drawTable([
(struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement(2, 2, string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{cyan cells}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{cyan cells}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{cyan cells}"i"{cyan cells}")),
(struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement(0, 0, "diagonal 🚀"),
(struct) sparkles.ui.components.table.grid.PlacementA cell for the sparse authoring form ``Placement[]: it names its own (row, col)
and extent, so placements are order-independent and never need filler for the gaps
(uncovered slots become implicit blanks). Equivalent in power to Cell[][].
Placement(1, 1, "日本語"),
]),
),
//
// 6. Horizontal alignment
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Per-column horizontal alignment (left / center / right)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["left", "center", "right"],
["a", string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x85}"i"{green ✅}"), "1"],
["日本語", "mid", "4200"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnAligns: [(enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.left = 1left, (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.center = 2center, (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right])),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "defaultAlign: right, with a single Align.left override on col 0",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["metric", "v1", "v2"],
["cpu", "45", "80"],
["mem 💾", "1200", "980"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(defaultAlign: (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right, columnAligns: [(enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.left = 1left])),
),
//
// 7. Vertical alignment
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Per-column vertical alignment (top / middle / bottom in a tall row)",
content: string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Cell[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a dense Cell[][] (cells may carry colSpan/rowSpan) as a boxed table.
Covered slots are omitted from the following cells (rows may be ragged); the
placement cursor recovers their positions. Malformed tables (overlap, over-long
rowspans) still render deterministically — use validateTable to detect them.
See Cell.
drawTable([
[
(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("line 1\nline 2\nline 3\nline 4"),
(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x96\xb2 top}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x96\xb2 top}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{green \xe2\x96\xb2 top}"i"{green ▲ top}")),
(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{yellow \xe2\x97\x8f middle}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{yellow \xe2\x97\x8f middle}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{yellow \xe2\x97\x8f middle}"i"{yellow ● middle}")),
(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell(string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{red \xe2\x96\xbc bottom}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{red \xe2\x96\xbc bottom}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{red \xe2\x96\xbc bottom}"i"{red ▼ bottom}")),
],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnVAligns: [(enum) sparkles.ui.components.table.grid.VAlignVertical alignment of a cell's content within its (possibly multi-line or
rowspan) height. inherit defers to the column/table default. (Model-side
so per-cell overrides can carry it; the renderer applies it.)
VAlign.(enum value) sparkles.ui.components.table.grid.VAlign.top = 1top, (enum) sparkles.ui.components.table.grid.VAlignVertical alignment of a cell's content within its (possibly multi-line or
rowspan) height. inherit defers to the column/table default. (Model-side
so per-cell overrides can carry it; the renderer applies it.)
VAlign.(enum value) sparkles.ui.components.table.grid.VAlign.top = 1top, (enum) sparkles.ui.components.table.grid.VAlignVertical alignment of a cell's content within its (possibly multi-line or
rowspan) height. inherit defers to the column/table default. (Model-side
so per-cell overrides can carry it; the renderer applies it.)
VAlign.(enum value) sparkles.ui.components.table.grid.VAlign.middle = 2middle, (enum) sparkles.ui.components.table.grid.VAlignVertical alignment of a cell's content within its (possibly multi-line or
rowspan) height. inherit defers to the column/table default. (Model-side
so per-cell overrides can carry it; the renderer applies it.)
VAlign.(enum value) sparkles.ui.components.table.grid.VAlign.bottom = 3bottom])),
),
//
// 8. Glyph presets (all five)
//
sparkles.ui.components.demo.Section table.main.preset(string name) @systempreset("rounded"),
sparkles.ui.components.demo.Section table.main.preset(string name) @systempreset("square"),
sparkles.ui.components.demo.Section table.main.preset(string name) @systempreset("ascii"),
sparkles.ui.components.demo.Section table.main.preset(string name) @systempreset("double"),
sparkles.ui.components.demo.Section table.main.preset(string name) @systempreset("heavy"),
//
// 9. Custom glyphs
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Custom TableGlyphs (dotted rules — fields are individually overridable)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
[string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold x}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold x}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold x}"i"{bold x}"), string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold y}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold y}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold y}"i"{bold y}")],
["1", "日本"],
["2", "🚀"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(glyphs: (struct) sparkles.ui.components.table.layout.TableGlyphsThe configurable box-drawing glyph set. Defaults are the rounded frame plus the
square interior corners spans create; every field is a caller-overridable dchar.
TableGlyphs(
topLeft: '·', topRight: '·', bottomLeft: '·', bottomRight: '·',
horizontalLine: '┈', verticalLine: '┊',
teeDown: '·', teeUp: '·', teeRight: '·', teeLeft: '·', cross: '·',
cornerTL: '·', cornerTR: '·', cornerBL: '·', cornerBR: '·'))),
),
//
// 10. Separator toggles
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Toggle: border off",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] toggleSampletoggleSample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(border: false)),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Toggle: column separators off",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] toggleSampletoggleSample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnSeparators: false)),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Toggle: row separators on",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] toggleSampletoggleSample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(rowSeparators: true)),
),
//
// 10b. Header row & stub column separators (distinct emphasis rules)
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Header row separator (headerRows: 1 — distinct heavy rule under the header)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] samplesample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(headerRows: 1)),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Stub column separator (headerCols: 1, columnSeparators off — heavy ┃ after the stub)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] samplesample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(headerCols: 1, columnSeparators: false)),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Header row + stub column (headerRows: 1, headerCols: 1 — ╋ where the rules cross)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable((local variable) string[][] samplesample, (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(headerRows: 1, headerCols: 1)),
),
//
// 11. Width caps & wrapping — sparkles.base.text robustness
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Wrap (a): total maxWidth: 40 — shrink largest-first to fit",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["id", "description"],
["1", "A fairly long description that will not fit a narrow terminal and must wrap"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(maxWidth: 40)),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Wrap (b): per-column columnMaxWidths: [0, 20] — cap one column",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["id", "note"],
["1", "wrap this column at twenty cells while the id column stays untouched"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnMaxWidths: [0, 20])),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Width floor: columnMinWidths: [12, 0] — stable geometry for live re-renders",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["name", "value"],
["cpu", "45%"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnMinWidths: [12, 0])),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Wrap (c): explicit \\n in content — hard break",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["key", "value"],
["PATH", "/usr/local/bin\n/opt/app/bin\n/home/user/bin"],
]),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Wrap (d): Unicode width — full-width CJK (2 cells each) + emoji graphemes",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["lang", "sample"],
["ja", "日本語のテキストは全角文字で構成されています"],
["mix", "🚀 ✅ 🎉 🇯🇵 café résumé"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnMaxWidths: [0, 14])),
),
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Wrap (e): ANSI-safe wrapping — SGR style re-opened on each line",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["level", "message"],
[
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{red ERR}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{red ERR}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{red ERR}"i"{red ERR}"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold.green A long styled message whose bold-green SGR style must be re-emitted on every wrapped continuation line, never split mid-escape}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold.green A long styled message whose bold-green SGR style must be re-emitted on every wrapped continuation line, never split mid-escape}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold.green A long styled message whose bold-green SGR style must be re-emitted on every wrapped continuation line, never split mid-escape}"i"{bold.green A long styled message whose bold-green SGR style must be re-emitted on every wrapped continuation line, never split mid-escape}"),
],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(columnMaxWidths: [0, 26])),
),
//
// 12. validateTable — detect + render anyway
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "validateTable (overlap): reports the error AND still renders deterministically",
content: (local variable) const(string) validationNotevalidationNote ~ "\n\n" ~ string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Placement[] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a sparse Placement[] (order-independent cells naming their own
(row, col) and extent) as a boxed table. Lowers to the same slot grid as the
dense forms, so it renders identically. See Placement.
drawTable((local variable) sparkles.ui.components.table.grid.Placement[] overlappingoverlapping),
),
//
// 13. Title & footer — spliced into the frame like drawBox's
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Title/footer: spliced into the borders (truncated with … when narrow)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["item", "qty"],
["nuts", "12"],
["bolts", "7"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(title: string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Inventory}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Inventory}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safeditto — defaults to ColorDepth.trueColor (no folding).
styledText((template instance) core.interpolation.InterpolatedLiteral!"{bold Inventory}"i"{bold Inventory}"),
footer: "2 kinds", headerRows: 1,
columnAligns: [(enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.left = 1left, (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right])),
),
//
// 14. Align.decimal — a column of numbers sharing a dot position
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Align.decimal: values align on the last '.' (dotless sit left of it)",
content: string sparkles.ui.components.table.render.drawTable(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a rectangular string[][] as a boxed table. With the default
TableProps the output is byte-identical to the pre-overhaul renderer.
drawTable([
["benchmark", "median/iter"],
["parse", "1.25µs"],
["render", "23.5µs"],
["noop", "980ns"],
], (struct) sparkles.ui.components.table.layout.TablePropsTable rendering configuration. Defaults reproduce the pre-overhaul rendering
byte-for-byte: rounded glyphs, column separators on, row separators off, outer
border on, left/top alignment.
TableProps(headerRows: 1,
columnAligns: [(enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.left = 1left, (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.decimal = 4decimal])),
),
//
// 15. Per-cell halign/valign — overrides beat the column default
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "Per-cell align: a centered colspan banner over left/right columns",
content: string sparkles.ui.components.table.render.drawTable(sparkles.ui.components.table.grid.Cell[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null))Render a dense Cell[][] (cells may carry colSpan/rowSpan) as a boxed table.
Covered slots are omitted from the following cells (rows may be ragged); the
placement cursor recovers their positions. Malformed tables (overlap, over-long
rowspans) still render deterministically — use validateTable to detect them.
See Cell.
drawTable([
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("Quarterly totals", colSpan: 2, halign: (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.center = 2center)],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("north"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("1200", halign: (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right)],
[(struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("south"), (struct) sparkles.ui.components.table.grid.CellA table cell for the dense authoring form ``Cell[][]. colSpan/rowSpan (default
make it cover a rectangle of grid slots; the slots it covers are omitted
from the following cells of this and later rows (the placement cursor skips them).
A plain string[][] is sugar for extent-1 cells.
Cell("98", halign: (enum) sparkles.base.text.width.AlignHorizontal alignment of text within a fixed-width field. inherit means "defer
to a caller-supplied default" (e.g. a table column's default alignment) and is
treated as left if it reaches alignField unresolved. decimal aligns a
column of numbers on their last . — inherently columnar (a lone field has
no shared dot position), so alignField treats it as right; the columnar
pad is applied by the consumer (see drawTable's per-column handling).
Align.(enum value) sparkles.base.text.width.Align.right = 3right)],
]),
),
//
// 16. Streaming views — lazy line/chunk emission (eager layout)
//
(struct) sparkles.ui.components.demo.SectionA section in a demo with a header and content.
Section(
header: "drawTableLines: a forward range of lines (LiveRegion-ready), byte-identical joined",
content: string table.streamingNote()Demonstrates the streaming views: drawTableLines yields the same bytes as
drawTable line by line (no trailing newlines — ready for a LiveRegion
frame), and drawTableChunks!false reveals the table cell by cell.
streamingNote,
),
],
);
}
/// Demonstrates the streaming views: `drawTableLines` yields the same bytes as
/// `drawTable` line by line (no trailing newlines — ready for a `LiveRegion`
/// frame), and `drawTableChunks!false` reveals the table cell by cell.
private (alias) object.string = stringstring string table.streamingNote()Demonstrates the streaming views: drawTableLines yields the same bytes as
drawTable line by line (no trailing newlines — ready for a LiveRegion
frame), and drawTableChunks!false reveals the table cell by cell.
streamingNote()
{
import (package) stdstd.(package) std.algorithmalgorithm.(module) std.algorithm.iterationThis is a submodule of std.algorithm.
It contains generic iteration algorithms.
Function Name Description cache Eagerly evaluates and caches another range's front. lazyCache Lazily evaluates and caches another range's front, unlike cache. cacheBidirectional As above, but also provides back and popBack. chunkBy chunkBy!((a,b) => a[1] == b[1])([[1, 1], [1, 2], [2, 2], [2, 1]]) returns a range containing 3 subranges: the first with just [1, 1]; the second with the elements [1, 2] and [2, 2]; and the third with just [2, 1]. cumulativeFold cumulativeFold!((a, b) => a + b)([1, 2, 3, 4]) returns a lazily-evaluated range containing the successive reduced values 1, 3, 6, 10. each each!writeln([1, 2, 3]) eagerly prints the numbers 1, 2 and 3 on their own lines. filter filter!(a => a > 0)([1, -1, 2, 0, -3]) iterates over elements 1 and 2. filterBidirectional Similar to filter, but also provides back and popBack at a small increase in cost. fold fold!((a, b) => a + b)([1, 2, 3, 4]) returns 10. group group([5, 2, 2, 3, 3]) returns a range containing the tuples tuple(5, 1), tuple(2, 2), and tuple(3, 2). joiner joiner(["hello", "world!"], "; ") returns a range that iterates over the characters "hello; world!". No new string is created - the existing inputs are iterated. map map!(a => a * 2)([1, 2, 3]) lazily returns a range with the numbers 2, 4, 6. mean Colloquially known as the average, mean([1, 2, 3]) returns 2. permutations Lazily computes all permutations using Heap's algorithm. reduce reduce!((a, b) => a + b)([1, 2, 3, 4]) returns 10. This is the old implementation of fold. splitWhen Lazily splits a range by comparing adjacent elements. splitter Lazily splits a range by a separator, element predicate or whitespace. substitute [1, 2].substitute(1, 0.1) returns [0.1, 2]. sum Same as fold, but specialized for accurate summation. uniq Iterates over the unique elements in a range, which is assumed sorted.
Source
std/algorithm/iteration.d
iteration : (alias template) joiner = std.algorithm.iteration.joiner(RoR, Separator)(RoR r, Separator sep)Lazily joins a range of ranges with a separator. The separator itself
is a range. If a separator is not provided, then the ranges are
joined directly without anything in between them (often called flatten
in other languages).
Params:
r = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of input
ranges to be joined.
sep = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) of
element(s) to serve as separators in the joined range.
Returns:
A range of elements in the joined range. This will be a bidirectional range if
both outer and inner ranges of RoR are at least bidirectional ranges. Else if
both outer and inner ranges of RoR are forward ranges, the returned range will
be likewise. Otherwise it will be only an input range. The
$(REF_ALTTEXT range bidirectionality, isBidirectionalRange, std,range,primitives)
is propagated if no separator is specified.
See_also:
$(REF chain, std,range), which chains a sequence of ranges with compatible elements
into a single range.
Note:
When both outer and inner ranges of RoR are bidirectional and the joiner is
iterated from the back to the front, the separator will still be consumed from
front to back, even if it is a bidirectional range too.
joiner, (alias template) map = std.algorithm.iteration.map(fun...) if (fun.length >= 1)Implements the homonym function (also known as transform) present
in many languages of functional flavor. The call map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Params:
fun = one or more transformation functions
See_Also:
$(HTTP en.wikipedia.org/wiki/Map_(higher-order_function), Map (higher-order function))
map;
import (package) stdstd.(module) std.convA one-stop shop for converting values from one type to another.
Category Functions Generic asOriginalType castFrom parse to toChars bitCast Strings text wtext dtext writeText writeWText writeDText hexString Numeric octal roundTo signed unsigned Exceptions ConvException ConvOverflowException
Source
std/conv.d
conv : (alias template) text = std.conv.text(T...)(T args) if (T.length > 0)Convenience functions for converting one or more arguments
of any type into _text (the three character widths).
text, (alias template) to = std.conv.to(T)The to template converts a value from one type _to another.
The source type is deduced and the target type must be specified, for example the
expression to!int(42.0) converts the number 42 from
double _to int. The conversion is "safe", i.e.,
it checks for overflow; to!int(4.2e10) would throw the
ConvOverflowException exception. Overflow checks are only
inserted when necessary, e.g., to!double(42) does not do
any checking because any int fits in a double.
Conversions from string _to numeric types differ from the C equivalents
atoi() and atol() by checking for overflow and not allowing whitespace.
For conversion of strings _to signed types, the grammar recognized is:
$(PRE $(I Integer):
$(I Sign UnsignedInteger)
$(I UnsignedInteger)
$(I Sign):
$(B +)
$(B -))
For conversion _to unsigned types, the grammar recognized is:
$(PRE $(I UnsignedInteger):
$(I DecimalDigit)
$(I DecimalDigit) $(I UnsignedInteger))
to;
import (package) stdstd.(module) std.rangeThis module defines the notion of a range. Ranges generalize the concept of
arrays, lists, or anything that involves sequential access. This abstraction
enables the same set of algorithms (see std.algorithm) to be used
with a vast variety of different concrete types. For example,
a linear search algorithm such as find
works not just for arrays, but for linked-lists, input files,
incoming network data, etc.
Guides
There are many articles available that can bolster understanding ranges:
Ali Çehreli's tutorial on ranges
for the basics of working with and creating range-based code.
Jonathan M. Davis Introduction to Ranges
talk at DConf 2015 a vivid introduction from its core constructs to practical advice.
The DLang Tour's chapter on ranges
for an interactive introduction.
H. S. Teoh's tutorial on
component programming with ranges for a real-world showcase of the influence
of range-based programming on complex algorithms.
Andrei Alexandrescu's article
On Iteration for conceptual aspect of ranges and the motivation
Submodules
This module has two submodules:
The std.range.primitives submodule
provides basic range functionality. It defines several templates for testing
whether a given object is a range, what kind of range it is, and provides
some common range operations.
The std.range.interfaces submodule
provides object-based interfaces for working with ranges via runtime
polymorphism.
The remainder of this module provides a rich set of range creation and
composition templates that let you construct new ranges out of existing ranges:
| chain |
Concatenates several ranges into a single range.
|
| choose |
Chooses one of two ranges at runtime based on a boolean condition.
|
| chooseAmong |
Chooses one of several ranges at runtime based on an index.
|
| chunks |
Creates a range that returns fixed-size chunks of the original
range.
|
| cycle |
Creates an infinite range that repeats the given forward range
indefinitely. Good for implementing circular buffers.
|
| drop |
Creates the range that results from discarding the first n
elements from the given range.
|
| dropBack |
Creates the range that results from discarding the last n
elements from the given range.
|
| dropExactly |
Creates the range that results from discarding exactly n
of the first elements from the given range.
|
| dropBackExactly |
Creates the range that results from discarding exactly n
of the last elements from the given range.
|
| dropOne |
Creates the range that results from discarding
the first element from the given range.
|
| dropBackOne |
Creates the range that results from discarding
the last element from the given range.
|
| enumerate |
Iterates a range with an attached index variable.
|
| evenChunks |
Creates a range that returns a number of chunks of
approximately equal length from the original range.
|
| frontTransversal |
Creates a range that iterates over the first elements of the
given ranges.
|
| generate |
Creates a range by successive calls to a given function. This
allows to create ranges as a single delegate.
|
| indexed |
Creates a range that offers a view of a given range as though
its elements were reordered according to a given range of indices.
|
| iota |
Creates a range consisting of numbers between a starting point
and ending point, spaced apart by a given interval.
|
| lockstep |
Iterates n ranges in lockstep, for use in a foreach
loop. Similar to zip, except that lockstep is designed
especially for foreach loops.
|
| nullSink |
An output range that discards the data it receives.
|
| only |
Creates a range that iterates over the given arguments.
|
| padLeft |
Pads a range to a specified length by adding a given element to
the front of the range. Is lazy if the range has a known length.
|
| padRight |
Lazily pads a range to a specified length by adding a given element to
the back of the range.
|
| radial |
Given a random-access range and a starting point, creates a
range that alternately returns the next left and next right element to
the starting point.
|
| recurrence |
Creates a forward range whose values are defined by a
mathematical recurrence relation.
|
| refRange |
Pass a range by reference. Both the original range and the RefRange
will always have the exact same elements.
Any operation done on one will affect the other.
|
| repeat |
Creates a range that consists of a single element repeated n
times, or an infinite range repeating that element indefinitely.
|
| retro |
Iterates a bidirectional range backwards.
|
| roundRobin |
Given n ranges, creates a new range that return the n
first elements of each range, in turn, then the second element of each
range, and so on, in a round-robin fashion.
|
| sequence |
Similar to recurrence, except that a random-access range is
created.
|
| slide |
Creates a range that returns a fixed-size sliding window
over the original range. Unlike chunks,
it advances a configurable number of items at a time,
not one chunk at a time.
|
| stride |
Iterates a range with stride n.
|
| tail |
Return a range advanced to within n elements of the end of
the given range.
|
| take |
Creates a sub-range consisting of only up to the first n
elements of the given range.
|
| takeExactly |
Like take, but assumes the given range actually has n
elements, and therefore also defines the length property.
|
| takeNone |
Creates a random-access range consisting of zero elements of the
given range.
|
| takeOne |
Creates a random-access range consisting of exactly the first
element of the given range.
|
| tee |
Creates a range that wraps a given range, forwarding along
its elements while also calling a provided function with each element.
|
| transposed |
Transposes a range of ranges.
|
| transversal |
Creates a range that iterates over the n'th elements of the
given random-access ranges.
|
| zip |
Given n ranges, creates a range that successively returns a
tuple of all the first elements, a tuple of all the second elements,
etc.
|
Sortedness
Ranges whose elements are sorted afford better efficiency with certain
operations. For this, the assumeSorted function can be used to
construct a SortedRange from a pre-sorted range. The sort function also conveniently
returns a SortedRange. SortedRange objects provide some additional
range operations that take advantage of the fact that the range is sorted.
Source
std/range/package.d
range : (alias template) enumerate = std.range.enumerate(Enumerator = size_t, Range)(Range range, Enumerator start = 0) if (isIntegral!Enumerator && isInputRange!Range)Iterate over range with an attached index variable.
Each element is a $(REF Tuple, std,typecons) containing the index
and the element, in that order, where the index member is named index
and the element member is named value.
The index starts at start and is incremented by one on every iteration.
Overflow:
If range has length, then it is an error to pass a value for start
so that start + range.length is bigger than Enumerator.max, thus
it is ensured that overflow cannot happen.
If `range` does not have length, and `popFront` is called when
`front.index == Enumerator.max`, the index will overflow and
continue from `Enumerator.min`.
Params:
range = the $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to attach indexes to
start = the number to start the index counter from
Returns:
At minimum, an input range. All other range primitives are given in the
resulting range if range has them. The exceptions are the bidirectional
primitives, which are propagated only if range has length.
Example:
Useful for using foreach with an index loop variable:
import std.stdio : stdin, stdout;
import std.range : enumerate;
foreach (lineNum, line; stdin.byLine().enumerate(1))
stdout.writefln("line #%s: %s", lineNum, line);
----
enumerate;
import (package) sparklessparkles.(package) sparkles.uiui.(package) sparkles.ui.componentscomponents.(module) sparkles.ui.components.tableThe span-capable table: pure model resolution in
sparkles.ui.components.table.grid, the content-agnostic layout core
(configuration, width/height solving, junction glyphs, line ordering) in
sparkles.ui.components.table.layout, and the string view in
sparkles.ui.components.table.render, re-exported here under the historical
module name. Nothing else lives in this file — the test runner does not
discover unittests in package.d modules.
The widget view (sparkles.ui.components.table.widgets) is deliberately
not re-exported: it imports the whole toolkit — canvas, chrome, state,
widget, wrap — where the three modules above reach no further than
sparkles:base. Re-exporting it would put that closure on every consumer of
drawTable, including the wasm playground, which compiles a hand-listed set
of source directories and fails outright when the closure widens. Import it by
its own module path where the widget view is actually wanted.
table : (alias template) drawTableChunks = sparkles.ui.components.table.render.drawTableChunks(bool lineBuffered = true)(string[][] cells, TableProps props = TableProps.init)The chunk view of drawTable (the sibling of drawBoxChunks): chunks carry
their own newlines and join("") reproduces drawTable byte-for-byte.
lineBuffered: true yields one chunk per rendered body text line (line +
'\n'); lineBuffered: false yields one chunk per contentful cell field
(the aligned content pad run), so pacing the output reveals the table
cell by cell in reading order. Frame pieces — borders, junction rules
(including a spliced title/footer), separators, blank filler fields — never
form a standalone chunk: they accumulate as a pending prefix merged onto the
next content chunk, and the trailing frame (closing border, bottom rule) is
appended to the final content chunk. A table with no content at all
degrades to a single chunk carrying the whole frame.
drawTableChunks, (alias) drawTableLines = sparkles.ui.components.table.render.TableLineRange sparkles.ui.components.table.render.drawTableLines(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null)) @systemThe lazy line view of drawTable: eager layout, lazy emission. Table
layout is two-pass (column widths scan all content), so unlike the
fixed-width drawBox case the input can never be consumed lazily; what is
lazy is emission — each rule / body text line is built on demand from the
resolved layout.
A forward range of string lines without trailing newlines (ready for
LiveRegion.update), with .length. Parity:
drawTableLines(c, p).map!(l => l ~ '\n').join == drawTable(c, p)
byte-for-byte (drawTable terminates every line, including the last), i.e.
drawTableLines(c, p).array == drawTable(c, p).splitLines. An empty grid is
an empty range (drawTable's historical "").
drawTableLines;
auto (local variable) string[][] cellscells = [["a", "b"], ["1", "2"]];
(alias) object.string = stringstring (local variable) string out_out_;
foreach ((local variable) ulong ii, (local variable) string lineline; sparkles.ui.components.table.render.TableLineRange sparkles.ui.components.table.render.drawTableLines(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null)) @systemThe lazy line view of drawTable: eager layout, lazy emission. Table
layout is two-pass (column widths scan all content), so unlike the
fixed-width drawBox case the input can never be consumed lazily; what is
lazy is emission — each rule / body text line is built on demand from the
resolved layout.
A forward range of string lines without trailing newlines (ready for
LiveRegion.update), with .length. Parity:
drawTableLines`(c, p).map!(l => l ~ '\n').join == drawTable(c, p)`
byte-for-byte (drawTable terminates every line, including the last), i.e.
drawTableLines(c, p).array == drawTable(c, p).splitLines. An empty grid is
an empty range (drawTable's historical "").
drawTableLines((local variable) string[][] cellscells).std.range.enumerate!(ulong, TableLineRange).Result std.range.enumerate!(ulong, sparkles.ui.components.table.render.TableLineRange)(sparkles.ui.components.table.render.TableLineRange range, ulong start = 0LU) pure nothrow @nogc @safeIterate over range with an attached index variable.
Each element is a Tuple containing the index
and the element, in that order, where the index member is named index
and the element member is named value.
The index starts at start and is incremented by one on every iteration.
Overflow
If range has length, then it is an error to pass a value for start
so that ``start + range.length is bigger than Enumerator.max, thus
it is ensured that overflow cannot happen.
If range does not have length, and popFront is called when
front.index == Enumerator.max, the index will overflow and
continue from Enumerator.min.
Example
Useful for using foreach with an index loop variable:
import std.stdio : stdin, stdout;
import std.range : enumerate;
foreach (lineNum, line; stdin.byLine().enumerate(1))
stdout.writefln("line #%s: %s", lineNum, line);
Examples
Can start enumeration from a negative position:
import std.array : assocArray;
import std.range : enumerate;
bool[int] aa = true.repeat(3).enumerate(-1).assocArray();
assert(aa[-1]);
assert(aa[0]);
assert(aa[1]);
enumerate)
(local variable) string out_out_ ~= string std.conv.text!(string, ulong, string, string, string)(string __param_0, ulong __param_1, string __param_2, string __param_3, string __param_4) pure nothrow @safeConvenience functions for converting one or more arguments
of any type into text (the three character widths).
text("line ", (local variable) ulong ii, ": ", (local variable) string lineline, "\n");
const (local variable) const(string) chunkschunks = sparkles.ui.components.table.render.TableChunkRange!false sparkles.ui.components.table.render.drawTableChunks!false(string[][] cells, sparkles.ui.components.table.layout.TableProps props = TableProps(TableGlyphs('\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u252c', '\u2534', '\u251c', '\u2524', '\u253c', '\u250c', '\u2510', '\u2514', '\u2518', '\u257c', '\u257e', EmphasisGlyphs('\u2501', '\u2502', '\u252f', '\u2537', '\u251d', '\u2525', '\u253f', '\u250d', '\u2511', '\u2515', '\u2519'), EmphasisGlyphs('\u2500', '\u2503', '\u2530', '\u2538', '\u2520', '\u2528', '\u2542', '\u250e', '\u2512', '\u2516', '\u251a'), EmphasisGlyphs('\u2501', '\u2503', '\u2533', '\u253b', '\u2523', '\u252b', '\u254b', '\u250f', '\u2513', '\u2517', '\u251b')), true, true, false, 0LU, 0LU, 0LU, null, null, null, null, Align.left, null, VAlign.top, null)) @systemThe chunk view of drawTable (the sibling of drawBoxChunks): chunks carry
their own newlines and join("") reproduces drawTable byte-for-byte.
lineBuffered: true yields one chunk per rendered body text line (line +
'\n'); lineBuffered: false yields one chunk per contentful cell field
(the aligned content pad run), so pacing the output reveals the table
cell by cell in reading order. Frame pieces — borders, junction rules
(including a spliced title/footer), separators, blank filler fields — never
form a standalone chunk: they accumulate as a pending prefix merged onto the
next content chunk, and the trailing frame (closing border, bottom rule) is
appended to the final content chunk. A table with no content at all
degrades to a single chunk carrying the whole frame.
drawTableChunks!false((local variable) string[][] cellscells).std.algorithm.iteration.MapResult!(to, TableChunkRange!false) std.algorithm.iteration.map!(to).map!(sparkles.ui.components.table.render.TableChunkRange!false)(sparkles.ui.components.table.render.TableChunkRange!false r) pure nothrow @nogc @safeImplements the homonym function (also known as transform) present
in many languages of functional flavor. The call ``map!(fun)(range)
returns a range of which elements are obtained by applying fun(a)
left to right for all elements a in range. The original ranges are
not changed. Evaluation is done lazily.
Examples
import std.algorithm.comparison : equal;
import std.range : chain, only;
auto squares =
chain(only(1, 2, 3, 4), only(5, 6)).map!(a => a * a);
assert(equal(squares, only(1, 4, 9, 16, 25, 36)));
Multiple functions can be passed to map. In that case, the
element type of map is a tuple containing one element for each
function.
auto sums = [2, 4, 6, 8];
auto products = [1, 4, 9, 16];
size_t i = 0;
foreach (result; [ 1, 2, 3, 4 ].map!("a + a", "a * a"))
{
assert(result[0] == sums[i]);
assert(result[1] == products[i]);
++i;
}
You may alias map with some function(s) to a symbol and use
it separately:
import std.algorithm.comparison : equal;
import std.conv : to;
alias stringize = map!(to!string);
assert(equal(stringize([ 1, 2, 3, 4 ]), [ "1", "2", "3", "4" ]));
map!((template) std.conv.to!stringThe to template converts a value from one type to another.
The source type is deduced and the target type must be specified, for example the
expression to`!int(42.0)` converts the number 42 from
`double` to `int`. The conversion is "safe", i.e.,
it checks for overflow; to!int(4.2e10) would throw the
ConvOverflowException exception. Overflow checks are only
inserted when necessary, e.g., ``to!double(42) does not do
any checking because any int fits in a double.
Conversions from string to numeric types differ from the C equivalents
atoi() and atol() by checking for overflow and not allowing whitespace.
For conversion of strings to signed types, the grammar recognized is:
Integer:
Sign UnsignedInteger
UnsignedInteger
Sign:
+
-
For conversion to unsigned types, the grammar recognized is:
UnsignedInteger:
DecimalDigit
DecimalDigit UnsignedInteger
Examples
Converting a value to its own type (useful mostly for generic code)
simply returns its argument.
int a = 42;
int b = to!int(a);
double c = to!double(3.14); // c is double with value 3.14
Converting among numeric types is a safe way to cast them around.
Conversions from floating-point types to integral types allow loss of
precision (the fractional part of a floating-point number). The
conversion is truncating towards zero, the same way a cast would
truncate. (To round a floating point value when casting to an
integral, use roundTo.)
import std.exception : assertThrown;
int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));
assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);
When converting strings to numeric types, note that D hexadecimal and binary
literals are not handled. Neither the prefixes that indicate the base, nor the
horizontal bar used to separate groups of digits are recognized. This also
applies to the suffixes that indicate the type.
To work around this, you can specify a radix for conversions involving numbers.
auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);
Conversions from integral types to floating-point types always
succeed, but might lose accuracy. The largest integers with a
predecessor representable in floating-point format are 2^24-1 for
float, 2^53-1 for double, and 2^64-1 for real (when
real is 80-bit, e.g. on Intel machines).
// 2^24 - 1, largest proper integer representable as float
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);
Conversion from string types to char types enforces the input
to consist of a single code point, and said code point must
fit in the target type. Otherwise, ConvException is thrown.
import std.exception : assertThrown;
assert(to!char("a") == 'a');
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
assert(to!wchar("ñ") == 'ñ');
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
assert(to!dchar("😃") == '😃');
// Using wstring or dstring as source type does not affect the result
assert(to!char("a"w) == 'a');
assert(to!char("a"d) == 'a');
// Two code points cannot be converted to a single one
assertThrown(to!char("ab"));
Converting an array to another array type works by converting each
element in turn. Associative arrays can be converted to associative
arrays as long as keys and values can in turn be converted.
import std.string : split;
int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);
Conversions operate transitively, meaning that they work on arrays and
associative arrays of any complexity.
This conversion works because to`!short` applies to an `int`, to!wstring
applies to a string, to`!string` applies to a `double`, and
to!(double[]) applies to an int[]. The conversion might throw an
exception because ``to!short might fail the range check.
int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);
Object-to-object conversions by dynamic casting throw exception when
the source is non-null and the target is null.
import std.exception : assertThrown;
// Testing object conversions
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));
Stringize conversion from all types is supported.
String to string conversion works for any two string types having
(char, wchar, dchar) character widths and any
combination of qualifiers (mutable, const, or immutable).
Converts array (other than strings) to string.
Each element is converted by calling ``to!T.
Associative array to string conversion.
Each element is converted by calling ``to!T.
Object to string conversion calls toString against the object or
returns "null" if the object is null.
Struct to string conversion calls toString against the struct if
it is defined.
For structs that do not define toString, the conversion to string
produces the list of fields.
Enumerated types are converted to strings as their symbolic names.
Boolean values are converted to "true" or "false".
char, wchar, dchar to a string type.
Unsigned or signed integers to strings.
: Convert integral value to string in radix radix.
radix must be a value from 2 to 36.
value is treated as a signed value only if radix is 10.
The characters A through Z are used to represent values 10 through 36
and their case is determined by the letterCase parameter.
All floating point types to all string types.
Pointer to string conversions convert the pointer to a size_t value.
If pointer is char*, treat it as C-style strings.
In that case, this function is @system.
See formatValue on how toString should be defined.
// Conversion representing dynamic/static array with string
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");
// Conversion representing associative array with string
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
to!string(associativeArray) == `["1":2, "0":1]`);
// char* to string conversion
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");
// Conversion reinterpreting void array to string
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);
auto c = to!(wchar[])(b);
assert(c == "abcx");
Strings can be converted to enum types. The enum member with the same name as the
input string is returned. The comparison is case-sensitive.
A ConvException is thrown if the enum does not have the specified member.
import std.exception : assertThrown;
enum E { a, b, c }
assert(to!E("a") == E.a);
assert(to!E("b") == E.b);
assertThrown!ConvException(to!E("A"));
to!(alias) object.string = stringstring).std.algorithm.iteration.joiner!(MapResult!(to, TableChunkRange!false), string).Result std.algorithm.iteration.joiner!(std.algorithm.iteration.MapResult!(to, TableChunkRange!false), string)(std.algorithm.iteration.MapResult!(to, TableChunkRange!false) r, string sep) @systemLazily joins a range of ranges with a separator. The separator itself
is a range. If a separator is not provided, then the ranges are
joined directly without anything in between them (often called flatten
in other languages).
Note
When both outer and inner ranges of RoR are bidirectional and the joiner is
iterated from the back to the front, the separator will still be consumed from
front to back, even if it is a bidirectional range too.
Examples
import std.algorithm.comparison : equal;
import std.conv : text;
assert(["abc", "def"].joiner.equal("abcdef"));
assert(["Mary", "has", "a", "little", "lamb"]
.joiner("...")
.equal("Mary...has...a...little...lamb"));
assert(["", "abc"].joiner("xyz").equal("xyzabc"));
assert([""].joiner("xyz").equal(""));
assert(["", ""].joiner("xyz").equal("xyz"));
joiner(" ⏵ ").string std.conv.to!string.to!(std.algorithm.iteration.joiner!(MapResult!(to, TableChunkRange!false), string).Result)(std.algorithm.iteration.joiner!(MapResult!(to, TableChunkRange!false), string).Result __param_0) @systemThe to template converts a value from one type to another.
The source type is deduced and the target type must be specified, for example the
expression to`!int(42.0)` converts the number 42 from
`double` to `int`. The conversion is "safe", i.e.,
it checks for overflow; to!int(4.2e10) would throw the
ConvOverflowException exception. Overflow checks are only
inserted when necessary, e.g., ``to!double(42) does not do
any checking because any int fits in a double.
Conversions from string to numeric types differ from the C equivalents
atoi() and atol() by checking for overflow and not allowing whitespace.
For conversion of strings to signed types, the grammar recognized is:
Integer:
Sign UnsignedInteger
UnsignedInteger
Sign:
+
-
For conversion to unsigned types, the grammar recognized is:
UnsignedInteger:
DecimalDigit
DecimalDigit UnsignedInteger
Examples
Converting a value to its own type (useful mostly for generic code)
simply returns its argument.
int a = 42;
int b = to!int(a);
double c = to!double(3.14); // c is double with value 3.14
Converting among numeric types is a safe way to cast them around.
Conversions from floating-point types to integral types allow loss of
precision (the fractional part of a floating-point number). The
conversion is truncating towards zero, the same way a cast would
truncate. (To round a floating point value when casting to an
integral, use roundTo.)
import std.exception : assertThrown;
int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));
assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);
When converting strings to numeric types, note that D hexadecimal and binary
literals are not handled. Neither the prefixes that indicate the base, nor the
horizontal bar used to separate groups of digits are recognized. This also
applies to the suffixes that indicate the type.
To work around this, you can specify a radix for conversions involving numbers.
auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);
Conversions from integral types to floating-point types always
succeed, but might lose accuracy. The largest integers with a
predecessor representable in floating-point format are 2^24-1 for
float, 2^53-1 for double, and 2^64-1 for real (when
real is 80-bit, e.g. on Intel machines).
// 2^24 - 1, largest proper integer representable as float
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);
Conversion from string types to char types enforces the input
to consist of a single code point, and said code point must
fit in the target type. Otherwise, ConvException is thrown.
import std.exception : assertThrown;
assert(to!char("a") == 'a');
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
assert(to!wchar("ñ") == 'ñ');
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
assert(to!dchar("😃") == '😃');
// Using wstring or dstring as source type does not affect the result
assert(to!char("a"w) == 'a');
assert(to!char("a"d) == 'a');
// Two code points cannot be converted to a single one
assertThrown(to!char("ab"));
Converting an array to another array type works by converting each
element in turn. Associative arrays can be converted to associative
arrays as long as keys and values can in turn be converted.
import std.string : split;
int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);
Conversions operate transitively, meaning that they work on arrays and
associative arrays of any complexity.
This conversion works because to`!short` applies to an `int`, to!wstring
applies to a string, to`!string` applies to a `double`, and
to!(double[]) applies to an int[]. The conversion might throw an
exception because ``to!short might fail the range check.
int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);
Object-to-object conversions by dynamic casting throw exception when
the source is non-null and the target is null.
import std.exception : assertThrown;
// Testing object conversions
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));
Stringize conversion from all types is supported.
String to string conversion works for any two string types having
(char, wchar, dchar) character widths and any
combination of qualifiers (mutable, const, or immutable).
Converts array (other than strings) to string.
Each element is converted by calling ``to!T.
Associative array to string conversion.
Each element is converted by calling ``to!T.
Object to string conversion calls toString against the object or
returns "null" if the object is null.
Struct to string conversion calls toString against the struct if
it is defined.
For structs that do not define toString, the conversion to string
produces the list of fields.
Enumerated types are converted to strings as their symbolic names.
Boolean values are converted to "true" or "false".
char, wchar, dchar to a string type.
Unsigned or signed integers to strings.
: Convert integral value to string in radix radix.
radix must be a value from 2 to 36.
value is treated as a signed value only if radix is 10.
The characters A through Z are used to represent values 10 through 36
and their case is determined by the letterCase parameter.
All floating point types to all string types.
Pointer to string conversions convert the pointer to a size_t value.
If pointer is char*, treat it as C-style strings.
In that case, this function is @system.
See formatValue on how toString should be defined.
// Conversion representing dynamic/static array with string
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");
// Conversion representing associative array with string
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
to!string(associativeArray) == `["1":2, "0":1]`);
// char* to string conversion
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");
// Conversion reinterpreting void array to string
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);
auto c = to!(wchar[])(b);
assert(c == "abcx");
Strings can be converted to enum types. The enum member with the same name as the
input string is returned. The comparison is case-sensitive.
A ConvException is thrown if the enum does not have the specified member.
import std.exception : assertThrown;
enum E { a, b, c }
assert(to!E("a") == E.a);
assert(to!E("b") == E.b);
assertThrown!ConvException(to!E("A"));
to!(alias) object.string = stringstring;
(local variable) string out_out_ ~= "\ncell chunks: " ~ (local variable) const(string) chunkschunks;
return (local variable) string out_out_;
}