aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Lakhtanov <ivan.lakhtanov@gmail.com>2016-08-21 20:53:58 (GMT)
committerIvan Lakhtanov <ivan.lakhtanov@gmail.com>2016-08-24 18:44:30 (GMT)
commitc4d18c576645412af466f723729a20cf0c4fe183 (patch)
tree3c068ae04702da5fd6a44a1ca420581a566f8cee
parent8da94fe3427c7dbc2157e3385012eb69b6392e82 (diff)
Documentation for Julia backend stuff
Differential Revision: https://phabricator.kde.org/D2507
-rw-r--r--README1
-rw-r--r--README.md1
-rw-r--r--src/backends/julia/juliabackend.h42
-rw-r--r--src/backends/julia/juliacompletionobject.h23
-rw-r--r--src/backends/julia/juliaexpression.cpp3
-rw-r--r--src/backends/julia/juliaexpression.h29
-rw-r--r--src/backends/julia/juliaextensions.h99
-rw-r--r--src/backends/julia/juliahighlighter.cpp37
-rw-r--r--src/backends/julia/juliahighlighter.h22
-rw-r--r--src/backends/julia/juliakeywords.h63
-rw-r--r--src/backends/julia/juliaserver/juliaserver.cpp11
-rw-r--r--src/backends/julia/juliaserver/juliaserver.h38
-rw-r--r--src/backends/julia/juliasession.cpp23
-rw-r--r--src/backends/julia/juliasession.h89
-rw-r--r--src/backends/julia/scripts/variables_loader.jl4
-rw-r--r--src/backends/julia/scripts/variables_saver.jl2
16 files changed, 459 insertions, 28 deletions
diff --git a/README b/README
index 5e166b3..8a54941 100644
--- a/README
+++ b/README
@@ -17,6 +17,7 @@ Available Backends
- 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
index fe90777..dc9f5b5 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@ Backends.
- 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
index e208993..b79d3e6 100644
--- 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<QVariant>().
+ */
explicit JuliaBackend(
QObject *parent = 0,
const QList<QVariant> &args = QList<QVariant>());
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
index 0a3ec6c..e993e6a 100644
--- 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.cpp b/src/backends/julia/juliaexpression.cpp
index 6746a6d..27cdd85 100644
--- a/src/backends/julia/juliaexpression.cpp
+++ b/src/backends/julia/juliaexpression.cpp
@@ -38,8 +38,10 @@ void JuliaExpression::evaluate()
setStatus(Cantor::Expression::Computing);
auto juliaSession = dynamic_cast<JuliaSession *>(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 @@ void JuliaExpression::finalize()
} 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/juliaexpression.h b/src/backends/julia/juliaexpression.h
index 344c585..fd5eb23 100644
--- 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/juliaextensions.h b/src/backends/julia/juliaextensions.h
index cb4486a..21e2e09 100644
--- 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.cpp b/src/backends/julia/juliahighlighter.cpp
index 26a7ec7..4795361 100644
--- a/src/backends/julia/juliahighlighter.cpp
+++ b/src/backends/julia/juliahighlighter.cpp
@@ -41,11 +41,19 @@ void JuliaHighlighter::highlightBlock(const QString &text)
// 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("'"));
@@ -53,11 +61,14 @@ void JuliaHighlighter::highlightBlock(const QString &text)
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<int> flags = {
IN_TRIPLE_QUOTE_STRING,
IN_SINGLE_QUOTE_STRING,
@@ -83,7 +94,7 @@ void JuliaHighlighter::highlightBlock(const QString &text)
commentFormat()
};
- int pos = 0;
+ int pos = 0; // current position in block
while (pos < text.length()) {
// Trying to close current environments
bool triggered = false;
@@ -91,27 +102,33 @@ void JuliaHighlighter::highlightBlock(const QString &text)
int flag = flags[i];
QRegExp &regexp = 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 &regexp = regexps_starts[i];
int newPos = regexp.indexIn(text, pos);
@@ -122,18 +139,21 @@ void JuliaHighlighter::highlightBlock(const QString &text)
}
}
+ // 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::highlightBlock(const QString &text)
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/juliahighlighter.h b/src/backends/julia/juliahighlighter.h
index a112732..6fb54ee 100644
--- 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/juliakeywords.h b/src/backends/julia/juliakeywords.h
index 3ea16a0..d58ddd6 100644
--- a/src/backends/julia/juliakeywords.h
+++ b/src/backends/julia/juliakeywords.h
@@ -21,37 +21,88 @@
#include <QStringList>
+/**
+ * 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.cpp b/src/backends/julia/juliaserver/juliaserver.cpp
index 736bc2c..c9beb4c 100644
--- a/src/backends/julia/juliaserver/juliaserver.cpp
+++ b/src/backends/julia/juliaserver/juliaserver.cpp
@@ -45,6 +45,7 @@ void JuliaServer::login(const QString &path) const
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 @@ void JuliaServer::runJuliaCommand(const QString &command)
.arg(error.fileName()).toLatin1().constData()
);
+ // Run command
jl_value_t *val = static_cast<jl_value_t *>(
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 @@ void JuliaServer::runJuliaCommand(const QString &command)
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_value_t *>(jl_eval_string("nothing"));
@@ -90,11 +95,13 @@ void JuliaServer::runJuliaCommand(const QString &command)
}
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/juliaserver/juliaserver.h b/src/backends/julia/juliaserver/juliaserver.h
index 0cb16e2..be76e6d 100644
--- a/src/backends/julia/juliaserver/juliaserver.h
+++ b/src/backends/julia/juliaserver/juliaserver.h
@@ -22,6 +22,13 @@
#include <QObject>
#include <QString>
+/**
+ * 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 @@ public:
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/juliasession.cpp b/src/backends/julia/juliasession.cpp
index 7958280..d4fcebf 100644
--- a/src/backends/julia/juliasession.cpp
+++ b/src/backends/julia/juliasession.cpp
@@ -225,17 +225,20 @@ void JuliaSession::listVariables()
<< 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)) {
@@ -243,6 +246,7 @@ void JuliaSession::listVariables()
}
processed_modules << module;
+ // Get whos(<module here>) output, maybe from cache
QString whos_output;
if (module == QLatin1String("__GLOBAL__")) {
runJuliaCommand(QLatin1String("whos()"));
@@ -258,6 +262,8 @@ void JuliaSession::listVariables()
}
}
+ // In this lists we will collect symbols to apply `show` to them
+ // in one DBus call
QStringList batchCommands;
QStringList batchTypes;
QStringList batchNames;
@@ -265,7 +271,7 @@ void JuliaSession::listVariables()
QString name =
line.simplified().split(QLatin1String(" ")).first().simplified();
- if (name.isEmpty()) {
+ if (name.isEmpty()) { // some empty line
continue;
}
@@ -273,15 +279,18 @@ void JuliaSession::listVariables()
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;
}
@@ -290,15 +299,17 @@ void JuliaSession::listVariables()
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 @@ void JuliaSession::listVariables()
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/juliasession.h b/src/backends/julia/juliasession.h
index 9f5a787..d101956 100644
--- a/src/backends/julia/juliasession.h
+++ b/src/backends/julia/juliasession.h
@@ -31,60 +31,143 @@ namespace Cantor {
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<JuliaExpression *> m_runningExpressions;
- JuliaExpression *m_currentExpression;
+ JuliaExpression *m_currentExpression; //< current expression
+ /// Variable management model
Cantor::DefaultVariableModel *m_variableModel;
+ /// Cache to speedup modules whos calls
QMap<QString, QString> 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/scripts/variables_loader.jl b/src/backends/julia/scripts/variables_loader.jl
index a649e06..6daf31e 100644
--- 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
index b5762b0..a97143c 100644
--- 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]