box.dhover×190all
#!/usr/bin/env dub
/+ dub.sdl:
    name "box"
    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"
    }
+/

import 
(package) std
std
.
(module) std.algorithm

This package implements generic algorithms oriented towards the processing of sequences. Sequences processed by these functions define range-based interfaces. See also Reference on ranges and tutorial on ranges.

Algorithms are categorized into the following submodules:

Submodule Functions

| Searching | all any balancedParens boyerMooreFinder canFind commonPrefix count countUntil endsWith find findAdjacent findAmong findSkip findSplit findSplitAfter findSplitBefore minCount maxCount minElement maxElement minIndex maxIndex minPos maxPos skipOver startsWith until |

| Comparison | among castSwitch clamp cmp either equal isPermutation isSameLength levenshteinDistance levenshteinDistanceAndPath max min mismatch predSwitch |

| Iteration | cache cacheBidirectional chunkBy cumulativeFold each filter filterBidirectional fold group joiner map mean permutations reduce splitWhen splitter substitute sum uniq |

| Sorting | completeSort isPartitioned isSorted isStrictlyMonotonic ordered strictlyOrdered makeIndex merge multiSort nextEvenPermutation nextPermutation nthPermutation partialSort partition partition3 schwartzSort sort topN topNCopy topNIndex |

| Set operations (setops) | cartesianProduct largestPartialIntersection largestPartialIntersectionWeighted multiwayMerge multiwayUnion setDifference setIntersection setSymmetricDifference |

| Mutation | bringToFront copy fill initializeAll move moveAll moveSome moveEmplace moveEmplaceAll moveEmplaceSome remove reverse strip stripLeft stripRight swap swapRanges uninitializedFill |

Many functions in this package are parameterized with a predicate. The predicate may be any suitable callable type (a function, a delegate, a functor, or a lambda), or a compile-time string. The string may consist of any legal D expression that uses the symbol a (for unary functions) or the symbols a and b (for binary functions). These names will NOT interfere with other homonym symbols in user code because they are evaluated in a different context. The default for all binary comparison predicates is "a == b" for unordered operations and "a < b" for ordered operations.

Example

int[] a = ...;
static bool greater(int a, int b)
{
    return a > b;
}
sort!greater(a);           // predicate as alias
sort!((a, b) => a > b)(a); // predicate as a lambda.
sort!"a > b"(a);           // predicate as string
                           // (no ambiguity with array name)
sort(a);                   // no predicate, "a < b" is implicit

Source

std/algorithm/package.d

@copyrightAndrei Alexandrescu 2008-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu
algorithm
:
(alias template) box.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.

@paramfun one or more transformation functions@seeMap (higher-order function)
map
,
(alias template) box.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).

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.

@paramr An input range of input ranges to be joined.@paramsep A forward range of element(s) to serve as separators in the joined range.@returnsA 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 range bidirectionality is propagated if no separator is specified.@seechain, which chains a sequence of ranges with compatible elements into a single range.
joiner
;
import
(package) std
std
.
(module) std.conv

A 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

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Shin Fujishiro, Adam D. Ruppe, Kenji Hara
conv
:
(alias template) box.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: Integer: Sign UnsignedInteger UnsignedInteger Sign: + -

For conversion to unsigned types, the grammar recognized is: UnsignedInteger: DecimalDigit DecimalDigit UnsignedInteger

to
;
import
(package) sparkles
sparkles
.
(package) sparkles.ui
ui
.
(package) sparkles.ui.components
components
.
(module) sparkles.ui.components.box
box
:
(alias) box.drawBox = string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
,
(struct) sparkles.ui.components.box.BoxProps
BoxProps
,
(enum) sparkles.ui.components.box.TitleOverflow

How a title too wide for maxWidth is handled. Only takes effect when maxWidth > 0; with no cap the box always expands to fit the title.

TitleOverflow
;
import
(package) sparkles
sparkles
.
(package) sparkles.ui
ui
.
(package) sparkles.ui.components
components
.
(module) sparkles.ui.components.demo

Demo 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.Section

A section in a demo with a header and content.

Section
,
(alias) box.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")) @safe

