5.3 Iterators and Copies¶
This chapter explains the difference between array placement and row iteration, and how both interact with card quantity in column A.
5.3.1 Why this matters¶
At first sight, these two expressions look similar:
[id1 id2 ... idn]
*[id1 id2 ... idn]
They are not equivalent. The first builds one composite placement inside one generated card. The second expands the dataset row into multiple generated cards, one per iterator value.
5.3.2 Array Without Iterator ([ ... ])¶
When a non-text field uses:
[id1 id2 ... idn]
PnPInk treats it as an array/group target for that field in the current card instance. All listed items are processed in the same row instance.
This is useful when you want several IDs resolved together in one card, and optionally apply local array layout/fit behavior.
Wildcard IDs are supported inside arrays:
[main_icon-*]
This expands to all matching IDs and keeps array/list semantics (single card instance).
Array repetition shorthand is also supported:
[3*:Ic(potato)]~i2
Equivalent to writing the same token three times in the list.
Grouped repetition is also supported with parentheses:
[id1 - 3*(id2 3- 3*id3) 4- id4]
Parentheses are grouping operators inside list/array bodies, so you can repeat a block as one unit.
5.3.3 Iterator (*...)¶
When a cell starts with *, it becomes an iterator expression.
*[id1 id2 ... idn]
Result:
- the row is expanded into multiple internal instances,
- each generated card gets one iterator value at that cell,
- by default (without explicit copies), generated cards count equals iterator length.
Conceptually: one different card per value.
Parentheses inside iterator lists¶
Inside *[ ... ], parentheses define one grouped iterator item (multivalue in the same generated card instance):
*[id1 id2 id3]
This iterates 3 scalar items (id1, then id2, then id3).
*[id1 (id2 id3)]
This iterates 2 items:
- first iteration:
id1 - second iteration:
id2 id3(multivalue group in the same card)
So *[id1 id2 id3] and *[id1 (id2 id3)] are intentionally different.
Group repetition also works:
*[id1 2*(id2 id3)]
Equivalent iterator sequence: id1, (id2 id3), (id2 id3).
Wildcard IDs are also supported in scalar/multivalue cells:
main_icon-*
Outside [ ... ], wildcard expansion behaves as multivalue (same card instance, token sequence order).
5.3.4 Multi-Level Iteration (*, **, ***)¶
PnPInk supports multiple iterator levels using leading stars.
*[A B C]
**[1 2]
This produces a nested expansion (cartesian-style): every level-1 value is combined with every level-2 value.
You can add more levels (***, etc.) when needed.
5.3.5 Supported Iterator Expressions¶
Current parser supports iterator payloads such as:
- bracket list/range:
*[1 2 3],*[1..10],*[A..F], - virtual sources with selectors,
- filesystem glob through
*@{...}, - spritesheet wildcard alias:
*@alias[*].
If an iterator resolves to zero values, that row yields zero generated instances.
5.3.6 Copies in Column A (Card Quantity)¶
Column A can declare explicit quantity (copies) for a row. With iterators, behavior is:
- No explicit copies in column A: Iterator count defines card count.
- Explicit copies in column A and copies > iterator count: Iterator values wrap around.
- Explicit copies in column A and copies < iterator count: Iterator sequence is truncated.
This gives predictable control when you need either:
- one card per iterator value,
- or a fixed number of cards regardless of iterator length.
5.3.7 Examples¶
One card with grouped IDs¶
art = [icon_fire icon_air icon_earth]
Interpretation: one row instance, one generated card, grouped placement in that card.
One card per ID¶
art = *[icon_fire icon_air icon_earth]
Interpretation: three generated cards from that row (unless column A copies overrides).
Iterator + explicit copies¶
Column A: 5
art = *[A B C]
Interpretation: 5 cards -> A, B, C, A, B (wrap).
Column A: 2
art = *[A B C]
Interpretation: 2 cards -> A, B (truncate).