Box family — phantom, smash, lap (items 1-3)#244
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces support for the box family of LaTeX commands (such as phantom, hphantom, vphantom, mathstrut, smash, and various lap commands) by implementing a new MTMathBox atom type and its corresponding MTMathBoxDisplay rendering class. Feedback on the implementation suggests improving the robustness of the parser when handling optional arguments for smash (e.g., [t] or [b]) by raising a parsing error if the closing bracket is missing.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (ch == '[') { | ||
| NSMutableString* opt = [NSMutableString string]; | ||
| while ([self hasCharacters]) { | ||
| unichar c = [self getNextCharacter]; | ||
| if (c == ']') { break; } | ||
| [opt appendString:[NSString stringWithCharacters:&c length:1]]; | ||
| } | ||
| NSString* o = [opt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; | ||
| if ([o isEqualToString:@"t"]) { box.keepHeight = NO; box.keepDepth = YES; } | ||
| else if ([o isEqualToString:@"b"]) { box.keepHeight = YES; box.keepDepth = NO; } | ||
| // any other value: ignore, leave smash-both flags (no crash). |
There was a problem hiding this comment.
When parsing the optional argument [t] or [b] for \smash, if the closing bracket ] is missing (e.g., \smash[t at the end of the input), the parser currently continues silently without raising an error. To be consistent with other optional argument parsing (like \sqrt) and standard LaTeX syntax, we should verify that the closing bracket was successfully found and raise a MTParseErrorCharacterNotFound error if it is missing.
if (ch == '[') {
NSMutableString* opt = [NSMutableString string];
BOOL foundClose = NO;
while ([self hasCharacters]) {
unichar c = [self getNextCharacter];
if (c == ']') {
foundClose = YES;
break;
}
[opt appendString:[NSString stringWithCharacters:&c length:1]];
}
if (!foundClose) {
[self setError:MTParseErrorCharacterNotFound message:@"Expected character not found: ]"];
return nil;
}
NSString* o = [opt stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([o isEqualToString:@"t"]) { box.keepHeight = NO; box.keepDepth = YES; }
else if ([o isEqualToString:@"b"]) { box.keepHeight = YES; box.keepDepth = NO; }
// any other value: ignore, leave smash-both flags (no crash).There was a problem hiding this comment.
Fixed in 0a8395f. The smash optional-arg loop now tracks the closing bracket and raises MTParseErrorCharacterNotFound when it is missing, matching the \sqrt[…] precedent. Added \smash[t to the parse-error test table.
Code review (orchestrator inline — automated review agent stalled twice on a stream watchdog, so this is a focused static review)Verdict: solid, no blocking issues. Faithful to the LLD; reuses the colorbox/overline idioms correctly. Full suite already green per the implementer (Xcode 313/313, What's right
Non-blocking nits
None of these block merge. |
\smash[t / \smash[b without a closing ']' silently recovered instead of erroring, unlike \sqrt[…] which raises MTParseErrorCharacterNotFound. Track the closing bracket and fail loud when it is absent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… mutating in draw: draw: translated the CTM and reset child.position = CGPointZero on every frame, a draw-time side-effect that sibling displays avoid. Follow the MTRadicalDisplay / MTInnerDisplay pattern: override setPosition: to push the offset-adjusted absolute position to the child once, leaving draw: to simply draw it. No behavior change (354/354 tests pass). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Goal
End-to-end support for the box family:
\phantom,\hphantom,\vphantom,\mathstrut,\smash(+[t]/[b]), and\llap/\rlap/\clap(+\math*lapaliases). Adds a single parameterized atom (MTMathBox, 5-flag matrix) + one display (MTMathBoxDisplay) backing the entire family.This is PR 1 of the box-and-spacing layer. It is independent of PR 2 and based directly on
master.Commits
[item 1]Add MTMathBox atom, MTBoxHAlign, and kMTMathAtomBox plumbing[item 2]Parse phantom/smash/lap commands into MTMathBox[item 3]Render MTMathBox via MTMathBoxDisplay and typesetter box caseImplementation
kMTMathAtomBox = 20(script-capable),MTBoxHAlignenum,MTMathBox : MTMathAtomwithinnerList+ keepWidth/keepHeight/keepDepth/drawChild/hAlign flags; lossystringValue/appendLaTeXToString:per the flag matrix.+boxCommandstable + dispatch branch in-atomForCommand:(synthetic(for\mathstrut, optional[t]/[b]for\smash).MTMathBoxDisplay : MTDisplayreporting flag-selected geometry and drawing/suppressing/offsetting its child; newkMTMathAtomBoxcase inMTTypesetter -createDisplayAtoms:(reclassifies to Ordinary, scripts supported).Tests
MTMathListTest: 10/10.MTMathListBuilderTest: 146/146.MTTypesetterTest: 108/108.swift test354/354, Xcode 313/313. Includes integration (vphantom drives delimiter size, scripts on box, rlap advance, negative-origin lap).Deviations (documented by implementer)
initWithType:value:declaration onMTMathBoxso the guard test can compile (base designated initializer lives in a private category).appendLaTeXToString:override callingself.stringValue(the base does not route throughstringValue), mirroringMTMathStyle.References
docs/plans/2026-06-28-box-spacing-layer.md(PR 1, Tasks 1–3)docs/lld/2026-06-28-box-spacing-layer.md🤖 Generated with Claude Code