Runs 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"),
    ],
);
@paramheader The demo header shown in the opening banner@paramcontent Array of sections to display@paramprops Configuration options
runDemo
;
import
(package) sparkles
sparkles
.
(package) sparkles.ui
ui
.
(package) sparkles.ui.components
components
.
(module) sparkles.ui.components.table

The 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) box.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
;
import
(package) sparkles
sparkles
.
(package) sparkles.base
base
.
(module) sparkles.base.term_style
term_style
:
(enum) sparkles.base.term_style.Style
Style
,
(alias) box.stylize = string sparkles.base.term_style.stylize(string text, sparkles.base.term_style.Style style, bool resetAfter = true) pure nothrow @safe
stylize
,
(alias) box.styleSample = string sparkles.base.term_style.styleSample(sparkles.base.term_style.Style style, bool resetAfter = true) pure nothrow @safe

Returns the name of a Style styled with that style.

Useful for displaying style palettes where styles demonstrate themselves.

Example

``styleSample(Style.red) returns "red" rendered in red.

styleSample
;
import
(package) sparkles
sparkles
.
(package) sparkles.base
base
.
(module) sparkles.base.styled_template

Style 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) box.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) sparkles
sparkles
.
(package) sparkles.base
base
.
(module) sparkles.base.prettyprint
prettyprint
:
(alias template) box.prettyPrint = sparkles.base.prettyprint.prettyPrint(T, Hook = void)(in T value, in PrettyPrintOptions!Hook opt = PrettyPrintOptions!Hook())

Convenience overload that returns a string.

prettyPrint
,
(alias struct) box.PrettyPrintOptions = sparkles.base.prettyprint.PrettyPrintOptions(SourceUriHook = void)
PrettyPrintOptions
;
struct
(struct) box.Config
Config
{
(alias) object.string = string
string
(field) string box.Config.host
host
;
int
(field) int box.Config.port
port
;
bool
(field) bool box.Config.ssl
ssl
;
(alias) object.string = string
string
[]
(field) string[] box.Config.endpoints
endpoints
;
} struct
(struct) box.Server
Server
{
(alias) object.string = string
string
(field) string box.Server.name
name
;
(alias) object.string = string
string
(field) string box.Server.ip
ip
;
int
(field) int box.Server.port
port
;
} struct
(struct) box.Cluster
Cluster
{
(alias) object.string = string
string
(field) string box.Cluster.name
name
;
(struct) box.Server
Server
[]
(field) box.Server[] box.Cluster.servers
servers
;
bool
(field) bool box.Cluster.active
active
;
} void
void D main()
main
()
{
void sparkles.ui.components.demo.runDemo(string header, sparkles.ui.components.demo.Section[] content, sparkles.ui.components.demo.DemoProps props = DemoProps(67LU, "Demo Complete")) @safe

Runs 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");
@paramheader The demo header shown in the opening banner@paramcontent Array of sections to display@paramprops Configuration options
runDemo
(
header: "drawBox Demo - All Features", content: [
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Simple Box", content: ["1"] .
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("1"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Box with Styled Content", content: [
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Status: }{green Running}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Status: }{green Running}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Status: }{green Running}"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Mode: }{yellow Production}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Mode: }{yellow Production}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Mode: }{yellow Production}"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Health: }{brightGreen Healthy}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Health: }{brightGreen Healthy}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Health: }{brightGreen Healthy}"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Uptime: }{cyan 3 days, 14 hours}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Uptime: }{cyan 3 days, 14 hours}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Uptime: }{cyan 3 days, 14 hours}"),
].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("Status"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Box without Left Border", content: ["This is line number 1", "This is line number 2", "This is line number 3"] .
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("No Border",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(omitLeftBorder: true)),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Box with Embedded Table", content: [ ["Name", "Age", "Role"], ["Alice", "30", "Engineer"], ["Bob", "25", "Designer"], ["Carol", "35", "Manager"], ].
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.ui.components.box.drawBox(string content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))

Overload that accepts a single string and splits it into lines internally.

