mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-27 03:47:09 -06:00
Equation gallery: group multi-letter operands in two templates (#347)
A script or above/below operand takes one letter unless it is grouped, as in Word, so `⟶┴yields` (Yields) put only "y" above the arrow and the n×n Matrix's `a_1n`, `a_m1`, `a_mn` subscripted only "1" and "m". Grouped as `⟶┴(yields)` and `a_(1n)`, `a_(m1)`, `a_(mn)`. A new test fails when any template or built-in equation leaves letters right after a script or limit. Claude-Session: https://claude.ai/code/session_01WtHKQ7wrZm3uBuaG1Ye8po Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Dmitrii Khlapov
Claude Opus 5.5
parent
1d7a54f883
commit
e2d8551b7f
@@ -435,7 +435,7 @@ pub const STRUCTURES: &[Gallery] = &[
|
||||
t("op.eqAbove", "Text over Equal", "=┴⬚"),
|
||||
],
|
||||
),
|
||||
("Common Operator Structures", &[t("op.yields", "Yields", "⟶┴yields"), t("op.deltaArrow", "Delta over arrow", "⟶┴∆")]),
|
||||
("Common Operator Structures", &[t("op.yields", "Yields", "⟶┴(yields)"), t("op.deltaArrow", "Delta over arrow", "⟶┴∆")]),
|
||||
],
|
||||
},
|
||||
Gallery {
|
||||
@@ -486,7 +486,7 @@ pub const STRUCTURES: &[Gallery] = &[
|
||||
(
|
||||
"Sparse Matrices",
|
||||
&[
|
||||
t("mat.sparse", "n×n Matrix", "(■(a_11&⋯&a_1n@⋮&⋱&⋮@a_m1&⋯&a_mn))"),
|
||||
t("mat.sparse", "n×n Matrix", "(■(a_11&⋯&a_(1n)@⋮&⋱&⋮@a_(m1)&⋯&a_(mn)))"),
|
||||
t("mat.identityN", "n×n Identity Matrix", "[■(1&0&⋯&0@0&1&⋯&0@⋮&⋮&⋱&⋮@0&0&⋯&1)]"),
|
||||
],
|
||||
),
|
||||
@@ -548,6 +548,28 @@ mod tests {
|
||||
})
|
||||
}
|
||||
|
||||
/// A script or above/below operand takes one letter unless it is grouped (`a_(mn)`), as in
|
||||
/// Word; letters right after one mean a template split a word (`⟶┴yields` put only `y` above
|
||||
/// the arrow).
|
||||
fn split_operand(a: &[MNode]) -> bool {
|
||||
a.windows(2).any(|w| {
|
||||
matches!(w[0], MNode::Lim { .. } | MNode::Script { .. })
|
||||
&& matches!(&w[1], MNode::Run(r) if r.text.starts_with(|c: char| c.is_alphabetic()))
|
||||
}) || a
|
||||
.iter()
|
||||
.any(|n| (0..wordcraft_doc::math_edit::child_count(n)).any(|c| wordcraft_doc::math_edit::child(n, c).is_some_and(|x| split_operand(x))))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_letter_operands_are_grouped() {
|
||||
for tpl in templates() {
|
||||
assert!(!split_operand(&tpl.nodes()), "{} splits an operand: {}", tpl.id, tpl.linear);
|
||||
}
|
||||
for (id, _, lin) in BUILT_INS {
|
||||
assert!(!split_operand(&parse_linear(lin)), "{id} splits an operand: {lin}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_template_builds() {
|
||||
let mut ids = std::collections::HashSet::new();
|
||||
|
||||
Reference in New Issue
Block a user