diff --git a/README b/README --- a/README +++ b/README @@ -17,6 +17,7 @@ - R Project for Statistical Computing: http://r-project.org/ - Sage Mathematics Software: http://sagemath.org/ - Scilab for Numerical Computation: http://scilab.org/ +- Julia programming language: http://julialang.org/ How To Build and Install Cantor -=-=-=-=-=-=-=-=-=-=-=-=-= diff --git a/README.md b/README.md --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ - R Project for Statistical Computing: http://r-project.org/ - Sage Mathematics Software: http://sagemath.org/ - Scilab for Numerical Computation: http://scilab.org/ +- Julia programming language: http://julialang.org/ ## How To Build and Install Cantor diff --git a/src/backends/julia/juliabackend.h b/src/backends/julia/juliabackend.h --- a/src/backends/julia/juliabackend.h +++ b/src/backends/julia/juliabackend.h @@ -21,24 +21,66 @@ #include "backend.h" +/** + * Backend for Julia language + * + * @see http://julialang.org/ + * @see JuliaServer + */ class JuliaBackend: public Cantor::Backend { Q_OBJECT public: + /** + * Constructs julia backend + * + * @param parent QObject parent. Defaults to nullptr. + * @param args Additional arguments for the backend. + * Defaults to QList(). + */ explicit JuliaBackend( QObject *parent = 0, const QList &args = QList()); virtual ~JuliaBackend() {} + /** + * @see Cantor::Backend::id + */ virtual QString id() const override; + + /** + * @see Cantor::Backend::createSession + */ virtual Cantor::Session *createSession() override; + /** + * @see Cantor::Backend::capabilities + */ virtual Cantor::Backend::Capabilities capabilities() const override; + + /** + * @see Cantor::Backend::description + */ virtual QString description() const override; + + /** + * @see Cantor::Backend::helpUrl + */ virtual QUrl helpUrl() const override; + + /** + * @see Cantor::Backend::requirementsFullfilled + */ virtual bool requirementsFullfilled() const override; + /** + * @see Cantor::Backend::settingsWidget + */ virtual QWidget *settingsWidget(QWidget *parent) const override; + + /** + * @see Cantor::Backend::config + */ virtual KConfigSkeleton *config() const override; }; diff --git a/src/backends/julia/juliacompletionobject.h b/src/backends/julia/juliacompletionobject.h --- a/src/backends/julia/juliacompletionobject.h +++ b/src/backends/julia/juliacompletionobject.h @@ -24,16 +24,39 @@ class JuliaSession; +/** + * Implements code completion for Julia language + * + * Uses Julia's Base.REPL.REPLCompletions.completions command to get + * context-aware completions like in native Julia REPL + */ class JuliaCompletionObject : public Cantor::CompletionObject { public: + /** + * Constructs JuliaCompletionObject + * + * @param cmd command piece to generate completion + * @param index index of cursor in commmand + * @param session current session + */ JuliaCompletionObject(const QString &cmd, int index, JuliaSession *session); ~JuliaCompletionObject(); protected: + /** + * @see Cantor::CompletionObject::mayIdentifierContain + */ virtual bool mayIdentifierContain(QChar c) const; virtual bool mayIdentifierBeginWith(QChar c) const; + /** + * @see Cantor::CompletionObject::mayIdentifierBeginWith + */ + protected Q_SLOTS: + /** + * @see Cantor::CompletionObject::fetchCompletions + */ void fetchCompletions(); }; diff --git a/src/backends/julia/juliaexpression.h b/src/backends/julia/juliaexpression.h --- a/src/backends/julia/juliaexpression.h +++ b/src/backends/julia/juliaexpression.h @@ -21,19 +21,48 @@ #include "expression.h" +/** + * Expression of Julia language + */ class JuliaExpression: public Cantor::Expression { Q_OBJECT public: + /** + * Creates new JuliaExpression + * + * @param session session to bound expression to + */ JuliaExpression(Cantor::Session *session); virtual ~JuliaExpression() {}; + /** + * @see Cantor::Expression::evaluate + */ virtual void evaluate() override; + + /** + * @see Cantor::Expression::interrupt + */ virtual void interrupt() override; + + /** + * Call this function from session when JuliaServer ends evaluation of + * this expression. + * + * This checks inline plots, exceptions and set appropriate result + */ void finalize(); private: + /// If not empty, it's a filename of plot image file expression is awaiting + /// to get QString m_plot_filename; + + /** + * @return bool indicator if current expression contains command that + * shows plot + */ bool checkPlotShowingCommands(); }; diff --git a/src/backends/julia/juliaexpression.cpp b/src/backends/julia/juliaexpression.cpp --- a/src/backends/julia/juliaexpression.cpp +++ b/src/backends/julia/juliaexpression.cpp @@ -38,8 +38,10 @@ setStatus(Cantor::Expression::Computing); auto juliaSession = dynamic_cast(session()); + // Plots integration m_plot_filename.clear(); if (juliaSession->integratePlots() and checkPlotShowingCommands()) { + // Simply add plot saving command to the end of execution QStringList inlinePlotFormats; inlinePlotFormats << QLatin1String("svg"); inlinePlotFormats << QLatin1String("eps"); @@ -73,6 +75,7 @@ } else { if (not m_plot_filename.isEmpty() and QFileInfo(m_plot_filename).exists()) { + // If we have plot in result, show it setResult( new Cantor::ImageResult(QUrl::fromLocalFile(m_plot_filename))); QDir().remove(m_plot_filename); diff --git a/src/backends/julia/juliaextensions.h b/src/backends/julia/juliaextensions.h --- a/src/backends/julia/juliaextensions.h +++ b/src/backends/julia/juliaextensions.h @@ -25,81 +25,180 @@ ~Julia##name##Extension(); +/** + * Implementation of linear algebra wizards for Julia + */ class JuliaLinearAlgebraExtension: public Cantor::LinearAlgebraExtension { public: JULIA_EXT_CDTOR_DECL(LinearAlgebra) + /** + * @see Cantor::LinearAlgebraExtension::createVector + */ virtual QString createVector( const QStringList &entries, VectorType type) override; + /** + * @see Cantor::LinearAlgebraExtension::nullVector + */ virtual QString nullVector(int size, VectorType type) override; + /** + * @see Cantor::LinearAlgebraExtension::createMatrix + */ virtual QString createMatrix( const Cantor::LinearAlgebraExtension::Matrix &matrix) override; + /** + * @see Cantor::LinearAlgebraExtension::identityMatrix + */ virtual QString identityMatrix(int size) override; + + /** + * @see Cantor::LinearAlgebraExtension::nullMatrix + */ virtual QString nullMatrix(int rows, int columns) override; + + /** + * @see Cantor::LinearAlgebraExtension::rank + */ virtual QString rank(const QString &matrix) override; + + /** + * @see Cantor::LinearAlgebraExtension::invertMatrix + */ virtual QString invertMatrix(const QString &matrix) override; + + /** + * @see Cantor::LinearAlgebraExtension::charPoly + */ virtual QString charPoly(const QString &matrix) override; + + /** + * @see Cantor::LinearAlgebraExtension::eigenVectors + */ virtual QString eigenVectors(const QString &matrix) override; + + /** + * @see Cantor::LinearAlgebraExtension::eigenValues + */ virtual QString eigenValues(const QString &matrix) override; }; +/** + * Implementation of packaging wizards for Julia + */ class JuliaPackagingExtension: public Cantor::PackagingExtension { public: JULIA_EXT_CDTOR_DECL(Packaging) + /** + * @see Cantor::PackagingExtension::importPackage + */ virtual QString importPackage(const QString &module) override; }; +/** + * Implementation of plot wizards for Julia + * + * Plotting is based on GR package + */ class JuliaPlotExtension: public Cantor::PlotExtension { public: JULIA_EXT_CDTOR_DECL(Plot) + /** + * @see Cantor::PlotExtension::plotFunction2d + */ virtual QString plotFunction2d( const QString &function, const QString &variable, const QString &left, const QString &right) override; + /** + * @see Cantor::PlotExtension::plotFunction3d + */ virtual QString plotFunction3d( const QString &function, VariableParameter var1, VariableParameter var2) override; }; +/** + * Implementation of script wizard for Julia + */ class JuliaScriptExtension: public Cantor::ScriptExtension { public: JULIA_EXT_CDTOR_DECL(Script) + /** + * @see Cantor::ScriptExtension::scriptFileFilter + */ virtual QString scriptFileFilter() override; + + /** + * @see Cantor::ScriptExtension::highlightingMode + */ virtual QString highlightingMode() override; + + /** + * @see Cantor::ScriptExtension::runExternalScript + */ virtual QString runExternalScript(const QString &path) override; }; +/** + * Julia variable management extension + * + * Based on JLD package for loading/saving variables + */ class JuliaVariableManagementExtension: public Cantor::VariableManagementExtension { public: JULIA_EXT_CDTOR_DECL(VariableManagement) + // There is no way to completely delete object from scope: + // http://docs.julialang.org/en/release-0.4/manual/faq/#how-do-i-delete-an-object-in-memory + // So we are saving special marker to variable to mark it as removed static const QString REMOVED_VARIABLE_MARKER; + /** + * @see Cantor::VariableManagementExtension::addVariable + */ virtual QString addVariable( const QString &name, const QString &value) override; + /** + * @see Cantor::VariableManagementExtension::setValue + */ virtual QString setValue( const QString &name, const QString &value) override; + /** + * @see Cantor::VariableManagementExtension::removeVariable + */ virtual QString removeVariable(const QString &name) override; + + /** + * @see Cantor::VariableManagementExtension::saveVariables + */ virtual QString saveVariables(const QString &fileName) override; + + /** + * @see Cantor::VariableManagementExtension::loadVariables + */ virtual QString loadVariables(const QString &fileName) override; + + /** + * @see Cantor::VariableManagementExtension::clearVariables + */ virtual QString clearVariables() override; }; diff --git a/src/backends/julia/juliahighlighter.h b/src/backends/julia/juliahighlighter.h --- a/src/backends/julia/juliahighlighter.h +++ b/src/backends/julia/juliahighlighter.h @@ -21,18 +21,40 @@ #include "defaulthighlighter.h" +/** + * Implementation of JuliaHighlighter + * + * Takes into account loaded symbols from scope and predefined keywords. + * There is no common regexps that bound to fail with such syntax-overloaded + * languages as Julia + */ class JuliaHighlighter: public Cantor::DefaultHighlighter { Q_OBJECT public: + /** + * Constructs JuliaHighlighter + * + * @param parent QObject parent + */ JuliaHighlighter(QObject *parent); virtual ~JuliaHighlighter() {} public Q_SLOTS: + /** + * Call this to update highlighter to the current state of keywords storage + */ void updateHighlight(); protected: + /** + * @see Cantor::DefaultHighlighter::highlightBlock + */ virtual void highlightBlock(const QString &text) override; + + /** + * @see Cantor::DefaultHighlighter::nonSeparatingCharacters + */ virtual QString nonSeparatingCharacters() const override; }; diff --git a/src/backends/julia/juliahighlighter.cpp b/src/backends/julia/juliahighlighter.cpp --- a/src/backends/julia/juliahighlighter.cpp +++ b/src/backends/julia/juliahighlighter.cpp @@ -41,23 +41,34 @@ // Do some backend independent highlighting (brackets etc.) DefaultHighlighter::highlightBlock(text); + // Now we are about to make corrent strings and comments highlighting + // + // Main idea: as soon as string starts comment or anything else cant start + // until current string ends. The same with comment, except '#' comment + // that ends by newline + // + // To pass information to next block, we are using next states const int IN_MULTILINE_COMMENT = 1; const int IN_CHARACTER = 2; const int IN_SINGLE_QUOTE_STRING = 4; const int IN_TRIPLE_QUOTE_STRING = 8; + // Markers of scopes start, ends QRegExp multiLineCommentStart(QLatin1String("#=")); QRegExp multiLineCommentEnd(QLatin1String("=#")); QRegExp characterStartEnd(QLatin1String("'")); QRegExp singleQuoteStringStartEnd(QLatin1String("\"")); QRegExp tripleQuoteStringStartEnd(QLatin1String("\"\"\"")); QRegExp singleLineCommentStart(QLatin1String("#(?!=)")); + // Get current state int state = previousBlockState(); if (state == -1) { state = 0; } + // This 4 arrays establish matching between state, start marker, end marker + // and format to apply QList flags = { IN_TRIPLE_QUOTE_STRING, IN_SINGLE_QUOTE_STRING, @@ -83,35 +94,41 @@ commentFormat() }; - int pos = 0; + int pos = 0; // current position in block while (pos < text.length()) { // Trying to close current environments bool triggered = false; for (int i = 0; i < flags.size() and not triggered; i++) { int flag = flags[i]; QRegExp ®exp = regexps_ends[i]; QTextCharFormat &format = formats[i]; - if (state & flag) { + if (state & flag) { // Found current state + // find where end marker is int new_pos = regexp.indexIn(text, pos); int length; if (new_pos == -1) { + // not in this block, highlight till the end length = text.length() - pos; } else { + // highlight untill the marker and modify state length = new_pos - pos + regexp.matchedLength(); state -= flag; } + // Apply format to the found area setFormat(pos, length, format); pos = pos + length; triggered = true; } } - if (triggered) { + if (triggered) { // We have done something move to next iteration continue; } - QRegExp *minRegexp = nullptr; - int minPos = INT_MAX; - int minIdx = -1; + // Now we should found the scope that start the closest to current + // position + QRegExp *minRegexp = nullptr; // closest marker + int minPos = INT_MAX; // closest pos + int minIdx = -1; // closest scope index for (int i = 0; i < regexps_starts.size(); i++) { QRegExp ®exp = regexps_starts[i]; int newPos = regexp.indexIn(text, pos); @@ -122,18 +139,21 @@ } } + // Check where single line comment starts int singleLineCommentStartPos = singleLineCommentStart.indexIn(text, pos); if (singleLineCommentStartPos != -1 and singleLineCommentStartPos < minPos) { + // single line comment starts earlier setFormat(pos, text.length() - pos, commentFormat()); break; } else if (minRegexp) { + // We are going to another scope state += flags[minIdx]; pos = minPos + minRegexp->matchedLength(); setFormat(minPos, minRegexp->matchedLength(), formats[minIdx]); - } else { + } else { // There is nothing to highlight break; } } @@ -143,14 +163,15 @@ void JuliaHighlighter::updateHighlight() { + // Remove rules for outdated variables and functions for (const auto &var : JuliaKeywords::instance()->removedVariables()) { removeRule(var); } - for (const auto &func : JuliaKeywords::instance()->removedFunctions()) { removeRule(func); } + // Add actual variables and function addVariables(JuliaKeywords::instance()->variables()); addFunctions(JuliaKeywords::instance()->functions()); rehighlight(); diff --git a/src/backends/julia/juliakeywords.h b/src/backends/julia/juliakeywords.h --- a/src/backends/julia/juliakeywords.h +++ b/src/backends/julia/juliakeywords.h @@ -21,37 +21,88 @@ #include +/** + * Keywords storage for Julia session + * + * Class is implemented with singleton pattern + */ class JuliaKeywords { public: + /** + * @return singleton instance pointer + */ static JuliaKeywords *instance(); + /** + * @return list of Julia language predefined keywords + */ const QStringList &keywords() const { return m_keywords; } + + /** + * @return list of predefined commands, that are capable to show plot + */ const QStringList &plotShowingCommands() const { return m_plotShowingCommands; } + /** + * @return list of known variable names + */ const QStringList &variables() const { return m_variables; } + + /** + * @return list of variables removed during the last clearVariables() call + */ const QStringList &removedVariables() const { return m_removedVariables; } + + /** + * Clears all known variables + */ void clearVariables(); + + /** + * Add new variable to the known list + * + * @param variable name of the variable to add + */ void addVariable(const QString &variable); + /** + * @return list of known function names + */ const QStringList &functions() const { return m_functions; } + + /** + * @return list of functions removed during the last clearFunctions() call + */ const QStringList &removedFunctions() const { return m_removedFunctions; } + + /** + * Clears all known functions + */ void clearFunctions(); + + /** + * Add new function to the known list + * + * @param function name of the function to add + */ void addFunction(const QString &function); private: - QStringList m_keywords; - QStringList m_plotShowingCommands; - QStringList m_variables; - QStringList m_removedVariables; - QStringList m_functions; - QStringList m_removedFunctions; + QStringList m_keywords; //< list of predefined keywords + QStringList m_plotShowingCommands; //< list of predefined plot showing cmds + QStringList m_variables; //< list of variables known at the moment + QStringList m_removedVariables; //< list of variables removed during cleaning + QStringList m_functions; //< list of known function at the moment + QStringList m_removedFunctions; //< list of functions removed during cleaning + // We are hidding constructor and destructor for singleton JuliaKeywords() {} ~JuliaKeywords() {} + /// Do first load of predefined stuff from keywords.xml void loadFromFile(); }; diff --git a/src/backends/julia/juliaserver/juliaserver.h b/src/backends/julia/juliaserver/juliaserver.h --- a/src/backends/julia/juliaserver/juliaserver.h +++ b/src/backends/julia/juliaserver/juliaserver.h @@ -22,6 +22,13 @@ #include #include +/** + * Implementation of command execution server with DBus interface for Julia + * language. + * + * Uses Julia embedding + * http://docs.julialang.org/en/release-0.4/manual/embedding/ to get results. + */ class JuliaServer: public QObject { Q_OBJECT @@ -31,14 +38,39 @@ virtual ~JuliaServer(); public Q_SLOTS: + /** + * Initializer for JuliaServer. Call this first before using it + * + * @param path path to julia executable + */ Q_SCRIPTABLE void login(const QString &path) const; + + /** + * Runs a piece of julia code. After this returns use getOutput, getError, + * getWasException methods to retrieve execution result. + * + * @param command maybe multiline piece of julia code to run + */ Q_SCRIPTABLE void runJuliaCommand(const QString &command); + + /** + * @return stdout output of the last command execution + */ Q_SCRIPTABLE QString getOutput() const; + + /** + * @return stderr output of the last command exection + */ Q_SCRIPTABLE QString getError() const; + + /** + * @return indicator that exception was triggered during last command + * execution + */ Q_SCRIPTABLE bool getWasException() const; private: - QString m_error; - QString m_output; - bool m_was_exception; + QString m_error; //< Stores last stderr output + QString m_output; //< Stores last stdout output + bool m_was_exception; //< Stores indicator of exception }; diff --git a/src/backends/julia/juliaserver/juliaserver.cpp b/src/backends/julia/juliaserver/juliaserver.cpp --- a/src/backends/julia/juliaserver/juliaserver.cpp +++ b/src/backends/julia/juliaserver/juliaserver.cpp @@ -45,6 +45,7 @@ void JuliaServer::runJuliaCommand(const QString &command) { + // Redirect stdout, stderr to temprorary files QTemporaryFile output, error; if (not output.open() or not error.open()) { qFatal("Unable to create temprorary files for stdout/stderr"); @@ -61,10 +62,13 @@ .arg(error.fileName()).toLatin1().constData() ); + // Run command jl_value_t *val = static_cast( jl_eval_string(command.toLatin1().constData()) ); - if (jl_exception_occurred()) { + + if (jl_exception_occurred()) { // If exception occured + // Show it to user in stderr jl_value_t *ex = jl_exception_in_transit; jl_printf(JL_STDERR, "error during run:\n"); jl_function_t *showerror = @@ -78,7 +82,8 @@ jl_call3(showerror, err_stream, ex, bt); jl_exception_clear(); m_was_exception = true; - } else if (val) { + } else if (val) { // no exception occured + // If last result is not nothing, show it jl_function_t *equality = jl_get_function(jl_base_module, "=="); jl_value_t *nothing = static_cast(jl_eval_string("nothing")); @@ -90,11 +95,13 @@ } m_was_exception = false; } + // Clean up streams and files jl_eval_string("flush(STDOUT)"); jl_eval_string("flush(STDERR)"); jl_eval_string("redirect_stdout(__originalSTDOUT__)"); jl_eval_string("redirect_stderr(__originalSTDERR__)"); + // Clean up variables auto vars_to_remove = { "__originalSTDOUT__", "__originalSTDERR__" }; diff --git a/src/backends/julia/juliasession.h b/src/backends/julia/juliasession.h --- a/src/backends/julia/juliasession.h +++ b/src/backends/julia/juliasession.h @@ -31,60 +31,143 @@ class DefaultVariableModel; } +/** + * Implements a Cantor session for the Julia backend + * + * It communicates through DBus interface with JuliaServer + */ class JuliaSession: public Cantor::Session { Q_OBJECT public: + /** + * Constructs session + * + * @param backend owning backend + */ JuliaSession(Cantor::Backend *backend); virtual ~JuliaSession() {} + /** + * @see Cantor::Session::login + */ virtual void login() override; + + /** + * @see Cantor::Session::logout + */ virtual void logout() override; + /** + * @see Cantor::Session::interrupt + */ virtual void interrupt() override; + /** + * @see Cantor::Session::evaluateExpression + */ virtual Cantor::Expression *evaluateExpression( const QString &command, Cantor::Expression::FinishingBehavior behave) override; + /** + * @see Cantor::Session::completionFor + */ virtual Cantor::CompletionObject *completionFor( const QString &cmd, int index = -1) override; + /** + * @see Cantor::Session::syntaxHighlighter + */ virtual QSyntaxHighlighter *syntaxHighlighter(QObject *parent); + + /** + * @see Cantor::Session::variableModel + */ virtual QAbstractItemModel *variableModel() override; + /** + * @return indicator if config says to integrate plots into worksheet + */ bool integratePlots(); Q_SIGNALS: + /** + * Emit this to update syntax highlighter + */ void updateHighlighter(); private Q_SLOTS: + /** + * Called when async call to JuliaServer is finished + */ void onResultReady(); private: - KProcess *m_process; - QDBusInterface *m_interface; + KProcess *m_process; //< process to run JuliaServer inside + QDBusInterface *m_interface; //< interface to JuliaServer + /// Expressions running at the moment QList m_runningExpressions; - JuliaExpression *m_currentExpression; + JuliaExpression *m_currentExpression; //< current expression + /// Variable management model Cantor::DefaultVariableModel *m_variableModel; + /// Cache to speedup modules whos calls QMap m_whos_cache; friend JuliaExpression; friend JuliaCompletionObject; + /** + * Runs Julia expression + * + * @param expression expression to run + */ void runExpression(JuliaExpression *expression); + /** + * Runs Julia piece of code in synchronous mode + * + * @param command command to execute + */ void runJuliaCommand(const QString &command) const; + + /** + * Runs Julia piece of code in asynchronous mode. When finished + * onResultReady is called + * + * @param command command to execute + */ void runJuliaCommandAsync(const QString &command); + /** + * Helper method to get QString returning function result + * + * @param method DBus method to call + * @return result of the method + */ QString getStringFromServer(const QString &method); + + /** + * @return stdout of the last executed command + */ QString getOutput(); + + /** + * @return stderr of the last executed command + */ QString getError(); + + /** + * @return indicator of exception occured during the last command execution + */ bool getWasException(); + /** + * Updates variable model by querying all modules in scope with whos command + */ void listVariables(); }; diff --git a/src/backends/julia/juliasession.cpp b/src/backends/julia/juliasession.cpp --- a/src/backends/julia/juliasession.cpp +++ b/src/backends/julia/juliasession.cpp @@ -225,24 +225,28 @@ << QLatin1String("__originalSTDOUT__") << QLatin1String("__originalSTDERR__"); + // Wrapping removed marker to quotes auto rem_marker = QString::fromLatin1("\"%1\"") .arg(JuliaVariableManagementExtension::REMOVED_VARIABLE_MARKER); + // Clear current symbols JuliaKeywords::instance()->clearVariables(); JuliaKeywords::instance()->clearFunctions(); - QStringList processed_modules; - QStringList modules_to_process; - modules_to_process << QLatin1String("__GLOBAL__"); + QStringList processed_modules; // modules we have processed + QStringList modules_to_process; // modules in queue + modules_to_process << QLatin1String("__GLOBAL__"); // starting from global while (modules_to_process.size() > 0) { + // Get from queue auto module = modules_to_process.front(); modules_to_process.pop_front(); if (processed_modules.contains(module)) { continue; } processed_modules << module; + // Get whos() output, maybe from cache QString whos_output; if (module == QLatin1String("__GLOBAL__")) { runJuliaCommand(QLatin1String("whos()")); @@ -258,47 +262,54 @@ } } + // In this lists we will collect symbols to apply `show` to them + // in one DBus call QStringList batchCommands; QStringList batchTypes; QStringList batchNames; for (auto line : whos_output.split(QLatin1String("\n"))) { QString name = line.simplified().split(QLatin1String(" ")).first().simplified(); - if (name.isEmpty()) { + if (name.isEmpty()) { // some empty line continue; } QString type = line.simplified().split(QLatin1String(" ")).last().simplified(); if (ignoredVariables.contains(name)) { + // Ignored variable continue; } if (type == QLatin1String("Module")) { + // Found module, place in queue modules_to_process.append(name); continue; } if (type == QLatin1String("Function")) { + // Found function JuliaKeywords::instance()->addFunction(name); continue; } if (module != QLatin1String("__GLOBAL__")) { continue; // Don't add variables not included on global scope } + // Add to batch batchCommands << QString::fromLatin1("show(%1);").arg(name); batchTypes << type; batchNames << name; } if (batchCommands.isEmpty()) { - continue; + continue; // nothing to do } + // Run batched command runJuliaCommand( batchCommands.join(QLatin1String("print(\"__CANTOR_DELIM__\");")) ); @@ -311,11 +322,13 @@ if (type == QLatin1String("ASCIIString")) { if (value == rem_marker) { + // This is removed variable m_variableModel->removeVariable(name); continue; } } + // Register variable m_variableModel->addVariable(name, value); JuliaKeywords::instance()->addVariable(name); } diff --git a/src/backends/julia/scripts/variables_loader.jl b/src/backends/julia/scripts/variables_loader.jl --- a/src/backends/julia/scripts/variables_loader.jl +++ b/src/backends/julia/scripts/variables_loader.jl @@ -1,4 +1,6 @@ -# Variable loading script +# Variable loading script. +# +# Install JLD script with `Pkg.add(JLD)` to use it import JLD for (var_name, value) in JLD.load("%1") s = symbol(var_name) diff --git a/src/backends/julia/scripts/variables_saver.jl b/src/backends/julia/scripts/variables_saver.jl --- a/src/backends/julia/scripts/variables_saver.jl +++ b/src/backends/julia/scripts/variables_saver.jl @@ -1,4 +1,6 @@ # Variable saving script +# +# Install JLD script with `Pkg.add(JLD)` to use it import JLD JLD.jldopen("%1", "w") do file for name in names(Main)[4:end]