drawBox
("Team"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Box with prettyPrint Output", content:
(struct) box.Config
Config
(
host: "localhost", port: 8080, ssl: true, endpoints: ["/api", "/health", "/metrics"], ).
string sparkles.base.prettyprint.prettyPrint!(box.Config, void)(in box.Config value, in sparkles.base.prettyprint.PrettyPrintOptions!void opt = PrettyPrintOptions(cast(ushort)2u, cast(ushort)8u, 32u, 80u, true, false)) pure nothrow @safe

Convenience overload that returns a string.

prettyPrint
(
(template instance) sparkles.base.prettyprint.PrettyPrintOptions!void
PrettyPrintOptions
!void(softMaxWidth: 0)).
string sparkles.ui.components.box.drawBox(string content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))

Overload that accepts a single string and splits it into lines internally.

drawBox
("Config"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Dashboard Example", content: [ [
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Metric}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Metric}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Metric}"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Value}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Value}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Value}"),
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 @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Status}")],
["CPU Usage", "45%",
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green OK}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green OK}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{green OK}")],
["Memory", "2.1 GB",
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green OK}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green OK}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{green OK}")],
["Disk", "89%",
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{yellow Warning}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{yellow Warning}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{yellow Warning}")],
["Network", "1.2 Gbps",
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green OK}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green OK}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{green OK}")],
].
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.ui.components.box.drawBox(string content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))

Overload that accepts a single string and splits it into lines internally.

drawBox
("Metrics"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Color Palette Box", content: [
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Foreground Colors:}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Foreground Colors:}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Foreground Colors:}"),
" " ~ [
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.red = [31u, 39u]
red
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.green = [32u, 39u]
green
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.yellow = [33u, 39u]
yellow
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.blue = [34u, 39u]
blue
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.magenta = [35u, 39u]
magenta
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.cyan = [36u, 39u]
cyan
]
.
std.algorithm.iteration.MapResult!(styleSample, Style[]) std.algorithm.iteration.map!(styleSample).map!(sparkles.base.term_style.Style[])(sparkles.base.term_style.Style[] r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!
string sparkles.base.term_style.styleSample(sparkles.base.term_style.Style style, bool resetAfter = true) pure nothrow @safe

Returns the name of a Style styled with that style.

Useful for displaying style palettes where styles demonstrate themselves.

Example

``styleSample(Style.red) returns "red" rendered in red.

Examples

assert(styleSample(Style.red) == "\x1b[31mred\x1b[39m");
assert(styleSample(Style.bold) == "\x1b[1mbold\x1b[22m");
assert(styleSample(Style.green, false) == "\x1b[32mgreen");
styleSample
.
std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result std.algorithm.iteration.joiner!(std.algorithm.iteration.MapResult!(styleSample, Style[]), string)(std.algorithm.iteration.MapResult!(styleSample, Style[]) r, string sep) pure nothrow @safe

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).

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"));
@paramr An input range of input ranges to be joined.@paramsep A forward range of element(s) to serve as separators in the joined range.@returnsA 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 range bidirectionality is propagated if no separator is specified.@seechain, which chains a sequence of ranges with compatible elements into a single range.
joiner
(" ").
string std.conv.to!string.to!(std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result)(std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result __param_0) pure @safe

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: 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.

    special case

    : 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 = string
string
,
"",
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Bright Colors:}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Bright Colors:}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Bright Colors:}"),
" " ~ [
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.brightRed = [91u, 39u]
brightRed
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.brightGreen = [92u, 39u]
brightGreen
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.brightYellow = [93u, 39u]
brightYellow
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.brightBlue = [94u, 39u]
brightBlue
]
.
std.algorithm.iteration.MapResult!(styleSample, Style[]) std.algorithm.iteration.map!(styleSample).map!(sparkles.base.term_style.Style[])(sparkles.base.term_style.Style[] r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!
string sparkles.base.term_style.styleSample(sparkles.base.term_style.Style style, bool resetAfter = true) pure nothrow @safe

Returns the name of a Style styled with that style.

Useful for displaying style palettes where styles demonstrate themselves.

Example

``styleSample(Style.red) returns "red" rendered in red.

Examples

assert(styleSample(Style.red) == "\x1b[31mred\x1b[39m");
assert(styleSample(Style.bold) == "\x1b[1mbold\x1b[22m");
assert(styleSample(Style.green, false) == "\x1b[32mgreen");
styleSample
.
std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result std.algorithm.iteration.joiner!(std.algorithm.iteration.MapResult!(styleSample, Style[]), string)(std.algorithm.iteration.MapResult!(styleSample, Style[]) r, string sep) pure nothrow @safe

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).

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"));
@paramr An input range of input ranges to be joined.@paramsep A forward range of element(s) to serve as separators in the joined range.@returnsA 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 range bidirectionality is propagated if no separator is specified.@seechain, which chains a sequence of ranges with compatible elements into a single range.
joiner
(" ").
string std.conv.to!string.to!(std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result)(std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result __param_0) pure @safe

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: 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.

    special case

    : 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 = string
