File indexing completed on 2024-05-19 11:21:24

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2012 Alexander Rieder <alexanderrieder@gmail.com>
0004 */
0005 
0006 #include "maximavariablemodel.h"
0007 
0008 #include "maximasession.h"
0009 #include "maximaexpression.h"
0010 #include "textresult.h"
0011 #include "latexresult.h"
0012 
0013 #include <QDebug>
0014 #include <KLocalizedString>
0015 
0016 #include "settings.h"
0017 
0018 //command used to inspect a maxima variable. %1 is the name of that variable
0019 const QString MaximaVariableModel::inspectCommand=QLatin1String(":lisp($disp $%1)");
0020 const QString MaximaVariableModel::variableInspectCommand=QLatin1String(":lisp(cantor-inspect $%1)");
0021 
0022 MaximaVariableModel::MaximaVariableModel(MaximaSession* session) : Cantor::DefaultVariableModel(session)
0023 {
0024 }
0025 
0026 void MaximaVariableModel::update()
0027 {
0028     if (static_cast<MaximaSession*>(session())->mode() != MaximaSession::Maxima)
0029         return;
0030 
0031     if (!m_variableExpression)
0032     {
0033         qDebug()<<"checking for new variables";
0034         const QString& cmd1 = variableInspectCommand.arg(QLatin1String("values"));
0035         m_variableExpression = static_cast<MaximaExpression*>(session()->evaluateExpression(cmd1, Cantor::Expression::FinishingBehavior::DoNotDelete, true));
0036         connect(m_variableExpression, &Cantor::Expression::statusChanged, this, &MaximaVariableModel::parseNewVariables);
0037     }
0038 
0039     if (!m_functionExpression)
0040     {
0041         qDebug()<<"checking for new functions";
0042         const QString& cmd2 = inspectCommand.arg(QLatin1String("functions"));
0043         m_functionExpression = static_cast<MaximaExpression*>(session()->evaluateExpression(cmd2, Cantor::Expression::FinishingBehavior::DoNotDelete, true));
0044         connect(m_functionExpression, &Cantor::Expression::statusChanged, this, &MaximaVariableModel::parseNewFunctions);
0045     }
0046 }
0047 
0048 QList<Cantor::DefaultVariableModel::Variable> parse(MaximaExpression* expr)
0049 {
0050     if(!expr
0051         || (expr->status()!=Cantor::Expression::Done && expr->errorMessage() != QLatin1String("$DONE"))
0052         || expr->results().isEmpty())
0053     {
0054         return QList<Cantor::DefaultVariableModel::Variable>();
0055     }
0056 
0057     //for parsing of names and values below (old code) we need to combine multiple results back to one string
0058     QString text;
0059     for (auto* result : expr->results())
0060     {
0061         if(result->type()==Cantor::TextResult::Type)
0062             text += static_cast<Cantor::TextResult*>(result)->plain();
0063         else if(expr->result()->type()==Cantor::LatexResult::Type)
0064             text += static_cast<Cantor::LatexResult*>(result)->plain();
0065     }
0066 
0067     const int nameIndex = text.indexOf(QLatin1Char(']'));
0068     QString namesString = text.left(nameIndex);
0069     //namesString.chop(1);
0070     namesString=namesString.mid(1);
0071     namesString=namesString.trimmed();
0072 
0073     qDebug()<<"variable names: "<<namesString;
0074     if(namesString.isEmpty())
0075         return QList<Cantor::DefaultVariableModel::Variable>();
0076 
0077     QStringList variableNames;
0078     QString valuesString;
0079     bool hasValues = false;
0080     QStringList variableValues;
0081     if ( namesString.contains(QLatin1Char(')')) )
0082     {
0083         //function definition(s): e.g
0084         //text = "[f1(x),f2(x,y),f3(x,y,z)]\n$DONE"
0085         //nameString = f1(x),f2(x,y),f3(x,y,z)
0086         //variableString = "\n$DONE"
0087         variableNames = namesString.split(QLatin1String("),"));
0088     }
0089     else
0090     {
0091         //variable definition(s): e.g.
0092         //text = "[a,b]\n1\n\"-cantor-value-separator-\"\n2\n\"-cantor-value-separator-\"\n($A $B)"
0093         //nameString = "[a,b]"
0094         //variableString = "\n1\n\"-cantor-value-separator-\"\n2\n\"-cantor-value-separator-\"\n($A $B)"
0095         variableNames = namesString.split(QLatin1Char(','));
0096         if (MaximaSettings::self()->variableManagement())
0097         {
0098             valuesString = text.mid(nameIndex+1).trimmed();
0099             valuesString = valuesString.remove(QLatin1String("\n")); //lists with many elements have line breaks, remove them
0100             variableValues = valuesString.split(QLatin1String("\"-cantor-value-separator-\""));
0101             hasValues = variableValues.isEmpty();
0102         }
0103     }
0104 
0105     qDebug()<<variableNames;
0106     qDebug()<<"string: "<<valuesString;
0107     qDebug()<<"values: "<<variableValues;
0108     qDebug()<<"has Values: "<<hasValues;
0109 
0110     QList<Cantor::DefaultVariableModel::Variable> variables;
0111     variables.reserve(variableNames.size());
0112     for(int i=0;i<variableNames.size();i++)
0113     {
0114         Cantor::DefaultVariableModel::Variable var;
0115         var.name=variableNames.at(i);;
0116         if(variableValues.size()>i)
0117         {
0118             var.value=variableValues.at(i).trimmed();
0119             var.value=var.value.remove(QLatin1String("\n")); //lists with many elements have line breaks, remove them
0120 
0121             // text output is quoted by Maxima, remove the quotes
0122             if (var.value.startsWith(QLatin1String("\"")))
0123             {
0124                 var.value.remove(0, 1);
0125                 var.value.chop(1);
0126                 var.value.replace(QLatin1String("\\\""), QLatin1String("\""));
0127             }
0128         }
0129         else
0130             var.value=QLatin1String("unknown");
0131 
0132         variables<<var;
0133     }
0134 
0135     return variables;
0136 }
0137 
0138 void MaximaVariableModel::parseNewVariables(Cantor::Expression::Status status)
0139 {
0140     if (status != Cantor::Expression::Done && status != Cantor::Expression::Error)
0141         return;
0142 
0143     qDebug()<<"parsing variables";
0144 
0145     QList<Variable> newVars=parse(m_variableExpression);
0146     setVariables(newVars);
0147 
0148     //the expression is not needed anymore
0149     m_variableExpression->deleteLater();
0150     m_variableExpression = nullptr;
0151 }
0152 
0153 void MaximaVariableModel::parseNewFunctions(Cantor::Expression::Status status)
0154 {
0155     if (status != Cantor::Expression::Done && status != Cantor::Expression::Error)
0156         return;
0157 
0158     qDebug()<<"parsing functions";
0159 
0160     // List of variables?
0161     QList<Variable> newFuncs=parse(m_functionExpression);
0162     QStringList functions;
0163     for (Variable var : newFuncs)
0164         functions << var.name.left(var.name.indexOf(QLatin1Char('(')));
0165     qDebug() << functions;
0166     setFunctions(functions);
0167 
0168     //the expression is not needed anymore
0169     m_functionExpression->deleteLater();
0170     m_functionExpression = nullptr;
0171 }
0172 
0173 MaximaSession* MaximaVariableModel::maximaSession()
0174 {
0175     return static_cast<MaximaSession*> (session());
0176 }