diff --git a/src/backends/julia/CMakeLists.txt b/src/backends/julia/CMakeLists.txt
--- a/src/backends/julia/CMakeLists.txt
+++ b/src/backends/julia/CMakeLists.txt
@@ -5,6 +5,10 @@
juliabackend.cpp
juliasession.cpp
juliaexpression.cpp
+ juliakeywords.cpp
+ juliahighlighter.cpp
)
-add_backend(juliabackend ${JuliaBackend_SRCS})
+qt5_add_resources(JuliaBackend_RSCS julia.qrc)
+
+add_backend(juliabackend ${JuliaBackend_SRCS} ${JuliaBackend_RSCS})
diff --git a/src/backends/julia/julia.qrc b/src/backends/julia/julia.qrc
new file mode 100644
--- /dev/null
+++ b/src/backends/julia/julia.qrc
@@ -0,0 +1,6 @@
+
+
+
+ keywords.xml
+
+
diff --git a/src/backends/julia/juliabackend.cpp b/src/backends/julia/juliabackend.cpp
--- a/src/backends/julia/juliabackend.cpp
+++ b/src/backends/julia/juliabackend.cpp
@@ -40,7 +40,7 @@
Cantor::Backend::Capabilities JuliaBackend::capabilities() const
{
- return Cantor::Backend::Nothing;
+ return Cantor::Backend::SyntaxHighlighting;
}
K_PLUGIN_FACTORY_WITH_JSON(
diff --git a/src/backends/julia/juliahighlighter.h b/src/backends/julia/juliahighlighter.h
new file mode 100644
--- /dev/null
+++ b/src/backends/julia/juliahighlighter.h
@@ -0,0 +1,38 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * ---
+ * Copyright (C) 2016 Ivan Lakhtanov
+ */
+#pragma once
+
+#include "defaulthighlighter.h"
+
+class JuliaHighlighter: public Cantor::DefaultHighlighter
+{
+ Q_OBJECT
+
+public:
+ JuliaHighlighter(QObject *parent);
+ virtual ~JuliaHighlighter() {}
+
+public Q_SLOTS:
+ void updateHighlight();
+
+protected:
+ virtual void highlightBlock(const QString &text) override;
+ virtual QString nonSeparatingCharacters() const override;
+};
diff --git a/src/backends/julia/juliahighlighter.cpp b/src/backends/julia/juliahighlighter.cpp
new file mode 100644
--- /dev/null
+++ b/src/backends/julia/juliahighlighter.cpp
@@ -0,0 +1,155 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * ---
+ * Copyright (C) 2016 Ivan Lakhtanov
+ */
+
+#include "juliahighlighter.h"
+#include "juliakeywords.h"
+
+#include
+#include
+
+JuliaHighlighter::JuliaHighlighter(QObject *parent)
+ : Cantor::DefaultHighlighter(parent)
+{
+ addRule(QRegExp(QLatin1String("\\b\\w+(?=\\()")), functionFormat());
+
+ // Code highlighting the different keywords
+ addKeywords(JuliaKeywords::instance()->keywords());
+ addVariables(JuliaKeywords::instance()->variables());
+}
+
+void JuliaHighlighter::highlightBlock(const QString &text)
+{
+ if (skipHighlighting(text)) {
+ return;
+ }
+
+ // Do some backend independent highlighting (brackets etc.)
+ DefaultHighlighter::highlightBlock(text);
+
+ 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;
+
+ QRegExp multiLineCommentStart(QLatin1String("#="));
+ QRegExp multiLineCommentEnd(QLatin1String("=#"));
+ QRegExp characterStartEnd(QLatin1String("'"));
+ QRegExp singleQuoteStringStartEnd(QLatin1String("\""));
+ QRegExp tripleQuoteStringStartEnd(QLatin1String("\"\"\""));
+ QRegExp singleLineCommentStart(QLatin1String("#(?!=)"));
+
+ int state = previousBlockState();
+ if (state == -1) {
+ state = 0;
+ }
+
+ QList flags = {
+ IN_TRIPLE_QUOTE_STRING,
+ IN_SINGLE_QUOTE_STRING,
+ IN_CHARACTER,
+ IN_MULTILINE_COMMENT
+ };
+ QList regexps_starts = {
+ tripleQuoteStringStartEnd,
+ singleQuoteStringStartEnd,
+ characterStartEnd,
+ multiLineCommentStart
+ };
+ QList regexps_ends = {
+ tripleQuoteStringStartEnd,
+ singleQuoteStringStartEnd,
+ characterStartEnd,
+ multiLineCommentEnd
+ };
+ QList formats = {
+ stringFormat(),
+ stringFormat(),
+ stringFormat(),
+ commentFormat()
+ };
+
+ int pos = 0;
+ 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) {
+ int new_pos = regexp.indexIn(text, pos);
+ int length;
+ if (new_pos == -1) {
+ length = text.length() - pos;
+ } else {
+ length = new_pos - pos + regexp.matchedLength();
+ state -= flag;
+ }
+ setFormat(pos, length, format);
+ pos = pos + length;
+ triggered = true;
+ }
+ }
+ if (triggered) {
+ continue;
+ }
+
+ QRegExp *minRegexp = nullptr;
+ int minPos = INT_MAX;
+ int minIdx = -1;
+ for (int i = 0; i < regexps_starts.size(); i++) {
+ QRegExp ®exp = regexps_starts[i];
+ int newPos = regexp.indexIn(text, pos);
+ if (newPos != -1) {
+ minPos = qMin(minPos, newPos);
+ minRegexp = ®exp;
+ minIdx = i;
+ }
+ }
+
+ int singleLineCommentStartPos =
+ singleLineCommentStart.indexIn(text, pos);
+
+ if (singleLineCommentStartPos != -1
+ and singleLineCommentStartPos < minPos) {
+ setFormat(pos, text.length() - pos, commentFormat());
+ break;
+ } else if (minRegexp) {
+ state += flags[minIdx];
+ pos = minPos + minRegexp->matchedLength();
+ setFormat(minPos, minRegexp->matchedLength(), formats[minIdx]);
+ } else {
+ break;
+ }
+ }
+
+ setCurrentBlockState(state);
+}
+
+void JuliaHighlighter::updateHighlight()
+{
+ addVariables(JuliaKeywords::instance()->variables());
+ rehighlight();
+}
+
+QString JuliaHighlighter::nonSeparatingCharacters() const
+{
+ return QLatin1String("[\\w\\u00A1-\\uFFFF!]");
+}
diff --git a/src/backends/julia/juliakeywords.h b/src/backends/julia/juliakeywords.h
new file mode 100644
--- /dev/null
+++ b/src/backends/julia/juliakeywords.h
@@ -0,0 +1,40 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * ---
+ * Copyright (C) 2016 Ivan Lakhtanov
+ */
+#pragma once
+
+#include
+
+class JuliaKeywords
+{
+public:
+ static JuliaKeywords* instance();
+
+ const QStringList &keywords() const { return m_keywords; }
+ const QStringList &variables() const { return m_variables; }
+
+private:
+ QStringList m_keywords;
+ QStringList m_variables;
+
+ JuliaKeywords() {}
+ ~JuliaKeywords() {}
+
+ void loadFromFile();
+};
diff --git a/src/backends/julia/juliakeywords.cpp b/src/backends/julia/juliakeywords.cpp
new file mode 100644
--- /dev/null
+++ b/src/backends/julia/juliakeywords.cpp
@@ -0,0 +1,81 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * ---
+ * Copyright (C) 2016 Ivan Lakhtanov
+ */
+#include "juliakeywords.h"
+
+#include
+#include
+#include
+
+#include
+
+JuliaKeywords *JuliaKeywords::instance()
+{
+ static JuliaKeywords *inst = 0;
+ if (inst == 0) {
+ inst = new JuliaKeywords();
+ inst->loadFromFile();
+ qSort(inst->m_variables);
+ qSort(inst->m_keywords);
+ }
+
+ return inst;
+}
+
+void JuliaKeywords::loadFromFile()
+{
+ //load the known keywords from an xml file
+ QFile file(QLatin1String(":xml/keywords.xml"));
+
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning() << "error opening keywords.xml file. highlighting and"
+ << " completion won't work";
+ return;
+ }
+
+ QXmlStreamReader xml(&file);
+
+ xml.readNextStartElement();
+ while (xml.readNextStartElement()) {
+ const QStringRef name = xml.name();
+
+ if (name == QLatin1String("keywords")
+ || name == QLatin1String("variables")) {
+ while (xml.readNextStartElement()) {
+ Q_ASSERT(
+ xml.isStartElement() && xml.name() == QLatin1String("word")
+ );
+
+ const QString text = xml.readElementText();
+
+ if (name == QLatin1String("keywords")) {
+ m_keywords << text;
+ } else if (name == QLatin1String("variables")) {
+ m_variables << text;
+ }
+ }
+ } else {
+ xml.skipCurrentElement();
+ }
+ }
+
+ if (xml.hasError()) {
+ qWarning() << "Error parsing keywords.xml: " << xml.errorString();
+ }
+}
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
@@ -45,6 +45,8 @@
const QString &cmd,
int index = -1) override;
+ virtual QSyntaxHighlighter *syntaxHighlighter(QObject *parent);
+
private Q_SLOTS:
void onResultReady();
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
@@ -27,6 +27,7 @@
#include
#include "juliaexpression.h"
+#include "juliahighlighter.h"
JuliaSession::JuliaSession(Cantor::Backend *backend)
: Session(backend)
@@ -131,6 +132,12 @@
return nullptr;
}
+QSyntaxHighlighter *JuliaSession::syntaxHighlighter(QObject* parent)
+{
+ JuliaHighlighter *highlighter = new JuliaHighlighter(parent);
+ return highlighter;
+}
+
void JuliaSession::runJuliaCommand(const QString &command) const
{
m_interface->call(QLatin1String("runJuliaCommand"), command);
diff --git a/src/backends/julia/keywords.xml b/src/backends/julia/keywords.xml
new file mode 100644
--- /dev/null
+++ b/src/backends/julia/keywords.xml
@@ -0,0 +1,44 @@
+
+
+
+ true
+ false
+ nothing
+ NaN
+ Inf
+
+
+ if
+ else
+ elseif
+ while
+ for
+ begin
+ let
+ end
+ do
+ try
+ catch
+ finally
+ return
+ break
+ continue
+ global
+ local
+ const
+ export
+ import
+ importall
+ using
+ function
+ macro
+ module
+ baremodule
+ type
+ immutable
+ quote
+ typealias
+ abstract
+ bitstype
+
+