string
,
"",
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Styles:}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Styles:}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Styles:}"),
" " ~ [
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.bold = [1u, 22u]
bold
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.dim = [2u, 22u]
dim
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.italic = [3u, 23u]
italic
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.underline = [4u, 24u]
underline
,
(enum) sparkles.base.term_style.Style
Style
.
(enum value) sparkles.base.term_style.Style.strikethrough = [9u, 29u]
strikethrough
]
.
std.algorithm.iteration.MapResult!(styleSample, Style[]) std.algorithm.iteration.map!(styleSample).map!(sparkles.base.term_style.Style[])(sparkles.base.term_style.Style[] r) pure nothrow @nogc @safe

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.

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" ]));
@paramfun one or more transformation functions@seeMap (higher-order function)@paramr an input range@returnsA range with each fun applied to all the elements. If there is more than one fun, the element type will be Tuple containing one element for each fun.
map
!
string sparkles.base.term_style.styleSample(sparkles.base.term_style.Style style, bool resetAfter = true) pure nothrow @safe

Returns the name of a Style styled with that style.

Useful for displaying style palettes where styles demonstrate themselves.

Example

``styleSample(Style.red) returns "red" rendered in red.

Examples

assert(styleSample(Style.red) == "\x1b[31mred\x1b[39m");
assert(styleSample(Style.bold) == "\x1b[1mbold\x1b[22m");
assert(styleSample(Style.green, false) == "\x1b[32mgreen");
styleSample
.
std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result std.algorithm.iteration.joiner!(std.algorithm.iteration.MapResult!(styleSample, Style[]), string)(std.algorithm.iteration.MapResult!(styleSample, Style[]) r, string sep) pure nothrow @safe

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).

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"));
@paramr An input range of input ranges to be joined.@paramsep A forward range of element(s) to serve as separators in the joined range.@returnsA 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 range bidirectionality is propagated if no separator is specified.@seechain, which chains a sequence of ranges with compatible elements into a single range.
joiner
(" ").
string std.conv.to!string.to!(std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result)(std.algorithm.iteration.joiner!(MapResult!(styleSample, Style[]), string).Result __param_0) pure @safe

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: 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.

    special case

    : 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 = string
string
,
].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("Styles"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Complex Data Structure", content:
(struct) box.Cluster
Cluster
(
name: "Production", servers: [
(struct) box.Server
Server
("web-01", "192.168.1.10", 80),
(struct) box.Server
Server
("web-02", "192.168.1.11", 80),
(struct) box.Server
Server
("db-01", "192.168.1.20", 5432),
], active: true, ).
string sparkles.base.prettyprint.prettyPrint!(box.Cluster, void)(in box.Cluster value, in sparkles.base.prettyprint.PrettyPrintOptions!void opt = PrettyPrintOptions(cast(ushort)2u, cast(ushort)8u, 32u, 80u, true, false)) pure nothrow @safe

Convenience overload that returns a string.

prettyPrint
(
(template instance) sparkles.base.prettyprint.PrettyPrintOptions!void
PrettyPrintOptions
!void(softMaxWidth: 60)).
string sparkles.ui.components.box.drawBox(string content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))

Overload that accepts a single string and splits it into lines internally.

