commit e743f6f6d3e57ae7e687e3e1adc964aadf23d3ee
Author: Enrico Forestieri <[email protected]>
Date: Sun May 18 22:14:43 2025 +0200
Fix bug #13186
Correctly parse \prod constructs for maxima, mathematica and maple.
---
src/mathed/InsetMathExInt.cpp | 6 ++++
src/mathed/MathExtern.cpp | 84 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 87 insertions(+), 3 deletions(-)
diff --git a/src/mathed/InsetMathExInt.cpp b/src/mathed/InsetMathExInt.cpp
index 70d1ba1604..05a58d964b 100644
--- a/src/mathed/InsetMathExInt.cpp
+++ b/src/mathed/InsetMathExInt.cpp
@@ -75,6 +75,8 @@ void InsetMathExInt::maple(MapleStream & os) const
{
if (symbol_ == "int" || symbol_ == "intop")
os << (os.maxima() ? "integrate(" : "int(");
+ else if (symbol_ == "prod")
+ os << "product(";
else
os << symbol_ << '(';
@@ -100,6 +102,8 @@ void InsetMathExInt::maxima(MaximaStream & os) const
{
if (symbol_ == "int" || symbol_ == "intop")
os << "integrate(";
+ else if (symbol_ == "prod")
+ os << "product(";
else
os << symbol_ << '(';
@@ -119,6 +123,8 @@ void InsetMathExInt::mathematica(MathematicaStream & os)
const
os << "Integrate[";
else if (symbol_ == "sum")
os << "Sum[";
+ else if (symbol_ == "prod")
+ os << "Product[";
else
os << symbol_ << '[';
diff --git a/src/mathed/MathExtern.cpp b/src/mathed/MathExtern.cpp
index 43ae76f0af..7834331216 100644
--- a/src/mathed/MathExtern.cpp
+++ b/src/mathed/MathExtern.cpp
@@ -372,9 +372,10 @@ void splitScripts(MathData & md)
continue;
if (script->nuc().size() == 1) {
- // leave alone sums and integrals
+ // leave alone sums, prods and integrals
MathAtom const & atom = script->nuc().front();
- if (testSymbol(atom, "sum") || testSymbol(atom, "int"))
+ if (testSymbol(atom, "sum") || testSymbol(atom, "int")
+ || testSymbol(atom, "prod"))
continue;
}
@@ -842,6 +843,81 @@ void extractSums(MathData & md)
}
+//
+// search prods
+//
+
+
+bool testProdSymbol(MathAtom const & p)
+{
+ return testSymbol(p, from_ascii("prod"));
+}
+
+
+bool testProd(MathAtom const & at)
+{
+ return
+ testProdSymbol(at) ||
+ ( at->asScriptInset()
+ && !at->asScriptInset()->nuc().empty()
+ && testProdSymbol(at->asScriptInset()->nuc().back()) );
+}
+
+
+// replace '\prod' ['_^'] f(x) sequences by a real InsetMathExInt
+// assume 'extractDelims' ran before
+void extractProds(MathData & md)
+{
+ // we need at least two items...
+ if (md.size() < 2)
+ return;
+
+ Buffer * buf = md.buffer();
+
+ //lyxerr << "\nProds from: " << md << endl;
+ for (size_t i = 0; i + 1 < md.size(); ++i) {
+ MathData::iterator it = md.begin() + i;
+
+ // is this a prod name?
+ if (!testProd(md[i]))
+ continue;
+
+ // create a proper inset as replacement
+ auto p = make_unique<InsetMathExInt>(buf, from_ascii("prod"));
+
+ // collect lower bound and summation index
+ InsetMathScript const * sub = md[i]->asScriptInset();
+ if (sub && sub->hasDown()) {
+ // try to figure out the product index from the
subscript
+ MathData const & ar = sub->down();
+ MathData::const_iterator xt =
+ find_if(ar.begin(), ar.end(), &testEqualSign);
+ if (xt != ar.end()) {
+ // we found a '=', use everything in front of
that as index,
+ // and everything behind as lower index
+ p->cell(1) = MathData(buf, ar.begin(), xt);
+ p->cell(2) = MathData(buf, xt + 1, ar.end());
+ } else {
+ // use everything as product index, don't use
scripts.
+ p->cell(1) = ar;
+ }
+ }
+
+ // collect upper bound
+ if (sub && sub->hasUp())
+ p->cell(3) = sub->up();
+
+ // use something behind the script as core
+ MathData::iterator tt = extractTerm(p->cell(0), it + 1,
md.end());
+
+ // cleanup
+ md.erase(it + 1, tt);
+ *it = MathAtom(p.release());
+ }
+ //lyxerr << "\nProds to: " << md << endl;
+}
+
+
//
// search differential stuff
//
@@ -1021,8 +1097,10 @@ void extractStructure(MathData & md, ExternalMath kind)
splitScripts(md);
extractDelims(md);
extractIntegrals(md, kind);
- if (kind != MATHML && kind != HTML)
+ if (kind != MATHML && kind != HTML) {
extractSums(md);
+ extractProds(md);
+ }
extractNumbers(md);
extractMatrices(md);
if (kind != MATHML && kind != HTML) {
--
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs