Properly move NbRuntime to its own thread
diff --git a/ide/IdeMain.cpp b/ide/IdeMain.cpp
index c8eae76..ec6627e 100644
--- a/ide/IdeMain.cpp
+++ b/ide/IdeMain.cpp
@@ -13,9 +13,6 @@
 
     QQmlApplicationEngine engine;
 
-    // This is done implicitly now.
-    // registerTypes(&engine);
-
     QQuickStyle::setStyle("Material");
 
     qRegisterMetaType<CellModel>();
diff --git a/ide/NbRuntime.cpp b/ide/NbRuntime.cpp
index 35df413..eeb9d0d 100644
--- a/ide/NbRuntime.cpp
+++ b/ide/NbRuntime.cpp
@@ -5,7 +5,7 @@
 #include "../StdLib.h"
 
 NbRuntime::NbRuntime(QObject *parent)
-    : QThread(parent)
+    : QObject(parent)
 {
     StdLib().load(_eval);
 }
@@ -65,7 +65,7 @@
             {
                 ParseResult ret;
                 Function func;
-                AstNode ast;
+                QList<AstNode> ast;
 
                 if ((ret = parser.parseFunctionDefinition(&func)))
                 {
@@ -76,14 +76,17 @@
                     emit cellFailedToParse(cell, ret);
                     goto endOfCell; // JANK!
                 }
-                else if ((ret = parser.parseOne(&ast)))
+                else if ((ret = parser.parseMany(&ast)) && !ast.empty())
                 {
-                    RuntimeResult nodeRes = _eval.evaluate(ast, _ctx);
-                    result += nodeRes;
-
-                    if (!nodeRes.success())
+                    for (const AstNode &node : ast)
                     {
-                        break;
+                        RuntimeResult nodeRes = _eval.evaluate(node, _ctx);
+                        result += nodeRes;
+
+                        if (!nodeRes.success())
+                        {
+                            goto endOfParseLoop;
+                        }
                     }
                 }
                 else if (ret.status() == ParseResult::INCOMPLETE)
@@ -105,6 +108,7 @@
                 }
             }
 
+        endOfParseLoop:
             emit cellFinishedRunning(cell, result);
 
         endOfCell:
diff --git a/ide/NbRuntime.h b/ide/NbRuntime.h
index 2f6a845..9d4c714 100644
--- a/ide/NbRuntime.h
+++ b/ide/NbRuntime.h
@@ -9,7 +9,7 @@
 #include "../Evaluator.h"
 #include "../Parser.h"
 
-class NbRuntime : public QThread
+class NbRuntime : public QObject
 {
     Q_OBJECT
 
diff --git a/ide/Notebook.cpp b/ide/Notebook.cpp
index 953e98b..3396779 100644
--- a/ide/Notebook.cpp
+++ b/ide/Notebook.cpp
@@ -4,17 +4,26 @@
 
 // TODO: avoid potential race condition if Cell is deleted, pass by value with same UUID instead
 
+Notebook::~Notebook()
+{
+    _rtThread->quit();
+    _rtThread->wait();
+}
+
 Notebook::Notebook(QObject *parent)
     : QObject(parent)
     , _cellModel(new CellModel(this))
+    , _rt(new NbRuntime(this))
+    , _rtThread(new QThread(this))
 {
-    connect(&_rt, &NbRuntime::cellFailedToParse, this, &Notebook::cellFailedToParse);
-    connect(&_rt, &NbRuntime::cellFinishedRunning, this, &Notebook::cellFinishedRunning);
-    connect(&_rt, &NbRuntime::cellQuit, this, &Notebook::cellQuit);
-    connect(&_rt, &NbRuntime::cellRunning, this, &Notebook::cellRunning);
-    connect(&_rt, &NbRuntime::cellWaiting, this, &Notebook::cellWaiting);
+    connect(_rt, &NbRuntime::cellFailedToParse, this, &Notebook::cellFailedToParse);
+    connect(_rt, &NbRuntime::cellFinishedRunning, this, &Notebook::cellFinishedRunning);
+    connect(_rt, &NbRuntime::cellQuit, this, &Notebook::cellQuit);
+    connect(_rt, &NbRuntime::cellRunning, this, &Notebook::cellRunning);
+    connect(_rt, &NbRuntime::cellWaiting, this, &Notebook::cellWaiting);
 
-    _rt.start();
+    _rt->moveToThread(_rtThread);
+    _rtThread->start();
 }
 
 Notebook::Notebook(const Notebook &other, QObject *parent)
@@ -34,12 +43,12 @@
 void Notebook::runCell(QUuid uuid)
 {
     qInfo() << "Running cell" << uuid;
-    _rt.queueCell(Cell::cellFromUuid(uuid));
+    _rt->queueCell(Cell::cellFromUuid(uuid));
 }
 
 void Notebook::quitCell(QUuid uuid)
 {
-    _rt.unqueueCell(Cell::cellFromUuid(uuid));
+    _rt->unqueueCell(Cell::cellFromUuid(uuid));
 }
 
 void Notebook::cellFinishedRunning(Cell *cell, RuntimeResult result)
diff --git a/ide/Notebook.h b/ide/Notebook.h
index 6a5d0cf..0dbe21e 100644
--- a/ide/Notebook.h
+++ b/ide/Notebook.h
@@ -14,6 +14,7 @@
     Q_PROPERTY(CellModel *cellModel READ cellModel NOTIFY cellModelChanged)
 
 public:
+    ~Notebook();
     explicit Notebook(QObject *parent = nullptr);
     Notebook(const Notebook &other, QObject *parent = nullptr);
 
@@ -37,7 +38,8 @@
 
     QList<Cell *> _cells;
     CellModel *_cellModel;
-    NbRuntime _rt;
+    NbRuntime *_rt;
+    QThread *_rtThread;
 };
 
 Q_DECLARE_METATYPE(Notebook)
diff --git a/ide/qml/NotebookCell.qml b/ide/qml/NotebookCell.qml
index 240e7f8..3c59393 100644
--- a/ide/qml/NotebookCell.qml
+++ b/ide/qml/NotebookCell.qml
@@ -22,7 +22,10 @@
 
     height: column.height
 
-    Keys.onEscapePressed: root.cellUnfocused()
+    Keys.onEscapePressed: {
+		root.cellUnfocused()
+		code.focus = false
+	}
 
     ColumnLayout {
         id: column
@@ -76,9 +79,11 @@
                     Layout.fillHeight: true
 
                     TextArea {
+                        id: code
+
                         Layout.fillWidth: true
                         Layout.fillHeight: true
-                        id: code
+
                         font.family: "monospace"
                         text: root.code
                         selectByMouse: true
@@ -115,6 +120,8 @@
                 }
 
                 RoundButton {
+					Layout.alignment: Qt.AlignTop
+
                     icon.source: "qrc:///icons/menu.svg"
                     icon.color: Constants.buttonGrey
                     flat: true