diff --git a/org.kde.cantor.appdata.xml b/org.kde.cantor.appdata.xml index cae857c3..e3cb51b3 100644 --- a/org.kde.cantor.appdata.xml +++ b/org.kde.cantor.appdata.xml @@ -1,116 +1,117 @@ org.kde.cantor.desktop CC0-1.0 GPL-2.0+ Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor Cantor xxCantorxx Cantor Cantor KDE Frontend to Mathematical Software Frontal del KDE per a programari matemàtic Frontal del KDE per a programari matemàtic Uživatelské rozhraní matematického softwaru pro KDE Eine KDE-Oberfläche für mathematische Software KDE Frontend to Mathematical Software Interfaz de KDE para software matemático KDE matemaatikatarkvara kasutajaliides KDE:n käyttöliittymä matemaattisille ohjelmistoille Interface KDE pour les logiciels de mathématiques Interface de KDE de software matemático Interfaccia KDE per software matematico KDE-Böversiet för Rekenprogrammen KDE-frontend tot wiskundige software KDE-grensesnitt til matematikkprogram Nakładka KDE dla oprogramowania matematycznego Interface para KDE de Aplicações Matemáticas Interface do KDE para software matemático Оболочка к системам компьютерной алгебры для KDE KDE Frontend pre matematický softvér KDE-jevo začelje za matematično programsko opremo KDE-gränssnitt till matematisk programvara Matematiksel Yazılım için bir KDE Önyüzü. Графічна оболонка KDE до математичного програмного забезпечення xxKDE Frontend to Mathematical Softwarexx 数学软件的 KDE 前端 KDE 數學軟體的前端介面

Cantor is a front-end to powerful mathematics and statistics packages. Cantor integrates them into the KDE Platform and provides a nice, worksheet-based, graphical user interface. It supports environments for KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, and Qalculate!

El Cantor és un frontal a paquets matemàtics i estadístics potents. El Cantor els integra en la plataforma del KDE i proporciona una interfície gràfica d'usuari agradable i basada en fulls de càlcul. Admet entorns pel KAlgebra, el Lua, el Maxima, el R, el Sage, l'Octave, el Python, l'Scilab, i el Qalculate.

El Cantor és un frontal a paquets matemàtics i estadístics potents. El Cantor els integra en la plataforma del KDE i proporciona una interfície gràfica d'usuari agradable i basada en fulls de càlcul. Admet entorns pel KAlgebra, el Lua, el Maxima, el R, el Sage, l'Octave, el Python, l'Scilab, i el Qalculate.

Cantor ist ein Bedienoberfläche zu leistungsfähigen Mathematik- und Statistik-Paketen. Cantor integriert sie in die KDE-Plattform und bietet eine grafische Benutzeroberfläche auf der Grundlage von Arbeitsblättern. Es unterstützt Umgebungen für KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, und Qalculate!

Cantor is a front-end to powerful mathematics and statistics packages. Cantor integrates them into the KDE Platform and provides a nice, worksheet-based, graphical user interface. It supports environments for KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, and Qalculate!

Cantor es una interfaz para potentes paquetes matemáticos y estadísticos. Cantor los integra en la Plataforma de KDE y proporciona una elegante interfaz de usuario gráfica basada en hojas de trabajo. Permite usar entornos para KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab y Qalculate!

Cantor on võimsate matemaatika- ja statistikapakettide kasutajaliides. Cantor lõimib nad KDE platvormi ja pakub neile kena, töölehepõhise graafilise kasutajaliidese. Toetatud on KAlgebra, Lua, Maxima, R-i, Sage, Octave'i, Pythoni, Scilabi ja Qalculate! keskkonnad.

Cantor on käyttöliittymä tehokkaille matematiikka- ja tilastolaskentapaketeille. Cantor integroi ne KDE-ympäristöön ja tarjoaa mukavan työkirjapohjaisen graafisen käyttöliittymän. Cantor tukee seuraavia ympäristöjä: KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, ja Qalculate!

Cantor est une interface pour des outils mathématiques puissants. Il permet d'intégrer ces outils au sein de la plate-forme KDE et fournit une interface graphique agréable. Il prend en charge les environnements pour KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab and Qalculate !

Cantor é unha interface gráfica para potentes paquetes de matemática e estatística. Cantor intégraos na plataforma de KDE e fornece unha boa interface gráfica de usuario baseada en follas de cálculo. É compatíbel com ambientes para KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, e Qalculate!

