Harden \stgroup and tighten the callout budget (review follow-up)
- Bracket ink is part of the fit: \st@facebody drops -inkw/-inke extreme coordinates and \stface/\ststack register them with the enclosing group/col/row fit, so a group outline can no longer be crossed by a member's bracket arms - \stlink inside \stgroup or \stcol is now a package error: sub-flow members never terminate a pending connector, so the arrow was dropped silently while the label still rendered - \stgroup requires role= (explicit role=neutral for mixed groups) and must bind at least two members or one \stcol partition; a lone stack or face inside a group is a dirty-build warning - lint: default budget is one \stcallout per figure; the allow-multiple-callouts directive relaxes it to one per band - build.sh: clean-build hint no longer names hue budget (lint owns it) - tests/group-callout.tex reworked: multi-member group with a bracketed member as a regression probe, single callout; new negative fixtures group-link, group-norole, group-single, callout-budget - api.md, checklist.md, style.md, layout.md, SKILL.md updated to match
This commit is contained in:
@@ -52,7 +52,7 @@ shape or convention you inferred.
|
||||
| data movement, collectives, non-linear ops | arrows and nodes | `\stlink`, `\stcomm` |
|
||||
| a split along the contracted axis | a vertical pair inside one band slot | `\stcol` … `\stcolend` |
|
||||
| adjacent objects that are one composite (heads of `q`, shards of `W`) | an outline in their own role hue | `\stgroup` … `\stgroupend` |
|
||||
| an aside about a whole band | a side card off its right edge, one per band | `\stcallout` |
|
||||
| an aside about a whole band | a side card off its right edge, one per figure | `\stcallout` |
|
||||
|
||||
Combine grammars only when each one adds information. Known zeros stay unfilled; masks,
|
||||
diagonals, sparsity and partitions must encode their exact structure.
|
||||
|
||||
+53
-2
@@ -146,6 +146,8 @@
|
||||
\newif\ifst@incol
|
||||
\newif\ifst@ingroup
|
||||
\newif\ifst@first
|
||||
\newcount\st@gcount % members registered by the open group
|
||||
\newif\ifst@ghascol % the open group contains a \stcol partition
|
||||
|
||||
\newcommand{\stlayoutreset}{%
|
||||
\global\st@railx=0pt \global\st@ycur=0pt
|
||||
@@ -176,11 +178,21 @@
|
||||
\xdef\st@collist{\st@collist(#1)}\st@regall{#1}%
|
||||
\else\ifst@ingroup
|
||||
\xdef\st@grouplist{\st@grouplist(#1)}\st@regall{#1}%
|
||||
\global\advance\st@gcount by 1
|
||||
\else
|
||||
\xdef\st@rowlist{\st@rowlist(#1)}\st@regall{#1}%
|
||||
\st@drawpendinglink{#1}%
|
||||
\gdef\st@lastnode{#1}%
|
||||
\fi\fi}
|
||||
% Bracket arms are drawn OUTSIDE the node box, so a fit over the node alone is
|
||||
% smaller than the ink. Register the bracket's extreme coordinates with
|
||||
% whatever fit will enclose the node, or a group outline (pad 1.6mm, overhang
|
||||
% 2.2mm) is crossed by the bracket it claims to contain.
|
||||
\newcommand{\st@regink}[1]{%
|
||||
\ifst@incol \xdef\st@collist{\st@collist#1}%
|
||||
\else\ifst@ingroup \xdef\st@grouplist{\st@grouplist#1}%
|
||||
\else \xdef\st@rowlist{\st@rowlist#1}%
|
||||
\fi\fi}
|
||||
|
||||
\newcommand{\st@needrow}[1]{%
|
||||
\ifst@inrow\else
|
||||
@@ -294,6 +306,7 @@
|
||||
Fix the height in \string\stcol}%
|
||||
\fi
|
||||
\st@checkh{\st@colname}{\the\dimen0}%
|
||||
\ifst@ingroup\global\st@ghascoltrue\fi
|
||||
\st@regrow{\st@colname}}}
|
||||
|
||||
% A node in the flow: an operator glyph, a collective, a note. It reserves its
|
||||
@@ -324,6 +337,19 @@
|
||||
% right-hand one exists, so a label can never be wider than its connector.
|
||||
\newcommand{\stlink}[2]{%
|
||||
\st@needrow{\stlink}%
|
||||
% Sub-flow members never terminate a pending connector (\st@regrow), so a
|
||||
% link opened inside one would build cleanly and draw no arrow at all.
|
||||
\ifst@ingroup
|
||||
\PackageError{supertensor}{\string\stlink\space inside \string\stgroup}%
|
||||
{A group member cannot terminate a connector, so the arrow would be
|
||||
dropped silently. Close the group first; the link then attaches to the
|
||||
outline itself.}%
|
||||
\fi
|
||||
\ifst@incol
|
||||
\PackageError{supertensor}{\string\stlink\space inside \string\stcol}%
|
||||
{A column item cannot terminate a connector. Close the column first;
|
||||
the link then attaches to the column as a whole.}%
|
||||
\fi
|
||||
\xdef\st@linkprev{\st@lastnode}%
|
||||
\ifblank{#2}%
|
||||
{\gdef\st@linklabel{}\stgap{\stlinklen}}%
|
||||
@@ -507,6 +533,7 @@
|
||||
\st@flowbegin{#2}{\st@tw}{\st@h}%
|
||||
\edef\st@do{\noexpand\st@facecore{#2}{\st@pos}}\st@do
|
||||
\st@regrow{#2}%
|
||||
\ifst@bracket\st@regink{(#2-inkw)(#2-inke)}\fi
|
||||
}{\st@facecore{#2}{#3}}%
|
||||
\endgroup}
|
||||
|
||||
@@ -587,6 +614,10 @@
|
||||
\draw[black!55, line width=0.5pt]
|
||||
($(#1.north east)+(1.1mm,0.6mm)$) -- ++(1.1mm,0)
|
||||
-- ($(#1.south east)+(2.2mm,-0.6mm)$) -- ++(-1.1mm,0);
|
||||
% The true ink extent, for \st@regink: fits over the bare node undershoot
|
||||
% the bracket by 2.2mm horizontally and 0.6mm vertically.
|
||||
\coordinate (#1-inkw) at ($(#1.south west)+(-2.2mm,-0.6mm)$);
|
||||
\coordinate (#1-inke) at ($(#1.north east)+(2.2mm,0.6mm)$);
|
||||
\fi}
|
||||
|
||||
% \st@tile{face}{row}{col}{level} -- one rounded tile with a white gutter.
|
||||
@@ -633,7 +664,8 @@
|
||||
\node[inner sep=0pt, outer sep=0pt,
|
||||
fit={(#2-front) ($(#2-front.north east)+(\st@back*\st@dx,\st@back*\st@dx)$)}]
|
||||
(#2) {};
|
||||
\ifblank{#3}{\st@regrow{#2}}{}%
|
||||
\ifblank{#3}{\st@regrow{#2}%
|
||||
\ifst@bracket\st@regink{(#2-front-inkw)(#2-front-inke)}\fi}{}%
|
||||
\endgroup}
|
||||
|
||||
% ------------------------------------------------------------- grouping ----
|
||||
@@ -657,7 +689,10 @@
|
||||
/st/group/.cd,
|
||||
role/.store in=\st@grole,
|
||||
pad/.store in=\st@gpad,
|
||||
role=neutral, pad=\stgrouppad,
|
||||
% No default role on purpose: a homogeneous group silently drawn in neutral
|
||||
% gray violates the "outline in the composite's own hue" rule without any
|
||||
% signal. A genuinely mixed group passes role=neutral explicitly.
|
||||
role={}, pad=\stgrouppad,
|
||||
}
|
||||
\newcommand{\stgroup}[2][]{%
|
||||
\st@needrow{\stgroup}%
|
||||
@@ -671,6 +706,11 @@
|
||||
the whole \string\stcol\space in the group instead.}%
|
||||
\fi
|
||||
\pgfkeys{/st/group/.cd,#1}%
|
||||
\ifdefempty{\st@grole}{%
|
||||
\PackageError{supertensor}{\string\stgroup\space `#2' has no role}%
|
||||
{The outline is drawn in the hue of the composite it names. Pass
|
||||
role=<declared role>, or role=neutral explicitly for a mixed group.}%
|
||||
\def\st@grole{neutral}}{}%
|
||||
\stcheckrole{\st@grole}%
|
||||
% Snapshot everything the closing macro needs: the keys are re-read by the
|
||||
% next face and the role ledger lookup must not be deferred.
|
||||
@@ -680,6 +720,7 @@
|
||||
\st@leadgap{\stgutter}%
|
||||
\global\advance\st@cx by \dimexpr\st@gpad\relax
|
||||
\gdef\st@grouplist{}%
|
||||
\global\st@gcount=0 \global\st@ghascolfalse
|
||||
\global\st@ingrouptrue\global\st@firsttrue}
|
||||
|
||||
\newcommand{\stgroupend}{%
|
||||
@@ -693,6 +734,16 @@
|
||||
fit={\st@grouplist}] (\st@gname) {};}\st@do
|
||||
\end{pgfonlayer}
|
||||
\global\st@firstfalse
|
||||
% A group must add information the members do not already carry: at least
|
||||
% two adjacent objects, or one \stcol partition. Around a single face or
|
||||
% stack the outline is decoration -- the stack already reads as one thing.
|
||||
\ifnum\st@gcount<2
|
||||
\ifst@ghascol\else
|
||||
\PackageWarning{supertensor}{Group `\st@gname' wraps a single object.
|
||||
Bind at least two members or one \string\stcol\space partition;
|
||||
a lone stack or face already reads as one composite}%
|
||||
\fi
|
||||
\fi
|
||||
% No \st@checkh: the overhang is 2*pad by construction, not driven by
|
||||
% content, and the members were already checked against the band. Warning
|
||||
% about it would only teach authors to inflate the declared band height.
|
||||
|
||||
+24
-13
@@ -10,8 +10,8 @@ does not need to be installed into your texmf tree.
|
||||
|
||||
The build first runs `scripts/lint.py`. It rejects ledger changes, untracked absolute
|
||||
objects, repeated anonymous dimensions, raw TikZ rectangles, a formula placed before the
|
||||
last row, an unclosed `\stgroup`, a callout anchored to anything other than a band or a
|
||||
second callout on one band, and more than four active hue families per row. Intentional galleries/tests may
|
||||
last row, an unclosed `\stgroup`, a callout anchored to anything other than a band, more
|
||||
than one callout in the figure, and more than four active hue families per row. Intentional galleries/tests may
|
||||
put `% supertensor-lint: allow-absolute, allow-missing-formula` near the top; do not add an
|
||||
exemption to a deliverable merely to make it pass.
|
||||
|
||||
@@ -105,10 +105,12 @@ but wrap hand-placed nodes in `\sttrack` so the cursor knows about them.
|
||||
role hue around whatever is placed between them, naming those objects as one composite:
|
||||
|
||||
```tex
|
||||
\stgroup[role=q]{qg} % keys: role= (hue), pad= (default \stgrouppad)
|
||||
\ststack[role=q]{qh}{}{T}{dh}{3} % "these three sheets are q"
|
||||
\stgroup[role=q]{qg} % keys: role= (REQUIRED, hue), pad= (default \stgrouppad)
|
||||
\stface[role=q]{q1}{}{T}{dh} % "these three heads are q"
|
||||
\stface[role=q, gap=2mm]{q2}{}{T}{dh}
|
||||
\stface[role=q, gap=2mm]{q3}{}{T}{dh}
|
||||
\stgroupend
|
||||
\stcaption{qg}{$\mathbf q$}{$B\times T\times h\times d_h$}
|
||||
\stcaption{qg}{$\mathbf q$}{$T\times h\times d_h$}
|
||||
```
|
||||
|
||||
The members go **inside** the block, and three properties follow from that:
|
||||
@@ -117,12 +119,18 @@ The members go **inside** the block, and three properties follow from that:
|
||||
swallow whatever sat between its members;
|
||||
- the group, not its last member, terminates a pending `\stlink` and sources the next
|
||||
one, so an arrow lands **on** the outline instead of ending inside it and crossing a
|
||||
border that is not its endpoint;
|
||||
- the padding is reserved on both sides, so the neighbour cannot land tangent to it.
|
||||
border that is not its endpoint. For the same reason `\stlink` **inside** a group is a
|
||||
package error: a member never terminates a connector, so the arrow would be dropped
|
||||
silently;
|
||||
- the padding is reserved on both sides, so the neighbour cannot land tangent to it. The
|
||||
fit includes decoration ink too: a `bracket=true` member's arms stay inside the outline.
|
||||
|
||||
`\strowend` fits the group, so `\stcaption{qg}{...}` hangs from the caption lane below the
|
||||
outline, not below the member. A group may contain a `\stcol`; it may not sit inside one,
|
||||
and it may not nest. An unclosed group is a lint error.
|
||||
A group must bind **at least two members, or one `\stcol` partition** — around a single
|
||||
face or stack the outline is decoration, and the package warns. `role=` is required; a
|
||||
genuinely mixed group passes `role=neutral` explicitly. `\strowend` fits the group, so
|
||||
`\stcaption{qg}{...}` hangs from the caption lane below the outline, not below the member.
|
||||
A group may contain a `\stcol`; it may not sit inside one, and it may not nest. An
|
||||
unclosed group is a lint error.
|
||||
|
||||
## Callouts
|
||||
|
||||
@@ -135,9 +143,12 @@ of a **finished** band, top-aligned with it. Call it after `\strowend`:
|
||||
\stcallout{n1}{5.2cm}{rowB}{下界化换来了什么}{Kimi Linear 的 $g$ 无下界……}
|
||||
```
|
||||
|
||||
Arg 3 must be a `\strow` band name — one aside per band, and never anchored to a single
|
||||
face. Both rules are lint errors, because a card beside one operand reads as a step in the
|
||||
computation (`layout.md`). Inside an open band it is a package error.
|
||||
Arg 3 must be a `\strow` band name, never a single face — a card beside one operand reads
|
||||
as a step in the computation (`layout.md`). The budget is **one callout per figure**: a
|
||||
card on every band is a dashboard, and the cards are unreadable at thumbnail size anyway.
|
||||
Both rules are lint errors; `% supertensor-lint: allow-multiple-callouts` relaxes the
|
||||
budget to one per band for a figure that genuinely needs it. Inside an open band a callout
|
||||
is a package error.
|
||||
|
||||
A callout pushes the vertical cursor below its own bottom edge. A card taller than its band
|
||||
therefore opens visible white space rather than colliding with the next stage — which is
|
||||
|
||||
@@ -38,10 +38,11 @@ into each other, not that the figure reads correctly.
|
||||
- [ ] Every connector's white label underlay covers only its own connector.
|
||||
- [ ] No connector crosses a box that is not its endpoint.
|
||||
- [ ] Symbols and shapes sit on two flat lanes per row; stage headings share a left rail.
|
||||
- [ ] Every `\stgroup` outline names a composite the computation actually has, is captioned,
|
||||
and carries its members' role hue (`neutral` only for genuinely mixed members).
|
||||
- [ ] Every `\stcallout` is an aside about its whole band, not a step: one per band, no
|
||||
taller than the band, and nothing in it that belongs in `\stmeaningbox`.
|
||||
- [ ] Every `\stgroup` outline names a composite the computation actually has, binds at
|
||||
least two members or a `\stcol` partition, is captioned, and carries its members'
|
||||
role hue (`neutral` only, and explicitly, for genuinely mixed members).
|
||||
- [ ] At most one `\stcallout` in the figure (exemption comment if more), an aside about
|
||||
its whole band, no taller than it, nothing in it that belongs in `\stmeaningbox`.
|
||||
- [ ] Top zone compact (≤2 formula lines, no shape underbraces).
|
||||
- [ ] Bottom box: one column, ≤3 rows, no overflow, no shrunken type.
|
||||
- [ ] If requested, signature is outside the box, one line, accurate, unclipped and subdued.
|
||||
|
||||
@@ -74,8 +74,8 @@ or on a `\stcallout` card hanging off the right edge of a band. Never drop a flo
|
||||
commentary card between two operands unless it is a real operation node (`st comm`).
|
||||
|
||||
`\stcallout` is that rule made structural: it refuses to open inside a band, the linter
|
||||
rejects it unless it is anchored to a `\strow` name, and a second card on one band is an
|
||||
error — side-by-side cards are a dashboard, not a figure. A card that ends up much taller
|
||||
rejects it unless it is anchored to a `\strow` name, and a second card in the figure is an
|
||||
error without an explicit exemption — a card per band is a dashboard, not a figure. A card that ends up much taller
|
||||
than its band is telling you the same thing the overflow warning does: that text is not an
|
||||
aside, it is the **Mechanism** row of `\stmeaningbox`.
|
||||
|
||||
|
||||
+3
-3
@@ -77,8 +77,8 @@ long, **remove content** — never add cards, columns or smaller type. Pass `{}`
|
||||
## Side cards
|
||||
|
||||
`\stcallout` is the only sanctioned floating text card, and it is deliberately narrow in
|
||||
scope: one per band, hung off the right edge of a *finished* band, never between two
|
||||
operands. When the text outgrows the height of its band, it is not an aside — move it into
|
||||
scope: one per figure by default, hung off the right edge of a *finished* band, never
|
||||
between two operands. When the text outgrows the height of its band, it is not an aside — move it into
|
||||
the **Mechanism** row of `\stmeaningbox` instead of widening or shrinking the card.
|
||||
|
||||
## Optional signature
|
||||
@@ -90,7 +90,7 @@ renders only the subject. Do not append an author, handle or brand identity.
|
||||
## Never
|
||||
|
||||
Charts or metric insets not present in the primary formula. Decorative pills, banners,
|
||||
shadows, repeated separators, explanatory cards other than one `\stcallout` per band.
|
||||
shadows, repeated separators, explanatory cards other than the one budgeted `\stcallout`.
|
||||
|
||||
## Reference image
|
||||
|
||||
|
||||
+1
-1
@@ -74,6 +74,6 @@ if [[ $status -ne 0 ]]; then
|
||||
echo "==> BUILD DIRTY: fix the warnings above before delivering." >&2
|
||||
else
|
||||
echo "==> clean. Now do the visual audit (references/checklist.md) --"
|
||||
echo " a clean build says nothing about collisions or hue budget."
|
||||
echo " a clean build says nothing about collisions or thumbnail legibility."
|
||||
fi
|
||||
exit $status
|
||||
|
||||
+14
-2
@@ -114,10 +114,13 @@ def lint(path: Path) -> list[str]:
|
||||
)
|
||||
|
||||
# A callout hangs off a BAND. Anchored to a face it becomes the floating
|
||||
# commentary card between two operands that layout.md forbids, and two of
|
||||
# them on one band is a dashboard, not a figure.
|
||||
# commentary card between two operands that layout.md forbids. The default
|
||||
# budget is ONE callout for the whole figure: a card per band is already a
|
||||
# dashboard, and at thumbnail size the cards are unreadable anyway. The
|
||||
# allow-multiple-callouts directive relaxes this to one per band.
|
||||
band_names = set(ROW_NAME_RE.findall(source))
|
||||
callout_anchors: dict[str, str] = {}
|
||||
first_callout: str | None = None
|
||||
for match in CALLOUT_RE.finditer(source):
|
||||
name, anchor = (part.strip() for part in match.groups())
|
||||
line = line_of(source, match.start())
|
||||
@@ -131,7 +134,16 @@ def lint(path: Path) -> list[str]:
|
||||
f"line {line}: callout {name!r} is the second card on band {anchor!r} "
|
||||
f"(after {callout_anchors[anchor]!r}); one aside per band"
|
||||
)
|
||||
elif first_callout is not None and "allow-multiple-callouts" not in allowed:
|
||||
errors.append(
|
||||
f"line {line}: callout {name!r} is the second card in the figure "
|
||||
f"(after {first_callout!r}); the budget is one callout per figure — "
|
||||
f"move the text to \\stmeaningbox, or add the "
|
||||
f"allow-multiple-callouts exemption"
|
||||
)
|
||||
callout_anchors.setdefault(anchor, name)
|
||||
if first_callout is None:
|
||||
first_callout = name
|
||||
|
||||
for row_number, row in enumerate(ROW_RE.finditer(source), start=1):
|
||||
row_roles = set(ROLE_KEY_RE.findall(row.group(1)))
|
||||
|
||||
+18
-26
@@ -1,7 +1,9 @@
|
||||
% Regression test for \stgroup and \stcallout.
|
||||
% - a group over one stack (the three sheets are one composite object),
|
||||
% - a group over two adjacent shards (the pair is one partitioned parent),
|
||||
% - a side card hanging off the right edge of each band.
|
||||
% - a group over three adjacent head faces (the trio is one composite q);
|
||||
% the first face carries bracket=true, probing that bracket ink is part
|
||||
% of the group's fit -- the outline must clear the bracket arms,
|
||||
% - a group over a \stcol partition (two shards tiling one parent W),
|
||||
% - one side card for the whole figure, hanging off a finished band.
|
||||
% No absolute coordinate appears anywhere in this figure.
|
||||
% ../scripts/build.sh group-callout.tex
|
||||
\documentclass[border=10pt]{standalone}
|
||||
@@ -9,9 +11,7 @@
|
||||
|
||||
\stsetrole{act}{stTeal}
|
||||
\stsetrole{w}{stOrange}
|
||||
\stsetrole{q}{stTeal}
|
||||
\stsetrole{k}{stViolet}
|
||||
\stsetrole{v}{stCoral}
|
||||
\stsetrole{q}{stViolet}
|
||||
|
||||
\stdim{T}{7}
|
||||
\stdim{d}{5}
|
||||
@@ -20,27 +20,18 @@
|
||||
\begin{document}
|
||||
\begin{tikzpicture}
|
||||
|
||||
\ststage{S1}{一、分组框:把已经排好的面命名为一个复合对象}
|
||||
\ststage{S1}{一、分组框:三个相邻的头合起来是一个复合对象}
|
||||
\strow{R1}{T}
|
||||
\stface[role=act, bracket=true]{X}{}{T}{d}
|
||||
\stlink{l1}{三路投影}
|
||||
\stlink{l1}{按头切分}
|
||||
\stgroup[role=q]{QG}
|
||||
\ststack[role=q]{Q}{}{T}{dh}{3}
|
||||
\stgroupend
|
||||
\stgroup[role=k]{KG}
|
||||
\ststack[role=k]{K}{}{T}{dh}{3}
|
||||
\stgroupend
|
||||
\stgroup[role=v]{VG}
|
||||
\ststack[role=v]{V}{}{T}{dh}{3}
|
||||
\stface[role=q, bracket=true]{Q1}{}{T}{dh}
|
||||
\stface[role=q, gap=2mm]{Q2}{}{T}{dh}
|
||||
\stface[role=q, gap=2mm]{Q3}{}{T}{dh}
|
||||
\stgroupend
|
||||
\strowend
|
||||
\stcaption{X}{$\mathbf X$}{$T\times d$}
|
||||
\stcaption{QG}{$\mathbf q$}{$h\times T\times d_h$}
|
||||
\stcaption{KG}{$\mathbf k$}{$h\times T\times d_h$}
|
||||
\stcaption{VG}{$\mathbf v$}{$h\times T\times d_h$}
|
||||
\stcallout{N1}{4.2cm}{R1}{分组框在说什么}%
|
||||
{外框与里面的面同色,因为它圈的是同一个对象的多头视图,不是一个新张量。
|
||||
框的内边距计入行的包围盒,所以下面的符号轨仍然从框底起算。}
|
||||
|
||||
\ststage{S2}{二、分组框圈住两片相邻的分片,标注它们合起来是谁}
|
||||
\strow{R2}{T}
|
||||
@@ -58,8 +49,10 @@
|
||||
\stcaption{H}{$\mathbf H$}{$T\times d$}
|
||||
\stcaption{WG}{$\mathbf W$}{$d\times T$}
|
||||
\stcaption{Z}{$\mathbf Z$}{$T\times T$}
|
||||
\stcallout{N2}{4.2cm}{R2}{一行一张卡}%
|
||||
{同一个 band 上挂两张卡会被 lint 拒绝:并排的说明卡是仪表盘,不是图。}
|
||||
\stcallout{N1}{4.2cm}{R2}{分组框在说什么}%
|
||||
{外框与成员同色,因为它圈的是同一个对象的分片视图,不是一个新张量。
|
||||
括号等装饰墨迹也计入外框的包围盒,所以框永远不会被成员的括号穿过;
|
||||
整张图默认只允许一张这样的卡片,再多就是仪表盘。}
|
||||
|
||||
\sttopformula{F}{$\displaystyle \mathbf Z=\mathbf H\,\mathbf W,\qquad
|
||||
\mathbf W=\begin{bmatrix}\mathbf W_a\\ \mathbf W_b\end{bmatrix}$}
|
||||
@@ -69,10 +62,9 @@
|
||||
{$T$ 序列长,$d$ 模型维,$d_h$ 头宽,$h$ 头数}
|
||||
{}
|
||||
{分组框是横向的子流:成员写在块里,所以它只能圈住相邻的对象;
|
||||
两侧的内边距各占一份宽度,箭头也接在外框上而不是成员上——
|
||||
否则连接线会穿过一个并非自己端点的框。
|
||||
说明卡挂在 band 右侧,并把纵向游标压到自己底边以下,所以卡片过高只会撑开空白,
|
||||
不会压住下一段。}
|
||||
它必须绑定至少两个成员或一个 \texttt{stcol} 分片,单个对象外再画框是装饰。
|
||||
连接线不能在框内起止——\texttt{stlink} 写在组里是构建错误,
|
||||
闭合后箭头接在外框上,而不是穿过一个并非自己端点的边。}
|
||||
|
||||
\end{tikzpicture}
|
||||
\end{document}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
% \stlink inside a group: members never terminate a pending connector, so the
|
||||
% arrow would be dropped silently. The package must error rather than build a
|
||||
% figure whose label appears but whose arrow does not.
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stgroup[role=x]{G}
|
||||
\stface[role=x]{A}{}{T}{T}
|
||||
\stlink{l1}{lost arrow}
|
||||
\stface[role=x]{B}{}{T}{T}
|
||||
\stgroupend
|
||||
\strowend
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,14 @@
|
||||
% A group with no role would silently fall back to neutral gray, violating
|
||||
% the "outline in the composite's own hue" rule. The package must error.
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stgroup{G}
|
||||
\stface[role=x]{A}{}{T}{T}
|
||||
\stface[role=x]{B}{}{T}{T}
|
||||
\stgroupend
|
||||
\strowend
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,13 @@
|
||||
% A group around a single object is decoration: the stack already reads as
|
||||
% one composite. The package must reject this with a dirty-build warning.
|
||||
\documentclass[border=2pt]{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stsetrole{x}{stTeal}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stgroup[role=x]{G}
|
||||
\ststack[role=x]{Q}{}{T}{T}{3}
|
||||
\stgroupend
|
||||
\strowend
|
||||
\end{tikzpicture}\end{document}
|
||||
@@ -0,0 +1,17 @@
|
||||
% One card per band, but a card on EVERY band, is still a dashboard. The
|
||||
% default budget is one callout per figure; this must fail lint without the
|
||||
% allow-multiple-callouts exemption.
|
||||
\documentclass{standalone}
|
||||
\usepackage[en]{supertensor}
|
||||
\stdim{T}{4}
|
||||
\begin{document}\begin{tikzpicture}
|
||||
\strow{R1}{T}
|
||||
\stface{A}{}{T}{T}
|
||||
\strowend
|
||||
\stcallout{N1}{3cm}{R1}{first}{one per figure}
|
||||
\strow{R2}{T}
|
||||
\stface{B}{}{T}{T}
|
||||
\strowend
|
||||
\stcallout{N2}{3cm}{R2}{second}{this one belongs in the meaning box}
|
||||
\sttopformula{F}{$A,B$}
|
||||
\end{tikzpicture}\end{document}
|
||||
Reference in New Issue
Block a user