aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRishabh Gupta <[email protected]>2018-03-14 12:05:19 -0300
committerFilipe Saraiva <[email protected]>2018-03-14 12:05:19 -0300
commit85d88cd1abe1cf32c401f428aa6fc7eb24a81a73 (patch)
treec5bca5489cb64ea04a5e2aafe9183cc31e929bea
parent6ad659fc436a400756f3168ed3ca521b22195506 (diff)
Port Lua backend to QProcess
* setup communication between Cantor and Lua interpreter through QProcess * use Lua interpreter for all the calculations * use Lua C Api for tab completion Commit from https://phabricator.kde.org/R55:4b1142d556601b68968ffb78369282060bda6ecb
-rw-r--r--src/backends/lua/luaexpression.cpp72
-rw-r--r--src/backends/lua/luaexpression.h8
-rw-r--r--src/backends/lua/luasession.cpp140
-rw-r--r--src/backends/lua/luasession.h14
4 files changed, 142 insertions, 92 deletions
diff --git a/src/backends/lua/luaexpression.cpp b/src/backends/lua/luaexpression.cpp
index 22f2c25..a88977e 100644
--- a/src/backends/lua/luaexpression.cpp
+++ b/src/backends/lua/luaexpression.cpp
@@ -32,8 +32,8 @@
#include <QString>
#include <QStringList>
-LuaExpression::LuaExpression( Cantor::Session* session, lua_State* L)
- : Cantor::Expression(session), m_L(L)
+LuaExpression::LuaExpression( Cantor::Session* session)
+ : Cantor::Expression(session)
{
}
@@ -43,58 +43,36 @@ LuaExpression::~LuaExpression()
void LuaExpression::evaluate()
{
- QString ret;
- Cantor::Expression::Status status;
- execute(ret, status);
-
- if(status == Cantor::Expression::Done)
- {
- QString cmd = command().simplified();
-
- if( cmd.startsWith(QLatin1String("show(")) || cmd.startsWith(QLatin1String("show (")) )
- setResult(new Cantor::ImageResult(QUrl::fromLocalFile(ret), ret));
- else
- setResult(new Cantor::TextResult(ret));
- }
- else
- {
- setErrorMessage(ret);
+ /*
+ * start evaluating the current expression
+ * set the status to computing
+ * decide what needs to be done if the user is trying to define a function etc
+ */
+ setStatus(Cantor::Expression::Computing);
+ if (command().isEmpty()) {
+ setStatus(Cantor::Expression::Done);
+ return;
}
- setStatus(status);
+ LuaSession* currentSession = dynamic_cast<LuaSession*>(session());
+ currentSession->runExpression(this);
}
-void LuaExpression::interrupt()
+void LuaExpression::parseOutput(QString &output)
{
- setStatus(Cantor::Expression::Interrupted);
-}
-
-void LuaExpression::execute(QString& ret, Cantor::Expression::Status& status)
-{
- int top = lua_gettop(m_L);
-
- // execute the command
- QString err = luahelper_dostring(m_L, QLatin1String("return ") + command() ); // try to return values...
- if( !err.isNull() ) err = luahelper_dostring(m_L, command() ); // try the original expression
+ output.replace(command(), QLatin1String(""));
+ output.replace(QLatin1String("return"), QLatin1String(""));
+ output.replace(QLatin1String(">"), QLatin1String(""));
+ output = output.trimmed();
- if( err.isNull() )
- {
- QStringList list;
- int n_out = lua_gettop(m_L) - top;
+ qDebug() << "final output of the command " << command() << ": " << output << endl;
- for(int i = -n_out; i < 0; ++i)
- list << luahelper_tostring(m_L, i);
+ setResult(new Cantor::TextResult(output));
- ret = list.join(QLatin1String("\n")) + luahelper_getprinted(m_L);
- status = Cantor::Expression::Done;
- }
- else
- {
- qDebug() << "error when executing" << command() << ":" << err;
- ret = err;
- status = Cantor::Expression::Error;
- }
-
- lua_settop(m_L, top);
+ setStatus(Cantor::Expression::Done);
}
+void LuaExpression::interrupt()
+{
+ setStatus(Cantor::Expression::Interrupted);
+}
diff --git a/src/backends/lua/luaexpression.h b/src/backends/lua/luaexpression.h
index 6acbaf4..e2d0e32 100644
--- a/src/backends/lua/luaexpression.h
+++ b/src/backends/lua/luaexpression.h
@@ -30,17 +30,13 @@ class LuaExpression : public Cantor::Expression
Q_OBJECT
public:
- LuaExpression( Cantor::Session* session, lua_State* L);
+ LuaExpression( Cantor::Session* session);
~LuaExpression();
void evaluate();
void interrupt();
+ void parseOutput(QString& output);
-private:
- // evaluates an expression, executing it on the Lua state and building an adequate response
- void execute(QString& ret, Cantor::Expression::Status& status);
-
- lua_State* m_L;
};
#endif /* _LUAEXPRESSION_H */
diff --git a/src/backends/lua/luasession.cpp b/src/backends/lua/luasession.cpp
index cd2424d..04c5ef8 100644
--- a/src/backends/lua/luasession.cpp
+++ b/src/backends/lua/luasession.cpp
@@ -26,7 +26,12 @@
#include <settings.h>
#include "ui_settings.h"
-LuaSession::LuaSession( Cantor::Backend* backend) : Session(backend)
+#include <QProcess>
+
+LuaSession::LuaSession( Cantor::Backend* backend) :
+ Session(backend),
+ m_process(0),
+ m_currentExpression(0)
{
}
@@ -38,45 +43,81 @@ void LuaSession::login()
{
emit loginStarted();
+ /*
+ * setup Qprocess here
+ * load the autoscripts
+ */
+
+ m_process = new QProcess(this);
+ m_process->setProgram(QLatin1String("/usr/bin/lua"));
+ m_process->setArguments(QStringList() << QLatin1String("-i"));
+
+ m_process->setProcessChannelMode(QProcess::SeparateChannels);
+
+ connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readIntroMessage()));
+ connect(m_process, SIGNAL(started()), this, SLOT(processStarted()));
+ m_process->start();
+
+ // we need this for tab completion
m_L = luaL_newstate();
luaL_openlibs(m_L);
- QStringList errors;
- errors << luahelper_dostring(m_L, QLatin1String("__cantor = {}"));
+ changeStatus(Cantor::Session::Done);
+ emit loginDone();
+}
+
+void LuaSession::readIntroMessage()
+{
+ while(m_process->bytesAvailable()) {
+ m_output.append(QString::fromLocal8Bit(m_process->readLine()));
+ }
- errors << luahelper_dostring(m_L,
- QLatin1String("function print(...)\n"
- "local t = {}\n"
- "for i = 1, select('#',...) do\n"
- "local a = select(i,...)\n"
- "t[i] = tostring(a)\n"
- "end\n"
- "table.insert(__cantor, table.concat(t,'\t'))\n"
- " end"));
+ if(!m_output.isEmpty() && m_output.trimmed().endsWith(QLatin1String(">"))) {
+ qDebug() << " reading the intro message " << m_output ;
+ m_output.clear();
- errors << luahelper_dostring(m_L,
- QLatin1String("function show(a)\n"
- "assert(type(a) == 'string')\n"
- "return a\n"
- "end"));
+ disconnect(m_process, SIGNAL(readyReadStandardOutput()), this , SLOT(readIntroMessage()));
+ connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput()));
+ connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(readError()));
+ }
+}
- if(!errors.empty())
- qDebug() << errors.join(QLatin1String("\n"));
+void LuaSession::readOutput()
+{
+ /*
+ * parse the output
+ * clear all the garbage
+ * set it as output
+ */
+ // keep reading till the output ends with '>'.
+ // '>' marks the end of output for a particular command;
+ while(m_process->bytesAvailable()) {
+ m_output.append(QString::fromLocal8Bit(m_process->readLine()));
+ }
+ if(m_currentExpression && !m_output.isEmpty() && m_output.trimmed().endsWith(QLatin1String(">"))) {
+ // we have our complete output
+ // clean the output and parse it and clear m_output;
+ m_currentExpression->parseOutput(m_output);
+ m_output.clear();
- foreach (const QString &str, LuaSettings::self()->autorunScripts())
- evaluateExpression(QLatin1String("dofile('") + str + QLatin1String("')"), Cantor::Expression::DeleteOnFinish);
+ }
- changeStatus(Cantor::Session::Done);
- emit loginDone();
+}
+
+void LuaSession::readError()
+{
+ qDebug() << m_process->readAllStandardError() << endl;
+}
+
+void LuaSession::processStarted()
+{
+ qDebug() << m_process->program() << " pid " << m_process->processId() << " started " << endl;
}
void LuaSession::logout()
{
- if(m_L)
- {
- lua_close(m_L);
- m_L = 0;
- }
+ if(m_process)
+ m_process->kill();
}
void LuaSession::interrupt()
@@ -89,13 +130,28 @@ Cantor::Expression* LuaSession::evaluateExpression(const QString& cmd, Cantor::E
{
changeStatus(Cantor::Session::Running);
- LuaExpression* expr = new LuaExpression(this, m_L);
- connect(expr, &LuaExpression::statusChanged, this, &LuaSession::expressionFinished);
- expr->setFinishingBehavior(behave);
- expr->setCommand(cmd);
- expr->evaluate();
+ m_currentExpression = new LuaExpression(this);
+ connect(m_currentExpression, SIGNAL(statusChanged(Cantor::Expression::Status)), this, SLOT(expressionFinished(Cantor::Expression::Status)));
+ m_currentExpression->setFinishingBehavior(behave);
+ m_currentExpression->setCommand(cmd);
+ m_currentExpression->evaluate();
+
+ return m_currentExpression;
+}
+
+void LuaSession::runExpression(LuaExpression *currentExpression)
+{
+ /*
+ * get the current command
+ * format it and write to m_process
+ */
+ QString command = currentExpression->command();
+
+ command += QLatin1String("\n");
- return expr;
+ qDebug() << "final command to be executed " << command << endl;
+
+ m_process->write(command.toLocal8Bit());
}
Cantor::CompletionObject* LuaSession::completionFor(const QString& command, int index)
@@ -103,10 +159,19 @@ Cantor::CompletionObject* LuaSession::completionFor(const QString& command, int
return new LuaCompletionObject(command, index, this);
}
-void LuaSession::expressionFinished()
+void LuaSession::expressionFinished(Cantor::Expression::Status status)
{
- // synchronous
- changeStatus(Cantor::Session::Done);
+ switch(status) {
+
+ case Cantor::Expression::Computing:
+ break;
+
+ case Cantor::Expression::Done:
+ case Cantor::Expression::Error:
+ case Cantor::Expression::Interrupted:
+ changeStatus(Cantor::Session::Done);
+ break;
+ }
}
QSyntaxHighlighter* LuaSession::syntaxHighlighter(QObject* parent)
@@ -119,4 +184,3 @@ lua_State* LuaSession::getState() const
{
return m_L;
}
-
diff --git a/src/backends/lua/luasession.h b/src/backends/lua/luasession.h
index 7293536..879e322 100644
--- a/src/backends/lua/luasession.h
+++ b/src/backends/lua/luasession.h
@@ -25,6 +25,7 @@
#include <lua.hpp>
class LuaExpression;
+class QProcess;
class LuaSession : public Cantor::Session
{
@@ -38,16 +39,27 @@ public:
void interrupt();
+ void runExpression(LuaExpression* currentExpression);
+
Cantor::Expression* evaluateExpression(const QString& command, Cantor::Expression::FinishingBehavior behave);
Cantor::CompletionObject* completionFor(const QString& cmd, int index=-1);
virtual QSyntaxHighlighter* syntaxHighlighter(QObject* parent);
lua_State* getState() const;
+public Q_SLOTS:
+ void readIntroMessage();
+ void readOutput();
+ void readError();
+ void processStarted();
+
private Q_SLOTS:
- void expressionFinished();
+ void expressionFinished(Cantor::Expression::Status status);
private:
lua_State* m_L;
+ QProcess* m_process;
+ LuaExpression* m_currentExpression;
+ QString m_output;
};
#endif /* _LUASESSION_H */