Cantor è un'interfaccia a potenti pacchetti di matematica e statistica. Cantor li integra nella piattaforma di KDE e fornisce una gradevole interfaccia grafica basata su fogli di lavoro. Supporta KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab e Qalculate!

Cantor is en Böversiet för en Reeg deegt Mathematik- un Statistik-Paketen. Cantor integreert de na KDE un stellt en smuck graafsche Böversiet mit Arbeitblääd praat. Dat ünnerstütt Ümgeven för KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, un Qalculate!

Cantor is een zogenaamd frontend tussen de gebruiker en krachtige pakketten voor wiskunde en statistiek. Cantor integreert die in het KDE-platform en is hiervoor een geschikte grafische tussenlaag (interface) op basis van een rekenblad (spreadsheet). Ondersteund worden omgevingen voor KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, and Qalculate!

Cantor jest nakładką na zaawansowane pakiety matematyczne i statystyczne. Cantor integruje je z Platformą KDE i dostarcza przyjemnego, opartego na arkuszach roboczych, graficznego układu sterowania. Obsługuje środowiska takie jak: KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab oraz Qalculate!

O Cantor é uma interface para diversos pacotes poderosos de matemática e estatística. O Cantor integra-os na Plataforma do KDE e oferece uma interface gráfica agradável e baseada em folhas de trabalho. Suporta ambientes para o KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab e Qalculate!

Cantor é uma interface para os pacotes de matemática e estatísticas poderosa. O Cantor integra-as na plataforma do KDE e oferece uma interface gráfica agradável e baseada numa folha de trabalho. Ele tem suporte aos ambientes para KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab e Qalculate!

Cantor — программа для удобной работы с математическими и статистическими пакетами. Обладает графическим интерфейсом, позволяющим параллельно работать с несколькими документами. Поддерживаются системы компьютерной алгебры и языки KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab и Qalculate!

Cantor je frontend pre mocné matematické a štatistické balíky. Integruje ich do KDE platformy a poskytuje pekné, listovo založené grafické používateľské prostredie. Podporuje prostredia pre KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab a Qalculate!

Cantor je začelje za zmogljive matematične in statistične pakete. Cantor jih vgradi v okolje KDE in ponuja lep grafični uporabniški vmesnik, ki temelji na preglednicah. Podpira okolja za KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, in Qalculate!

Cantor är ett gränssnitt till kraftfulla matematiska och statistiska paket. Cantor integrerar dem med KDE:s plattform och tillhandahåller ett snyggt, arbetsbladsbaserat, grafiskt användargränssnitt. Det stödjer miljöer för Kalgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab och Qalculate!.

Cantor güçlü matematik ve istatistik paketleri için bir önyüzdür. Cantor onları KDE Platformunda tümleştirir ve güzel, çalışma sayfası temelli bir grafik arayüz sağlar. KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, ve Qalculate gibi ortamları destekler.

Cantor> — графічна оболонка до потужних програм обробки математичних та статистичних даних. Cantor інтегрує ці програми до платформи KDE і надає користувачами зручний заснований на обчислювальних аркушах графічний інтерфейс. Передбачено підтримку роботи у режимі оболонок до KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab та Qalculate!

xxCantor is a front-end to powerful mathematics and statistics packages. Cantor integrates them into the KDE Platform and provides a nice, worksheet-based, graphical user interface. It supports environments for KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab, and Qalculate!xx

Cantor 是一个强大的数学和统计学工具包的前端。Cantor 将它们集成到 KDE 平台并提供了美观,基于工作表的图形用户界面。它支持 KAlgebra,Lua,Maxima,R,Sage,Octave,Python,Scilab 和 Qalculate 环境!

Cantor 是一套強大的數學與統計軟體套件的前端介面。Cantor 會將它們整合到 KDE 並提供一套工作表式的圖形介面。它之援 KAlgebra, Lua, Maxima, R, Sage, Octave, Python, Scilab 與 Qalculate 的環境。