drawBox
("Cluster"),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Box with Footer", content: [ "Build started at 14:32:01", "Compiling 42 modules...", "Linking executable...", "Build completed in 3.2s", ].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("Build Log",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(footer:
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x93 Success}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x93 Success}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{green ✓ Success}"))),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Task Status with Footer", content: [
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Task: }Deploy to production")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Task: }Deploy to production" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Task: }Deploy to production"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Started: }2024-01-15 10:30")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Started: }2024-01-15 10:30" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Started: }2024-01-15 10:30"),
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{bold Duration: }45 seconds")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{bold Duration: }45 seconds" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{bold Duration: }45 seconds"),
].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
(
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{cyan deploy-v2.1.0}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{cyan deploy-v2.1.0}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{cyan deploy-v2.1.0}"),
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(footer:
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{red \xe2\x9c\x97 Failed}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{red \xe2\x9c\x97 Failed}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{red ✗ Failed}")),
), ),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "minWidth - Pad a Short Box to a Fixed Frame", content: ["Done"] .
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("Status",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(minWidth: 40)),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "maxWidth - Wrap Long Lines Within the Frame", content: [ "The quick brown fox jumps over the lazy dog and keeps on running well past the edge.", ].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("Wrapped",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(maxWidth: 40)),
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Fixed Width - minWidth == maxWidth", content: [ "Short line", "A much longer line that has to wrap to stay inside the fixed-width frame.", ].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
(
"Fixed 40",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(minWidth: 40, maxWidth: 40, footer:
string sparkles.base.styled_template.styledText!(core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x93 aligned}")(core.interpolation.InterpolationHeader header, core.interpolation.InterpolatedLiteral!"{green \xe2\x9c\x93 aligned}" __param_1, core.interpolation.InterpolationFooter footer) nothrow @safe

ditto — defaults to ColorDepth.trueColor (no folding).

styledText
(i"{green ✓ aligned}")),
), ),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Aligned Stack - Same Width Regardless of Content", content: [ ["ok"].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("alpha",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(minWidth: 44, maxWidth: 44)),
["a slightly longer middle line"] .
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("beta",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(minWidth: 44, maxWidth: 44)),
["x"].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
("gamma",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(minWidth: 44, maxWidth: 44)),
].
std.algorithm.iteration.joiner!(string[], string).Result std.algorithm.iteration.joiner!(string[], string)(string[] r, string sep) pure nothrow @nogc @safe

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).

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"));
@paramr An input range of input ranges to be joined.@paramsep A forward range of element(s) to serve as separators in the joined range.@returnsA 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 range bidirectionality is propagated if no separator is specified.@seechain, which chains a sequence of ranges with compatible elements into a single range.
joiner
("\n").
string std.conv.to!string.to!(std.algorithm.iteration.joiner!(string[], string).Result)(std.algorithm.iteration.joiner!(string[], string).Result __param_0) pure @safe

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: 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.

    special case

    : 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 = string
string
,
),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Title Overflow - wrap (nested title box with ┤ ├ handles)", content: [ "Body content line one", "Body content line two", ].
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
(
"This is a very long multi-line drawBox title. It ends here.",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(maxWidth: 40, titleOverflow:
(enum) sparkles.ui.components.box.TitleOverflow

How a title too wide for maxWidth is handled. Only takes effect when maxWidth > 0; with no cap the box always expands to fit the title.

TitleOverflow
.
(enum value) sparkles.ui.components.box.TitleOverflow.wrap = 1

Wrap a long title into a nested title box (┤ ├ handles on the frame).

wrap
),
), ),
(struct) sparkles.ui.components.demo.Section

A section in a demo with a header and content.

Section
(
header: "Title Overflow - ellipsis (truncate to one line)", content: ["Body content line one"] .
string sparkles.ui.components.box.drawBox(string[] content, string title, sparkles.ui.components.box.BoxProps props = BoxProps(false, null, null, null, null, null, 0LU, 0LU, TitleOverflow.expand, '\u256d', '\u256e', '\u2570', '\u256f', '\u2500', '\u2502', '\u257c', '\u257e', '\u2524', '\u251c'))
drawBox
(
"This is a very long multi-line drawBox title. It ends here.",
(struct) sparkles.ui.components.box.BoxProps
BoxProps
(maxWidth: 40, titleOverflow:
(enum) sparkles.ui.components.box.TitleOverflow

How a title too wide for maxWidth is handled. Only takes effect when maxWidth > 0; with no cap the box always expands to fit the title.

TitleOverflow
.
(enum value) sparkles.ui.components.box.TitleOverflow.ellipsis = 2

Truncate the title to one line with a trailing '…'.

ellipsis
),
), ), ], ); }