#!/usr/bin/env dub
/+ dub.sdl:
name "property_tree_tree_adapter"
targetPath "build"
dependency "sparkles:ui" path="../../../.."
dflags "-preview=in" "-preview=dip1000"
buildType "checked" {
buildOptions "optimize" "inline" "debugInfo"
}
+/
/**
* The whole thing as an ADAPTER over the existing components:
* `TreeData!PropNode` + `TreeViewState!string` + `activate`/`collapseOrUp` +
* `treeText`. No new interaction machinery.
*
* Under test:
* C20. A property tree needs NOTHING new from the tree component except a
* rebuild: `TreeStep.rebuild` already means "the opened set changed",
* which for us means "re-walk the subject".
* C21. `state.open` keyed by the path string is the whole persistence story.
* C22. The one real toolkit gap: `TreeData.hasChildren` is STRUCTURAL, so a
* closed composite whose children were never materialised renders as a
* leaf and `collapseOrUp` will not close it. `activate` already reads an
* `expandable` capability off the node value; `treeView`/`writeTreeText`
* and `collapseOrUp` do not.
* C23. An edit ([`edit-commands.d`](./edit-commands.d)) followed by a rebuild refreshes the badges and
* preserves cursor and expansion — the frame model's whole promise.
*
* Run: `dub run --single tree-adapter.d`
*/
module (module) property_tree_tree_adapterThe whole thing as an ADAPTER over the existing components:
TreeData!PropNode + TreeViewState!string + activate/collapseOrUp +
treeText. No new interaction machinery.
Under test:
C20. A property tree needs NOTHING new from the tree component except a
rebuild: TreeStep.rebuild already means "the opened set changed",
which for us means "re-walk the subject".
C21. state.open keyed by the path string is the whole persistence story.
C22. The one real toolkit gap: TreeData.hasChildren is STRUCTURAL, so a
closed composite whose children were never materialised renders as a
leaf and collapseOrUp will not close it. activate already reads an
expandable capability off the node value; treeView/writeTreeText
and collapseOrUp do not.
C23. An edit (edit-commands.d) followed by a rebuild refreshes the badges and
preserves cursor and expansion — the frame model's whole promise.
Run
dub run --single tree-adapter.d
property_tree_tree_adapter;
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) property_tree_tree_adapter.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) property_tree_tree_adapter.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) stdstd.(module) std.traitsTemplates which extract information about types and symbols at compile time.
Category Templates Symbol Name traits fullyQualifiedName mangledName moduleName packageName Function traits isFunction arity functionAttributes hasFunctionAttributes functionLinkage FunctionTypeOf isSafe isUnsafe isFinal ParameterDefaults ParameterIdentifierTuple ParameterStorageClassTuple Parameters ReturnType SetFunctionAttributes variadicFunctionStyle Aggregate Type traits BaseClassesTuple BaseTypeTuple classInstanceAlignment EnumMembers FieldNameTuple Fields hasAliasing hasElaborateAssign hasElaborateCopyConstructor hasElaborateDestructor hasElaborateMove hasIndirections hasMember hasStaticMember hasNested hasUnsharedAliasing InterfacesTuple isInnerClass isNested MemberFunctionsTuple RepresentationTypeTuple TemplateArgsOf TemplateOf TransitiveBaseTypeTuple Type Conversion CommonType AllImplicitConversionTargets ImplicitConversionTargets CopyTypeQualifiers CopyConstness isAssignable isCovariantWith isImplicitlyConvertible isQualifierConvertible Type Constructors InoutOf ConstOf SharedOf SharedInoutOf SharedConstOf SharedConstInoutOf ImmutableOf QualifierOf Categories of types allSameType ifTestable isType isAggregateType isArray isAssociativeArray isAutodecodableString isBasicType isBoolean isBuiltinType isCopyable isDynamicArray isEqualityComparable isFloatingPoint isIntegral isNarrowString isConvertibleToString isNumeric isOrderingComparable isPointer isScalarType isSigned isSIMDVector isSomeChar isSomeString isStaticArray isUnsigned Type behaviours isAbstractClass isAbstractFunction isCallable isDelegate isExpressions isFinalClass isFinalFunction isFunctionPointer isInstanceOf isIterable isMutable isSomeFunction isTypeTuple General Types ForeachType KeyType Largest mostNegative OriginalType PointerTarget Signed Unconst Unshared Unqual Unsigned ValueType Promoted Misc lvalueOf rvalueOf Select select User-Defined Attributes hasUDA getUDAs getSymbolsByUDA
Source
std/traits.d
traits : (alias template) property_tree_tree_adapter.hasUDA = std.traits.hasUDA(alias symbol, alias attribute)Determine if a symbol has a given
user-defined attribute.
hasUDA, (alias template) property_tree_tree_adapter.isAggregateType = std.traits.isAggregateType(T)Detect whether type T is an aggregate type.
isAggregateType, (alias template) property_tree_tree_adapter.isArray = std.traits.isArray(T)Detect whether type T is an array (static or dynamic; for associative
arrays see isAssociativeArray).
isArray, (alias template) property_tree_tree_adapter.isSomeString = std.traits.isSomeString(T)Detect whether T is one of the built-in string types.
The built-in string types are Char[], where Char is any of char,
wchar or dchar, with or without qualifiers.
Static arrays of characters (like char[80]) are not considered
built-in string types.
isSomeString;
import (package) sparklessparkles.(package) sparkles.uiui.(package) sparkles.ui.componentscomponents.(module) sparkles.ui.components.inspectorThe inspector component (INS, docs/specs/ui/inspector.md) — an interactive
tree of nodes over a subject, with a details pane for the selected node
and a selection contract that lets the host highlight the selected node's
extent in the subject.
The shape is the one every structure inspector shares — Chromium's Elements
panel, Visual Studio's Live Visual Tree, neovim's :InspectTree — and the
component is deliberately generic over it:
an adapter supplies the node model (a
TreeData whose T carries
the view's DbI capabilities — label, slot, badge, …) and, by
presence, a details(node) capability for the details pane;
the tree is the shared interactive component
(sparkles.ui.components.tree_view) — cursor, disclosure,
viewport, the works;
the selection contract is one value: the host reads
state.tree.selectedNode and asks its adapter what extent that node
covers (a layout rect for a widget tree, a byte range for a syntax
tree) — the component never learns what an extent is;
the header carries the title and a row of host-supplied toggle
actions (hover-sync on/off, anonymous nodes, …) as data, hit-testable
by the ids the host minted.
inspectWidgets is the first adapter: the toolkit looking at itself.
Any sparkles:ui application can mount an inspector over its own widget tree
and layout — the Live-Visual-Tree capability, natively.
writeTreeText is the plain-text target: the same flattened rows as
indented text with guide rails, for logging, golden tests, and terminals with
no interactivity at all.
inspector : (alias template) property_tree_tree_adapter.treeText = sparkles.ui.components.inspector.treeText(T)(in TreeData!T data, in FlatTreeRow[] rows, in TreeGlyphs glyphs = TreeGlyphs.init, scope bool delegate(uint) @safe isOpen = null)ditto — as one string.
treeText;
import (package) sparklessparkles.(package) sparkles.uiui.(package) sparkles.ui.componentscomponents.(module) sparkles.ui.components.tree_viewThe interactive tree view (TRV1–TRV7) — the interaction half of the tree
component, completing the three-layer split whose data and view halves live in
sparkles.ui.components.tree_widget:
data — TreeData, the flat
arena. Owned by the adapter, rebuilt at will.
interaction (TreeViewState) — the opened set, the cursor,
the viewport and both scrollbars, and the live filter's editor: every
piece of state a tree pane keeps between frames, as one value.
view — treeView over the
viewSlice window this state selects.
Before this module the interaction layer existed three times — hue's explorer
pane, hue's GUI re-implementation of the same pane, and the gallery's tree
page each carried their own copy of "move through the visible rows",
"left closes, then climbs", and the scrollbar-grab-owns-the-pointer pointer
arms. The behaviors here are those, stated once:
The cursor moves by visible row, never by arena index — pressing down
inside a closed folder cannot land on a node nobody can see.
TreeViewState.clamp couples the cursor and the viewport: the
cursor stays in view, and the view never shows dead space below the
last row.
collapseOrUp is the universal two-step Left: close an open
node, else climb to its parent's row.
A press on a scrollbar is a grab, never a row click, and the grab owns
the pointer until release wherever the drag strays (STM9's inverse
mapping, same as the viewer's).
The live filter is the one line-edit machine (STM13); every edit asks
the adapter to rebuild, because in broot's tree-as-search-result mode
the tree is a function of the query.
What is deliberately not here: the node model and its rebuild policy
(lazy children, filtering predicates, git decoration — the adapter's), and
painting (a host slices with viewSlice and paints through its own
canvas). Mutations that invalidate the visible rows return
TreeStep`.rebuild` rather than calling anything: the adapter owns
rebuilding, the state only reports that it is needed.
tree_view : (alias template) property_tree_tree_adapter.activate = sparkles.ui.components.tree_view.activate(Key, T, KeyOf)(ref TreeViewState!Key s, in TreeData!T data, scope KeyOf keyOf)Enter / a second click (TRV7): a node with children toggles its disclosure
(rebuild); a leaf reports activated — its meaning (open the file, pick
the CST node) is the adapter's. An adapter whose expandability is not
"has children" (an empty directory still toggles) supplies expandable.
activate, (alias template) property_tree_tree_adapter.collapseOrUp = sparkles.ui.components.tree_view.collapseOrUp(Key, T, KeyOf)(ref TreeViewState!Key s, in TreeData!T data, scope KeyOf keyOf)The universal two-step Left (TRV3): close the selected node when it is open,
else move the cursor to its parent's row. keyOf maps a node index to the
adapter's disclosure key.
Returns rebuild when the opened set changed (the adapter re-flattens),
handled otherwise.
collapseOrUp,
(alias template) property_tree_tree_adapter.measureContent = sparkles.ui.components.tree_view.measureContent(Key, T)(ref TreeViewState!Key s, in TreeData!T data)Recomputes the widest visible row in cells (contentCols) from the same
node capabilities the renderer reads: per-depth guide cells (3), the marker
column (3), the label, and a badge's two cells when one is present.
measureContent, (enum) sparkles.ui.components.tree_view.TreeStepWhat an interaction did, and what the caller owes it.
TreeStep, (alias struct) property_tree_tree_adapter.TreeViewState = sparkles.ui.components.tree_view.TreeViewState(Key)The tree pane's interaction state (VMD2 + the viewport): one value a host
embeds, keyed by the adapter's node identity Key (a path for a filesystem
tree, a node index for an in-memory one) so the opened set survives rebuilds.
sel/top index the visible rows, not the arena. rows is the cached
result of the adapter's last flatten — derived data stored here so every
motion and clamp can see how many rows exist without a callback.
TreeViewState;
import (package) sparklessparkles.(package) sparkles.uiui.(package) sparkles.ui.componentscomponents.(module) sparkles.ui.components.tree_widgetThe tree component (WGT12, VMD1–VMD6) — the exemplar of the
view-model/view split, built to the tree-view case study's three-layer design:
data (TreeData) — a flat node arena with parent/child/sibling
index links. No interaction state, no decoration: an independent
structural snapshot needs one explicit arena duplication. The current D
slice aliases under default copy (UI-O1), and T supplies its own copy
contract.
interaction — an opened set (DisclosureState), a selection, a scroll offset — lives beside
the data, keyed by identity, so one tree can back several independent
views.
view (treeView) — a pure function from both to a widget
subtree; owns glyphs and slots only.
flatten — hierarchy to the visible rows — is a pure free function
with no lazy loading and no filtering mixed in (the case study names mixing
them as the failure mode), and it precomputes the four-state guide model
(space / continue / fork / end) per depth level, so no renderer re-derives
rails per frame.
tree_widget : (alias template) property_tree_tree_adapter.flatten = sparkles.ui.components.tree_widget.flatten(T)(in TreeData!T data, scope bool delegate(uint) @safe isOpen)The flatten step (VMD3): hierarchy → the visible rows, honoring isOpen
(closed nodes keep their subtree out). Pure and free — no lazy loading, no
filtering — and the guides are computed here, once, from a per-depth
"has later siblings" accumulator (broot's precomputed rails).
flatten, (alias struct) property_tree_tree_adapter.TreeData = sparkles.ui.components.tree_widget.TreeData(T)The data layer (VMD1): a flat arena of T values with index links. add
appends under a parent (or as a root), maintaining sibling chains; there is no
remove — rebuild instead (flat storage is what makes per-keystroke rebuilding
viable, per the case study's tree-as-search-result mode).
TreeData, (struct) sparkles.ui.components.tree_widget.TreeGlyphsThe tree's charset — theme-glyph data with unicode defaults. All guide
cells are three columns wide, with one space between the connector and
the row's content. An adapter whose icons already express disclosure
(the explorer's open/closed folder) passes empty marker strings.
TreeGlyphs;
@safe:
enum (enum) property_tree_tree_adapter.readOnlyreadOnly;
/// The node value, carrying exactly the capabilities the existing views read:
/// `label`, `badge` — plus `expandable`, which `activate` already honours.
struct (struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode
{
(alias) object.string = stringstring (field) string property_tree_tree_adapter.PropNode.pathpath;
(alias) object.string = stringstring (field) string property_tree_tree_adapter.PropNode.labellabel;
(alias) object.string = stringstring (field) string property_tree_tree_adapter.PropNode.badgethe presented value; empty for composites
badge; /// the presented value; empty for composites
bool (field) bool property_tree_tree_adapter.PropNode.expandableexpandable;
bool (field) bool property_tree_tree_adapter.PropNode.editableeditable = true;
}
// ── the adapter ──────────────────────────────────────────────────────────────
/// NOTE (C24): the adapter does NOT store a pointer to the subject. Under
/// dip1000 a struct holding `T*` into a caller's stack becomes `scope`, and
/// every non-scope member call on it is then refused in `@safe` code. Taking
/// `ref T` per rebuild is both safer and simpler — and it matches the frame
/// model, where the subject is whatever the host has THIS frame.
struct (struct) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer)NOTE (C24): the adapter does NOT store a pointer to the subject. Under
dip1000 a struct holding T* into a caller's stack becomes scope, and
every non-scope member call on it is then refused in @safe code. Taking
ref T per rebuild is both safer and simpler — and it matches the frame
model, where the subject is whatever the host has THIS frame.
PropTree(T)
{
(struct) sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode)The data layer (VMD1): a flat arena of T values with index links. add
appends under a parent (or as a root), maintaining sibling chains; there is no
remove — rebuild instead (flat storage is what makes per-keystroke rebuilding
viable, per the case study's tree-as-search-result mode).
TreeData!(struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode (field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata;
(struct) sparkles.ui.components.tree_view.TreeViewState!stringThe tree pane's interaction state (VMD2 + the viewport): one value a host
embeds, keyed by the adapter's node identity Key (a path for a filesystem
tree, a node index for an in-memory one) so the opened set survives rebuilds.
sel/top index the visible rows, not the arena. rows is the cached
result of the adapter's last flatten — derived data stored here so every
motion and clamp can see how many rows exist without a callback.
TreeViewState!(alias) object.string = stringstring (field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate;
int (field) int property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).maxDepthmaxDepth = 16;
void void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).rebuild(ref property_tree_tree_adapter.Layer subject) @saferebuild(ref (alias) T = property_tree_tree_adapter.LayerT (parameter) property_tree_tree_adapter.Layer subjectsubject)
{
(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata = (template instance) sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode)TreeData!(struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode.(constant) sparkles.ui.components.tree_widget.TreeData!(PropNode) sparkles.ui.components.tree_widget.TreeData!(PropNode).init = TreeData(null, 4294967295u)init;
void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Layer)(ref property_tree_tree_adapter.Layer v, uint parent, string prefix, int depth) pure @safewalk((parameter) property_tree_tree_adapter.Layer subjectsubject, uint.(constant) uint uint.max = 4294967295umax, "", 0);
(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.components.tree_widget.FlatTreeRow[] sparkles.ui.components.tree_view.TreeViewState!string.rowsThe visible rows, as the adapter last rebuilt them.
rows = sparkles.ui.components.tree_widget.FlatTreeRow[] sparkles.ui.components.tree_widget.flatten!(property_tree_tree_adapter.PropNode)(in sparkles.ui.components.tree_widget.TreeData!(PropNode) data, scope bool delegate(uint) @safe isOpen) @safeThe flatten step (VMD3): hierarchy → the visible rows, honoring isOpen
(closed nodes keep their subtree out). Pure and free — no lazy loading, no
filtering — and the guides are computed here, once, from a per-depth
"has later siblings" accumulator (broot's precomputed rails).
flatten!(struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode((field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata, (uint (parameter) uint nn) => bool property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).isOpen(uint node) const pure nothrow @nogc @safeisOpen((parameter) uint nn));
(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.void sparkles.ui.components.tree_view.measureContent!(string, property_tree_tree_adapter.PropNode)(ref sparkles.ui.components.tree_view.TreeViewState!string s, in sparkles.ui.components.tree_widget.TreeData!(PropNode) data) pure nothrow @nogc @safeRecomputes the widest visible row in cells (contentCols) from the same
node capabilities the renderer reads: per-depth guide cells (3), the marker
column (3), the label, and a badge's two cells when one is present.
measureContent((field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata);
(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.void sparkles.ui.components.tree_view.TreeViewState!string.clamp() pure nothrow @nogc @safeCouples cursor and viewport: the cursor stays valid and in view, and
the view never leaves dead space below the last row (a reveal before
the pane had its real height can overshoot; the next sized clamp
pulls back).
clamp();
}
bool bool property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).isOpen(uint node) const pure nothrow @nogc @safeisOpen(uint (parameter) uint nodenode) const => (field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.bool sparkles.ui.state.DisclosureState!string.isOpen(in string k) const pure nothrow @nogc @safetrue iff k is open under the current polarity + exceptions.
isOpen((field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode).Node[] sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).nodesnodes[(parameter) uint nodenode].(field) property_tree_tree_adapter.PropNode sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).Node.valuevalue.(field) string property_tree_tree_adapter.PropNode.pathpath);
(alias) object.string = stringstring string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).keyOf(uint node) const pure nothrow @nogc @safekeyOf(uint (parameter) uint nodenode) const => (field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode).Node[] sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).nodesnodes[(parameter) uint nodenode].(field) property_tree_tree_adapter.PropNode sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).Node.valuevalue.(field) string property_tree_tree_adapter.PropNode.pathpath;
private void void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke)(ref property_tree_tree_adapter.Stroke v, uint parent, string prefix, int depth) pure @safewalk(U)(ref (alias) U = property_tree_tree_adapter.StrokeU (parameter) property_tree_tree_adapter.Stroke vv, uint (parameter) uint parentparent, (alias) object.string = stringstring (parameter) string prefixprefix, int (parameter) int depthdepth)
{
static foreach (name; __traits(allMembers, U))
{{
alias (alias field) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke).M = double property_tree_tree_adapter.Stroke.widthM = __traits(getMember, U, name);
static if (__traits(compiles, typeof((field) double property_tree_tree_adapter.Stroke.widthM)) && !is(typeof((field) double property_tree_tree_adapter.Stroke.widthM) == function))
{{
alias (alias) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke).F = doubleF = typeof((field) double property_tree_tree_adapter.Stroke.widthM);
const (local variable) const(string) pathpath = (parameter) string prefixprefix.(field) ulong string.lengthlength ? (parameter) string prefixprefix ~ "." ~ name : (constant) string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke).name = "width"name;
static if ((template instance) std.traits.isAggregateType!doubleisAggregateType!(alias) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke).F = doubleF && !(template instance) isSomeString!FisSomeString!(alias) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Layer).F = property_tree_tree_adapter.StrokeF)
{
const (local variable) const(uint) nodenode = (field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.uint sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).add(property_tree_tree_adapter.PropNode value, uint parent = 4294967295u) pure nothrow @safeAppends value under parent (uint.max = a new root); returns its index.
add((struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode((local variable) const(string) pathpath, (constant) string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Layer).name = "stroke"name, "", true,
!(template instance) property_tree_tree_adapter.Layer.hasUDA!(stroke, property_tree_tree_adapter.readOnly)hasUDA!((field) property_tree_tree_adapter.Stroke property_tree_tree_adapter.Layer.strokeM, (enum) property_tree_tree_adapter.readOnlyreadOnly)), (parameter) uint parentparent);
if ((field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.bool sparkles.ui.state.DisclosureState!string.isOpen(in string k) const pure nothrow @nogc @safetrue iff k is open under the current polarity + exceptions.
isOpen((local variable) const(string) pathpath) && (parameter) int depthdepth + 1 < (field) int property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).maxDepthmaxDepth)
walk(__traits(getMember, v, name), (local variable) const(uint) nodenode, (local variable) const(string) pathpath, (parameter) int depthdepth + 1);
}
else static if ((template instance) std.traits.isArray!doubleisArray!(alias) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke).F = doubleF && !(template instance) isSomeString!FisSomeString!(alias) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Layer).F = stringF)
{
auto ref (local variable) int[] arrarr = __traits(getMember, v, name);
const (local variable) const(uint) nodenode = (field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.uint sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).add(property_tree_tree_adapter.PropNode value, uint parent = 4294967295u) pure nothrow @safeAppends value under parent (uint.max = a new root); returns its index.
add((struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode((local variable) const(string) pathpath, (constant) string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Layer).name = "dashes"name,
string std.conv.text!(string, ulong, string)(string __param_0, ulong __param_1, string __param_2) pure nothrow @safeConvenience functions for converting one or more arguments
of any type into text (the three character widths).
text("[", (local variable) int[] arrarr.(field) ulong int[].lengthlength, "]"), (local variable) int[] arrarr.(field) ulong int[].lengthlength > 0,
!(template instance) property_tree_tree_adapter.Layer.hasUDA!(dashes, property_tree_tree_adapter.readOnly)hasUDA!((field) int[] property_tree_tree_adapter.Layer.dashesM, (enum) property_tree_tree_adapter.readOnlyreadOnly)), (parameter) uint parentparent);
if ((field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.bool sparkles.ui.state.DisclosureState!string.isOpen(in string k) const pure nothrow @nogc @safetrue iff k is open under the current polarity + exceptions.
isOpen((local variable) const(string) pathpath) && (parameter) int depthdepth + 1 < (field) int property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).maxDepthmaxDepth)
foreach ((parameter) ulong ii, ref (parameter) int ee; (local variable) int[] arrarr)
{
const (local variable) const(string) epep = (local variable) const(string) pathpath ~ "[" ~ (local variable) ulong ii.string std.conv.to!string.to!ulong(ulong __param_0) pure nothrow @safeThe 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 ~ "]";
(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.uint sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).add(property_tree_tree_adapter.PropNode value, uint parent = 4294967295u) pure nothrow @safeAppends value under parent (uint.max = a new root); returns its index.
add((struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode((local variable) const(string) epep, "[" ~ (local variable) ulong ii.string std.conv.to!string.to!ulong(ulong __param_0) pure nothrow @safeThe 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 ~ "]",
string std.conv.text!int(int __param_0) pure nothrow @safeConvenience functions for converting one or more arguments
of any type into text (the three character widths).
text((local variable) int ee), false, !(template instance) property_tree_tree_adapter.Layer.hasUDA!(dashes, property_tree_tree_adapter.readOnly)hasUDA!((field) int[] property_tree_tree_adapter.Layer.dashesM, (enum) property_tree_tree_adapter.readOnlyreadOnly)), (local variable) const(uint) nodenode);
}
}
else
(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.uint sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).add(property_tree_tree_adapter.PropNode value, uint parent = 4294967295u) pure nothrow @safeAppends value under parent (uint.max = a new root); returns its index.
add((struct) property_tree_tree_adapter.PropNodeThe node value, carrying exactly the capabilities the existing views read:
label, badge — plus expandable, which activate already honours.
PropNode((local variable) const(string) pathpath, (constant) string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).walk!(property_tree_tree_adapter.Stroke).name = "width"name,
string std.conv.text!double(double __param_0) pure @safeConvenience functions for converting one or more arguments
of any type into text (the three character widths).
text(__traits(getMember, v, name)), false,
!(template instance) property_tree_tree_adapter.Stroke.hasUDA!(width, property_tree_tree_adapter.readOnly)hasUDA!((field) double property_tree_tree_adapter.Stroke.widthM, (enum) property_tree_tree_adapter.readOnlyreadOnly)), (parameter) uint parentparent);
}}
}}
}
}
// ── the subject ──────────────────────────────────────────────────────────────
enum (enum) property_tree_tree_adapter.CapCap { (enum value) property_tree_tree_adapter.Cap.butt = 0butt, (enum value) property_tree_tree_adapter.Cap.round = 1round }
struct (struct) property_tree_tree_adapter.StrokeStroke { double (field) double property_tree_tree_adapter.Stroke.widthwidth = 1; (enum) property_tree_tree_adapter.CapCap (field) property_tree_tree_adapter.Cap property_tree_tree_adapter.Stroke.capcap; }
struct (struct) property_tree_tree_adapter.LayerLayer
{
(alias) object.string = stringstring (field) string property_tree_tree_adapter.Layer.namename = "layer";
bool (field) bool property_tree_tree_adapter.Layer.visiblevisible = true;
(struct) property_tree_tree_adapter.StrokeStroke (field) property_tree_tree_adapter.Stroke property_tree_tree_adapter.Layer.strokestroke;
int[] (field) int[] property_tree_tree_adapter.Layer.dashesdashes;
@(enum) property_tree_tree_adapter.readOnlyreadOnly ulong (field) ulong property_tree_tree_adapter.Layer.idid = 42;
}
// ── driving a session ────────────────────────────────────────────────────────
void void D main() @safemain()
{
import (package) stdstd.(module) std.stdioCategory Symbols File handles _popen File isFileHandle openNetwork stderr stdin stdout Reading chunks lines readf readfln readln Writing toFile write writef writefln writeln Misc KeepTerminator LockType StdioException
Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio
is publically imported when importing std.stdio.
There are three layers of I/O:
The lowest layer is the operating system layer. The two main schemes are Windows and Posix.
C's stdio.h which unifies the two operating system schemes.
std.stdio, this module, unifies the various stdio.h implementations into
a high level package for D programs.
Source
std/stdio.d
stdio : (alias template) write = std.stdio.write(T...)(T args) if (!is(T[0] : File))Writes its arguments in text format to standard output (without a trailing newline).
Params:
args = the items to write to stdout
Throws: In case of an I/O error, throws an StdioException.
Example:
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
write("Input ", count, ": ", line, "\n");
}
}
---
write, (alias template) writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))Equivalent to $(D writef(fmt, args, '\n')).
writefln, (alias template) writeln = std.stdio.writeln(T...)(T args)Equivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Params:
args = the items to write to stdout
Throws:
In case of an I/O error, throws an $(LREF StdioException).
Example:
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
---
writeln;
(struct) property_tree_tree_adapter.LayerLayer (local variable) property_tree_tree_adapter.Layer ll;
(local variable) property_tree_tree_adapter.Layer ll.(field) int[] property_tree_tree_adapter.Layer.dashesdashes = [4, 2];
(struct) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer)NOTE (C24): the adapter does NOT store a pointer to the subject. Under
dip1000 a struct holding T* into a caller's stack becomes scope, and
every non-scope member call on it is then refused in @safe code. Taking
ref T per rebuild is both safer and simpler — and it matches the frame
model, where the subject is whatever the host has THIS frame.
PropTree!(struct) property_tree_tree_adapter.LayerLayer (local variable) property_tree_tree_adapter.PropTree!(Layer) tt;
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) int sparkles.ui.components.tree_view.TreeViewState!string.widthPane geometry: outer size, and rows of pane chrome outside the tree
(header + status/details; a chromeless pane sets 0). Prefer
resize over assigning height: a pane that GREW must not
scroll its content up to stay flush with the bottom.
width = 40;
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) int sparkles.ui.components.tree_view.TreeViewState!string.heightPane geometry: outer size, and rows of pane chrome outside the tree
(header + status/details; a chromeless pane sets 0). Prefer
resize over assigning height: a pane that GREW must not
scroll its content up to stay flush with the bottom.
height = 14;
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).rebuild(ref property_tree_tree_adapter.Layer subject) @saferebuild((local variable) property_tree_tree_adapter.Layer ll);
void void property_tree_tree_adapter.main.show(string what) @safeshow((alias) object.string = stringstring (parameter) string whatwhat)
{
void std.stdio.writefln!(char, string, long, ulong)(in char[] fmt, string __param_1, long __param_2, ulong __param_3) @safeEquivalent to writef(fmt, args, '\n').
writefln("\n── %s (cursor=%s, rows=%s) ─────────", (parameter) string whatwhat, (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) long sparkles.ui.components.tree_view.TreeViewState!string.selCursor row and first visible row (indices into rows).
sel,
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.components.tree_widget.FlatTreeRow[] sparkles.ui.components.tree_view.TreeViewState!string.rowsThe visible rows, as the adapter last rebuilt them.
rows.(field) ulong sparkles.ui.components.tree_widget.FlatTreeRow[].lengthlength);
void std.stdio.write!string(string __param_0) @safeWrites its arguments in text format to standard output (without a trailing newline).
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
write("Input ", count, ": ", line, "\n");
}
}
write(string sparkles.ui.components.inspector.treeText!(property_tree_tree_adapter.PropNode)(in sparkles.ui.components.tree_widget.TreeData!(PropNode) data, in sparkles.ui.components.tree_widget.FlatTreeRow[] rows, in sparkles.ui.components.tree_widget.TreeGlyphs glyphs = TreeGlyphs("\xe2\x94\x9c\xe2\x94\x80 ", "\xe2\x94\x94\xe2\x94\x80 ", "\xe2\x94\x82 ", " ", "\xe2\x96\xb8 ", "\xe2\x96\xbe ", ""), scope bool delegate(uint) @safe isOpen = cast(bool delegate(uint) @safe)null) @safeditto — as one string.
treeText((local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata, (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.components.tree_widget.FlatTreeRow[] sparkles.ui.components.tree_view.TreeViewState!string.rowsThe visible rows, as the adapter last rebuilt them.
rows));
}
void property_tree_tree_adapter.main.show(string what) @safeshow("closed");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("\nC20/C22 — Enter on `stroke`: `activate` reads `expandable` from");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" the node value, so a not-yet-materialised composite");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" still toggles. It returns rebuild; the adapter obeys.");
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.void sparkles.ui.components.tree_view.TreeViewState!string.moveSel(long dy) pure nothrow @nogc @safeMoves the cursor by dy visible rows (±1 step, ±bodyRows page),
keeping it in view.
moveSel(2); // → stroke
auto (local variable) sparkles.ui.components.tree_view.TreeStep stepstep = sparkles.ui.components.tree_view.TreeStep sparkles.ui.components.tree_view.activate!(string, property_tree_tree_adapter.PropNode, string delegate(uint) pure nothrow @nogc @safe)(ref sparkles.ui.components.tree_view.TreeViewState!string s, in sparkles.ui.components.tree_widget.TreeData!(PropNode) data, scope string delegate(uint) pure nothrow @nogc @safe keyOf) pure nothrow @safeEnter / a second click (TRV7): a node with children toggles its disclosure
(rebuild); a leaf reports activated — its meaning (open the file, pick
the CST node) is the adapter's. An adapter whose expandability is not
"has children" (an empty directory still toggles) supplies expandable.
activate((local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate, (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata, (uint (parameter) uint nn) => (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).keyOf(uint node) const pure nothrow @nogc @safekeyOf((parameter) uint nn));
void std.stdio.writefln!(char, sparkles.ui.components.tree_view.TreeStep, string)(in char[] fmt, sparkles.ui.components.tree_view.TreeStep __param_1, string __param_2) @safeEquivalent to writef(fmt, args, '\n').
writefln(" activate → %s key = %s", (local variable) sparkles.ui.components.tree_view.TreeStep stepstep, (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).keyOf(uint node) const pure nothrow @nogc @safekeyOf((local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.uint sparkles.ui.components.tree_view.TreeViewState!string.selectedNode() const pure nothrow @nogc @safeThe selected row's node, or uint.max when there is none.
selectedNode));
if ((local variable) sparkles.ui.components.tree_view.TreeStep stepstep == (enum) sparkles.ui.components.tree_view.TreeStepWhat an interaction did, and what the caller owes it.
TreeStep.(enum value) sparkles.ui.components.tree_view.TreeStep.rebuild = 2consumed; the opened set or filter changed — rebuild rows
rebuild) (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).rebuild(ref property_tree_tree_adapter.Layer subject) @saferebuild((local variable) property_tree_tree_adapter.Layer ll);
void property_tree_tree_adapter.main.show(string what) @safeshow("stroke open");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("\nC22 — the gap: Left on the SAME node. `collapseOrUp` asks");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" `data.hasChildren`, which is structural, so it closes only");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" because the children happen to be materialised now:");
const (local variable) const(bool) beforebefore = (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.bool sparkles.ui.state.DisclosureState!string.isOpen(in string k) const pure nothrow @nogc @safetrue iff k is open under the current polarity + exceptions.
isOpen("stroke");
(local variable) sparkles.ui.components.tree_view.TreeStep stepstep = sparkles.ui.components.tree_view.TreeStep sparkles.ui.components.tree_view.collapseOrUp!(string, property_tree_tree_adapter.PropNode, string delegate(uint) pure nothrow @nogc @safe)(ref sparkles.ui.components.tree_view.TreeViewState!string s, in sparkles.ui.components.tree_widget.TreeData!(PropNode) data, scope string delegate(uint) pure nothrow @nogc @safe keyOf) pure nothrow @safeThe universal two-step Left (TRV3): close the selected node when it is open,
else move the cursor to its parent's row. keyOf maps a node index to the
adapter's disclosure key.
Returns rebuild when the opened set changed (the adapter re-flattens),
handled otherwise.
collapseOrUp((local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate, (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata, (uint (parameter) uint nn) => (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).keyOf(uint node) const pure nothrow @nogc @safekeyOf((parameter) uint nn));
void std.stdio.writefln!(char, sparkles.ui.components.tree_view.TreeStep, const(bool), bool)(in char[] fmt, sparkles.ui.components.tree_view.TreeStep __param_1, const(bool) __param_2, bool __param_3) @safeEquivalent to writef(fmt, args, '\n').
writefln(" collapseOrUp → %s stroke open: %s → %s", (local variable) sparkles.ui.components.tree_view.TreeStep stepstep, (local variable) const(bool) beforebefore,
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.bool sparkles.ui.state.DisclosureState!string.isOpen(in string k) const pure nothrow @nogc @safetrue iff k is open under the current polarity + exceptions.
isOpen("stroke"));
if ((local variable) sparkles.ui.components.tree_view.TreeStep stepstep == (enum) sparkles.ui.components.tree_view.TreeStepWhat an interaction did, and what the caller owes it.
TreeStep.(enum value) sparkles.ui.components.tree_view.TreeStep.rebuild = 2consumed; the opened set or filter changed — rebuild rows
rebuild) (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).rebuild(ref property_tree_tree_adapter.Layer subject) @saferebuild((local variable) property_tree_tree_adapter.Layer ll);
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" With the node CLOSED, its children are gone, so a second");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" Left cannot distinguish `stroke` from a leaf — it climbs to");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" the parent instead. `collapseOrUp` needs the same");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln(" `expandable` capability `activate` already has.");
void std.stdio.writeln!string(string __param_0) @safeEquivalent to write(args, '\n'). Calling writeln without
arguments is valid and just prints a newline to the standard
output.
Example
Reads stdin and writes it to stdout with an argument
counter.
import std.stdio;
void main()
{
string line;
for (size_t count = 0; (line = readln) !is null; count++)
{
writeln("Input ", count, ": ", line);
}
}
writeln("\nC21/C23 — open two nodes, move the cursor, then EDIT:");
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open = (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.sparkles.ui.state.DisclosureState!string sparkles.ui.state.DisclosureState!string.opened(string k) const pure nothrow @safeThis state with k forced open / closed.
opened("stroke").sparkles.ui.state.DisclosureState!string sparkles.ui.state.DisclosureState!string.opened(string k) const pure nothrow @safeThis state with k forced open / closed.
opened("dashes");
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).rebuild(ref property_tree_tree_adapter.Layer subject) @saferebuild((local variable) property_tree_tree_adapter.Layer ll);
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) long sparkles.ui.components.tree_view.TreeViewState!string.selCursor row and first visible row (indices into rows).
sel = 4;
void property_tree_tree_adapter.main.show(string what) @safeshow("two open, cursor on stroke.cap");
(local variable) property_tree_tree_adapter.Layer ll.(field) property_tree_tree_adapter.Stroke property_tree_tree_adapter.Layer.strokestroke.(field) double property_tree_tree_adapter.Stroke.widthwidth = 3.5; // an edit lands ([`edit-commands.d`](./edit-commands.d))
(local variable) property_tree_tree_adapter.Layer ll.(field) int[] property_tree_tree_adapter.Layer.dashesdashes = [8, 4, 1]; // and a structural one
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.void property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).rebuild(ref property_tree_tree_adapter.Layer subject) @saferebuild((local variable) property_tree_tree_adapter.Layer ll);
void property_tree_tree_adapter.main.show(string what) @safeshow("after the edit — badges refreshed, expansion and cursor kept");
void std.stdio.writefln!(char, string[])(in char[] fmt, string[] __param_1) @safeEquivalent to writef(fmt, args, '\n').
writefln("\n opened set survived as data: %s", (local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.state.DisclosureState!string sparkles.ui.components.tree_view.TreeViewState!string.openUser intent (VMD5): which nodes should be open, keyed by identity.
open.(field) string[] sparkles.ui.state.DisclosureState!string.exceptionsSorted, unique keys that differ from the default.
exceptions);
void std.stdio.writefln!(char, bool)(in char[] fmt, bool __param_1) @safeEquivalent to writef(fmt, args, '\n').
writefln(" read-only field is marked: id.editable = %s",
(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode) property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).datadata.(field) sparkles.ui.components.tree_widget.TreeData!(PropNode).Node[] sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).nodesnodes[(local variable) property_tree_tree_adapter.PropTree!(Layer) tt.(field) sparkles.ui.components.tree_view.TreeViewState!string property_tree_tree_adapter.PropTree!(property_tree_tree_adapter.Layer).statestate.(field) sparkles.ui.components.tree_widget.FlatTreeRow[] sparkles.ui.components.tree_view.TreeViewState!string.rowsThe visible rows, as the adapter last rebuilt them.
rows[$ - 1].(field) uint sparkles.ui.components.tree_widget.FlatTreeRow.nodenode].(field) property_tree_tree_adapter.PropNode sparkles.ui.components.tree_widget.TreeData!(property_tree_tree_adapter.PropNode).Node.valuevalue.(field) bool property_tree_tree_adapter.PropNode.editableeditable);
}