http://edu.kde.org/cantor/ https://bugs.kde.org/enter_bug.cgi?format=guided&product=cantor http://docs.kde.org/stable/en/kdeedu/cantor/index.html https://www.kde.org/community/donations/?app=cantor&source=appdata Using Maxima backend of Cantor Usant el dorsal Maxima del Cantor Usant el dorsal Maxima del Cantor Maxima-Modul in Cantor Using Maxima backend of Cantor Usando el motor Maxima de Cantor Usando a infraestrutura de Maxima de Cantor De Maxima-backend van Cantor gebruiken + Używa silnika Maxima Cantora Uso da infra-estrutura de Maxima do Cantor Usando a infraestrutura Maxima do Cantor Användning av bakgrundsprogrammet Maxima i Cantor Використання модуля Maxima Cantor xxUsing Maxima backend of Cantorxx 使用 Cantor 的 Maxima 后端 使用 Cantor 的 Maxima 後端 http://kde.org/images/screenshots/cantor.png KDE cantor
diff --git a/src/backends/R/rserver/rserver.cpp b/src/backends/R/rserver/rserver.cpp index 05e29e68..6ebb36bb 100644 --- a/src/backends/R/rserver/rserver.cpp +++ b/src/backends/R/rserver/rserver.cpp @@ -1,510 +1,521 @@ /* 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) 2009 Alexander Rieder Copyright (C) 2010 Oleksiy Protas */ // TODO: setStatus in syntax and completions, to be or not to be? // on the one hand comme il faut, on another, causes flickering in UI #include "rserver.h" #include #include "radaptor.h" #include "rcallbacks.h" #include "settings.h" #include #include #include #include #include //R includes #include #include #include #include #define R_INTERFACE_PTRS #include RServer::RServer() : m_isInitialized(false),m_isCompletionAvailable(false) { new RAdaptor(this); m_tmpDir = QDir::tempPath() + QString::fromLatin1("/cantor_rserver-%1").arg(getpid()); QDir dir; dir.mkdir(m_tmpDir); qDebug()<<"storing plots at "<integratePlots()) { qDebug()<<"integrating plots"; newPlotDevice(); } //Loading automatic run scripts foreach (const QString& path, RServerSettings::self()->autorunScripts()) { int errorOccurred=0; if (QFile::exists(path)) R_tryEval(lang2(install("source"),mkString(path.toUtf8().data())),nullptr,&errorOccurred); // TODO: error handling else { qDebug()<<(QLatin1String("Script ")+path+QLatin1String(" not found")); // FIXME: or should we throw a messagebox } } qDebug()<<"done initializing"; // FIXME: other way to search symbols, see listSymbols for details listSymbols(); } //Code from the RInside library void RServer::autoload() { #include "rautoloads.h" /* Autoload default packages and names from autoloads.h * * This function behaves in almost every way like * R's autoload: * function (name, package, reset = FALSE, ...) * { * if (!reset && exists(name, envir = .GlobalEnv, inherits = FALSE)) * stop("an object with that name already exists") * m <- match.call() * m[[1]] <- as.name("list") * newcall <- eval(m, parent.frame()) * newcall <- as.call(c(as.name("autoloader"), newcall)) * newcall$reset <- NULL * if (is.na(match(package, .Autoloaded))) * assign(".Autoloaded", c(package, .Autoloaded), env = .AutoloadEnv) * do.call("delayedAssign", list(name, newcall, .GlobalEnv, * .AutoloadEnv)) * invisible() * } * * What's missing is the updating of the string vector .Autoloaded with * the list of packages, which by my code analysis is useless and only * for informational purposes. * */ //void autoloads(void){ SEXP da, dacall, al, alcall, AutoloadEnv, name, package; int i,j, idx=0, errorOccurred, ptct; /* delayedAssign call*/ PROTECT(da = Rf_findFun(Rf_install("delayedAssign"), R_GlobalEnv)); PROTECT(AutoloadEnv = Rf_findVar(Rf_install(".AutoloadEnv"), R_GlobalEnv)); if (AutoloadEnv == R_NilValue){ qDebug()<<"Cannot find .AutoloadEnv"; //exit(1); } PROTECT(dacall = allocVector(LANGSXP,5)); SETCAR(dacall,da); /* SETCAR(CDR(dacall),name); */ /* arg1: assigned in loop */ /* SETCAR(CDR(CDR(dacall)),alcall); */ /* arg2: assigned in loop */ SETCAR(CDR(CDR(CDR(dacall))),R_GlobalEnv); /* arg3 */ SETCAR(CDR(CDR(CDR(CDR(dacall)))),AutoloadEnv); /* arg3 */ /* autoloader call */ PROTECT(al = Rf_findFun(Rf_install("autoloader"), R_GlobalEnv)); PROTECT(alcall = allocVector(LANGSXP,3)); SET_TAG(alcall, R_NilValue); /* just like do_ascall() does */ SETCAR(alcall,al); /* SETCAR(CDR(alcall),name); */ /* arg1: assigned in loop */ /* SETCAR(CDR(CDR(alcall)),package); */ /* arg2: assigned in loop */ ptct = 5; for(i = 0; i < packc; ++i){ idx += (i != 0)? packobjc[i-1] : 0; for (j = 0; j < packobjc[i]; ++j){ /*printf("autload(%s,%s)\n",packobj[idx+j],pack[i]);*/ PROTECT(name = NEW_CHARACTER(1)); PROTECT(package = NEW_CHARACTER(1)); SET_STRING_ELT(name, 0, COPY_TO_USER_STRING(packobj[idx+j])); SET_STRING_ELT(package, 0, COPY_TO_USER_STRING(pack[i])); /* Set up autoloader call */ PROTECT(alcall = allocVector(LANGSXP,3)); SET_TAG(alcall, R_NilValue); /* just like do_ascall() does */ SETCAR(alcall,al); SETCAR(CDR(alcall),name); SETCAR(CDR(CDR(alcall)),package); /* Setup delayedAssign call */ SETCAR(CDR(dacall),name); SETCAR(CDR(CDR(dacall)),alcall); R_tryEval(dacall,R_GlobalEnv,&errorOccurred); if (errorOccurred){ qDebug()<<"Error calling delayedAssign!"; //exit(1); } ptct += 3; } } UNPROTECT(ptct); /* Initialize the completion libraries if needed, adapted from sys-std.c of R */ // TODO: should we do this or init on demand? // if (completion is needed) // TODO: discuss how to pass parameter { /* First check if namespace is loaded */ if (findVarInFrame(R_NamespaceRegistry,install("utils"))==R_UnboundValue) { /* Then try to load it */ SEXP cmdSexp, cmdexpr; ParseStatus status; int i; const char *p="try(loadNamespace('rcompgen'), silent=TRUE)"; PROTECT(cmdSexp=mkString(p)); cmdexpr=PROTECT(R_ParseVector(cmdSexp,-1,&status,R_NilValue)); if(status==PARSE_OK) { for(i=0;icmd=cmd; expr->hasOtherResults=false; setStatus(RServer::Busy); setCurrentExpression(expr); expr->std_buffer.clear(); expr->err_buffer.clear(); ReturnCode returnCode=RServer::SuccessCode; QString returnText; QStringList neededFiles; //Code to evaluate an R function (taken from RInside library) ParseStatus status; SEXP cmdSexp, cmdexpr = R_NilValue; SEXP result; int i, errorOccurred; QByteArray memBuf; memBuf.append(cmd.toUtf8()); PROTECT(cmdSexp = allocVector(STRSXP, 1)); SET_STRING_ELT(cmdSexp, 0, mkChar((char*)memBuf.data())); cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue)); switch (status) { case PARSE_OK: qDebug()<<"PARSING "< 1 */ for (i = 0; i < length(cmdexpr); ++i) { result = R_tryEval(VECTOR_ELT(cmdexpr, i), nullptr, &errorOccurred); if (errorOccurred) { qDebug()<<"Error occurred."; break; } // TODO: multiple results } memBuf.clear(); break; case PARSE_INCOMPLETE: /* need to read another line */ qDebug()<<"parse incomplete.."; break; case PARSE_NULL: qDebug()<<"ParseStatus is null: "<std_buffer<<" err: "<err_buffer; //if the command didn't print anything on its own, print the result //TODO: handle some known result types like lists, matrices separately // to make the output look better, by using html (tables etc.) if(expr->std_buffer.isEmpty()&&expr->err_buffer.isEmpty()) { qDebug()<<"printing result..."; SEXP count=PROTECT(R_tryEval(lang2(install("length"),result),nullptr,&errorOccurred)); // TODO: error checks if (*INTEGER(count)==0) qDebug() << "no result, so show nothing"; else Rf_PrintValue(result); UNPROTECT(1); } setCurrentExpression(nullptr); //is this save? if(!expr->err_buffer.isEmpty()) { returnCode=RServer::ErrorCode; returnText=expr->err_buffer; } else { returnCode=RServer::SuccessCode; returnText=expr->std_buffer; } }else { returnCode=RServer::ErrorCode; returnText=i18n("Error Parsing Command"); } if(internal) { qDebug()<<"internal result: "<hasOtherResults=true; newPlotDevice(); neededFiles<hasOtherResults) emit expressionFinished(returnCode, returnText); else showFiles(neededFiles); setStatus(Idle); // FIXME: Calling this every evaluation is probably ugly listSymbols(); } void RServer::completeCommand(const QString& cmd) { // setStatus(RServer::Busy); // TODO: is static okay? guess RServer is a singletone, but ... // TODO: error handling? // TODO: investigate encoding problem // TODO: propage the flexibility of token selection upward // TODO: what if install() fails? investigate // TODO: investigate why errors break the whole foodchain of RServer callbacks in here static SEXP comp_env=R_FindNamespace(mkString("utils")); static SEXP tokenizer_func=install(".guessTokenFromLine"); static SEXP linebuffer_func=install(".assignLinebuffer"); static SEXP buffer_end_func=install(".assignEnd"); static SEXP complete_func=install(".completeToken"); static SEXP retrieve_func=install(".retrieveCompletions"); /* Setting buffer parameters */ int errorOccurred=0; // TODO: error cheks, too lazy to do it now R_tryEval(lang2(linebuffer_func,mkString(cmd.toUtf8().data())),comp_env,&errorOccurred); R_tryEval(lang2(buffer_end_func,ScalarInteger(cmd.size())),comp_env,&errorOccurred); /* Passing the tokenizing work to professionals */ SEXP token=PROTECT(R_tryEval(lang1(tokenizer_func),comp_env,&errorOccurred)); /* Doing the actual stuff */ R_tryEval(lang1(complete_func),comp_env,&errorOccurred); SEXP completions=PROTECT(R_tryEval(lang1(retrieve_func),comp_env,&errorOccurred)); /* Populating the list of completions */ QStringList completionOptions; for (int i=0;i */ #include "juliacompletionobject.h" #include "juliasession.h" #include "juliakeywords.h" #include "result.h" #include #include JuliaCompletionObject::JuliaCompletionObject( const QString &command, int index, JuliaSession *session) : Cantor::CompletionObject(session) { setLine(command, index); } void JuliaCompletionObject::fetchCompletions() { if (session()->status() == Cantor::Session::Disable) { QStringList allCompletions; allCompletions << JuliaKeywords::instance()->keywords(); allCompletions << JuliaKeywords::instance()->variables(); allCompletions << JuliaKeywords::instance()->functions(); allCompletions << JuliaKeywords::instance()->plotShowingCommands(); setCompletions(allCompletions); emit fetchingDone(); } else { QString completionCommand; #if QT_VERSION_CHECK(JULIA_VERSION_MAJOR, JULIA_VERSION_MINOR, 0) >= QT_VERSION_CHECK(0, 7, 0) completionCommand = QString::fromLatin1( "using REPL; " "join(" "map(REPL.REPLCompletions.completion_text, REPL.REPLCompletions.completions(\"%1\", %2)[1])," "\"__CANTOR_DELIM__\")" ); #else completionCommand = QString::fromLatin1( "join(" "Base.REPL.REPLCompletions.completions(\"%1\", %2)[1]," "\"__CANTOR_DELIM__\")" ); #endif auto julia_session = static_cast(session()); julia_session->runJuliaCommand(completionCommand.arg(command()).arg(command().size())); auto result = julia_session->getOutput(); result.chop(1); result.remove(0, 1); QStringList completions = result.split(QLatin1String("__CANTOR_DELIM__")); if (command().contains(QLatin1Char('.'))) for(QString& word : completions) - if (!word.startsWith(command())) - word.prepend(command()); + { + const int i = command().lastIndexOf(QLatin1Char('.')); + const QString& prefix = command().remove(i, command().size()-i) + QLatin1Char('.'); + if (!word.startsWith(prefix)) + word.prepend(prefix); + } setCompletions(completions); emit fetchingDone(); } } bool JuliaCompletionObject::mayIdentifierContain(QChar c) const { return c.isLetter() || c.isDigit() || c == QLatin1Char('_') || c == QLatin1Char('%') || c == QLatin1Char('$') || c == QLatin1Char('.'); } bool JuliaCompletionObject::mayIdentifierBeginWith(QChar c) const { return c.isLetter() || c == QLatin1Char('_') || c == QLatin1Char('%') || c == QLatin1Char('$'); } diff --git a/src/backends/julia/testjulia.cpp b/src/backends/julia/testjulia.cpp index 2f0b46b2..61bbe959 100644 --- a/src/backends/julia/testjulia.cpp +++ b/src/backends/julia/testjulia.cpp @@ -1,274 +1,294 @@ /* * 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 "testjulia.h" #include "session.h" #include "backend.h" #include "expression.h" #include "result.h" #include "textresult.h" #include "imageresult.h" #include "defaultvariablemodel.h" #include "completionobject.h" QString TestJulia::backendName() { return QLatin1String("julia"); } void TestJulia::testOneLine() { Cantor::Expression *e = evalExp(QLatin1String("2 + 3")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Done); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QCOMPARE(e->result()->data().toString(), QLatin1String("5")); QVERIFY(e->errorMessage().isEmpty()); } void TestJulia::testOneLineWithPrint() { Cantor::Expression *e = evalExp(QLatin1String("print(2 + 3)")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Done); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QCOMPARE(e->result()->data().toString(), QLatin1String("5")); QVERIFY(e->errorMessage().isEmpty()); } void TestJulia::testException() { Cantor::Expression *e = evalExp(QLatin1String("sqrt(-1)")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Error); QVERIFY(e->result()); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QVERIFY( !e->errorMessage().isEmpty() && e->errorMessage().contains(QLatin1String( "sqrt will only return a complex result if called with a " "complex argument." )) ); } void TestJulia::testSyntaxError() { Cantor::Expression *e = evalExp(QLatin1String("for i = 1:10\nprint(i)")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Error); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QVERIFY( !e->errorMessage().isEmpty() && e->errorMessage().contains(QLatin1String( "syntax: incomplete: \"for\" at none:1 requires end" )) ); } void TestJulia::testMultilineCode() { Cantor::Expression *e = evalExp(QLatin1String( "q = 0; # comment\n" "# sdfsdf\n" "for i = 1:10\n" " global q\n" " q += i\n" "end\n" "print(q)" )); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Done); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QCOMPARE(e->result()->data().toString(), QLatin1String("55")); QVERIFY(e->errorMessage().isEmpty()); } void TestJulia::testPartialResultOnException() { Cantor::Expression *e = evalExp(QLatin1String( "for i = 1:5\n" " print(i)\n" "end\n" "sqrt(-1)\n" )); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Error); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QCOMPARE(e->result()->data().toString(), QLatin1String("12345")); QVERIFY( !e->errorMessage().isEmpty() && e->errorMessage().contains(QLatin1String( "sqrt will only return a complex result if called with a " "complex argument." )) ); } void TestJulia::testInlinePlot() { Cantor::Expression *e = evalExp(QLatin1String( "import GR\n" "GR.plot([-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], sin)" )); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Done); QVERIFY(e->result()->type() == Cantor::ImageResult::Type); } void TestJulia::testInlinePlotWithExceptionAndPartialResult() { Cantor::Expression *e = evalExp(QLatin1String( "import GR\n" "print(\"gonna plot\")\n" "sqrt(-1)\n" "GR.plot([-1, -0.75, -0.5, -0.25, 0, 0.25, 0.5, 0.75, 1], sin)\n" )); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Error); QVERIFY(e->result()->type() == Cantor::TextResult::Type); QCOMPARE(e->result()->data().toString(), QLatin1String("gonna plot")); QVERIFY( !e->errorMessage().isEmpty() && e->errorMessage().contains(QLatin1String( "sqrt will only return a complex result if called with a " "complex argument." )) ); } void TestJulia::testAddVariablesFromCode() { evalExp(QLatin1String("a = 0; b = 1; c = 2; d = 3\n")); auto variableModel = session()->variableModel(); QStringList variableNames = QString::fromLatin1("a b c d").split(QLatin1String(" ")); for (int i = 0; i < variableNames.size(); i++) { QModelIndexList matchedVariables = variableModel->match( variableModel->index(0, 0), Qt::DisplayRole, QVariant::fromValue(variableNames[i]), -1, Qt::MatchExactly ); QCOMPARE(matchedVariables.size(), 1); auto match = matchedVariables[0]; auto valueIndex = variableModel->index(match.row(), match.column() + 1); QVERIFY( valueIndex.data(Qt::DisplayRole) == QVariant::fromValue(QString::number(i)) ); } } void TestJulia::testAddVariablesFromManager() { auto variableModel = static_cast( session()->variableModel() ); QStringList variableNames = QString::fromLatin1("a b c d").split(QLatin1String(" ")); for (int i = 0; i < variableNames.size(); i++) { variableModel->addVariable(variableNames[i], QString::number(i)); QModelIndexList matchedVariables = variableModel->match( variableModel->index(0, 0), Qt::DisplayRole, QVariant::fromValue(variableNames[i]), -1, Qt::MatchExactly ); QCOMPARE(matchedVariables.size(), 1); auto match = matchedVariables[0]; auto valueIndex = variableModel->index(match.row(), match.column() + 1); QVERIFY( valueIndex.data(Qt::DisplayRole) == QVariant::fromValue(QString::number(i)) ); } } void TestJulia::testRemoveVariables() { auto variableModel = static_cast( session()->variableModel() ); QStringList variableNames = QString::fromLatin1("a b c d").split(QLatin1String(" ")); for (int i = 0; i < variableNames.size(); i++) { variableModel->addVariable(variableNames[i], QString::number(i)); } for (int i = 0; i < variableNames.size(); i += 2) { variableModel->removeVariable(variableNames[i]); } for (int i = 0; i < variableNames.size(); i++) { QModelIndexList matchedVariables = variableModel->match( variableModel->index(0, 0), Qt::DisplayRole, QVariant::fromValue(variableNames[i]), -1, Qt::MatchExactly ); if (i % 2 == 0) { QVERIFY(matchedVariables.isEmpty()); } else { QCOMPARE(matchedVariables.size(), 1); auto match = matchedVariables[0]; auto valueIndex = variableModel->index(match.row(), match.column() + 1); QVERIFY( valueIndex.data(Qt::DisplayRole) == QVariant::fromValue(QString::number(i)) ); } } } void TestJulia::testAutoCompletion() { auto prefix = QLatin1String("ex"); auto completionObject = session()->completionFor(prefix); - // Give sometime for Qt's singleShot in fetch completions to trigger - QTest::qWait(1000); + waitForSignal(completionObject, SIGNAL(fetchingDone())); auto completions = completionObject->completions(); QStringList completionsToCheck; completionsToCheck << QLatin1String("exit"); completionsToCheck << QLatin1String("exponent"); completionsToCheck << QLatin1String("exp"); for (auto completion : completionsToCheck) { QVERIFY(completions.contains(completion)); } for (auto completion : completions) { QVERIFY(completion.startsWith(prefix)); } } +void TestJulia::testComplexAutocompletion() +{ + auto prefix = QLatin1String("Base.Ma"); + auto completionObject = session()->completionFor(prefix); + waitForSignal(completionObject, SIGNAL(fetchingDone())); + auto completions = completionObject->completions(); + + QStringList completionsToCheck; + completionsToCheck << QLatin1String("Base.MainInclude"); + completionsToCheck << QLatin1String("Base.Math"); + completionsToCheck << QLatin1String("Base.Matrix"); + + for (auto completion : completionsToCheck) { + QVERIFY(completions.contains(completion)); + } + + for (auto completion : completions) { + QVERIFY(completion.startsWith(prefix)); + } +} + QTEST_MAIN(TestJulia) diff --git a/src/backends/julia/testjulia.h b/src/backends/julia/testjulia.h index ce16d033..0416de0b 100644 --- a/src/backends/julia/testjulia.h +++ b/src/backends/julia/testjulia.h @@ -1,84 +1,85 @@ /* * 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 TestJulia: public BackendTest { Q_OBJECT private Q_SLOTS: /** * Test simple one-line command. Check that last result is printed */ void testOneLine(); /** * Test one-line command returning `nothing`. No result is printed, except * what `print` does */ void testOneLineWithPrint(); /** * Test command, that emits exception */ void testException(); /** * Test command consisting of multiple lines, including comments. */ void testMultilineCode(); /** * Test command with malformed syntax */ void testSyntaxError(); /** * Test that results gathered before exception occurred are shown */ void testPartialResultOnException(); /** * Tests that inline plot is shown */ void testInlinePlot(); /** * Tests that when exception occurred and plotting is done, partial * text results shown to user */ void testInlinePlotWithExceptionAndPartialResult(); /** * Test registering new variables, when added by command */ void testAddVariablesFromCode(); /** * Test registering new variables, when added from variable manager */ void testAddVariablesFromManager(); /** * Test that removing variable unregisters it */ void testRemoveVariables(); /** * Test that auto completion provides expected results */ void testAutoCompletion(); + void testComplexAutocompletion(); private: QString backendName() override; };