Add recent file view, implement runtime options
diff --git a/Evaluator.cpp b/Evaluator.cpp
index 9ce5bf7..92979c4 100644
--- a/Evaluator.cpp
+++ b/Evaluator.cpp
@@ -244,6 +244,13 @@
     throw EvalQuitException();
 }
 
+void Evaluator::reset()
+{
+    _vars = {};
+    _functions = {};
+    _shouldContinue = true;
+}
+
 QList<Token> Evaluator::dig(QString name)
 {
     if (_vars.contains(name))
diff --git a/Evaluator.h b/Evaluator.h
index 7034669..a88e809 100644
--- a/Evaluator.h
+++ b/Evaluator.h
@@ -88,6 +88,8 @@
     // Throws an EvalQuitException
     void quit();
 
+    void reset();
+
 private:
 	QMap<QString, Function> _functions;
     QMap<QString, QStack<QList<Token>>> _vars;
diff --git a/VarContext.cpp b/VarContext.cpp
index a67df2b..f444faa 100644
--- a/VarContext.cpp
+++ b/VarContext.cpp
@@ -1,7 +1,7 @@
 #include "VarContext.h"
 
 void VarContext::add(char t, const QString &name, const Token &value) {
-    _vars.insert(name, Var{t, value});
+    _vars.insert(name, Var{t, value, {}});
 }
 
 char VarContext::exists(const QString &name) {
diff --git a/VarContext.h b/VarContext.h
index 6e5ea13..5ae93d5 100644
--- a/VarContext.h
+++ b/VarContext.h
@@ -8,7 +8,8 @@
 {
 public:
     VarContext() = default;
-    VarContext(VarContext const &other)  noexcept;
+    VarContext(VarContext const &other) noexcept;
+    VarContext &operator =(const VarContext &other) = default;
 
     void add(char t, const QString &name, const Token &value);
     void add(char t, const QString &name, const QList<Token> &value);
diff --git a/examples/Book Examples.refnb b/examples/Book Examples.refnb
new file mode 100644
index 0000000..142aa60
--- /dev/null
+++ b/examples/Book Examples.refnb
@@ -0,0 +1,10 @@
+{
+    "cells": [
+        {
+            "code": "* These are examples from the book",
+            "result": "Garbage at end of input at 1:1<br>* These are examples from the book<br><font color=\"red\">^~~</font>",
+            "resultType": 1,
+            "status": 1
+        }
+    ]
+}
diff --git a/ide/IDE.pri b/ide/IDE.pri
index 69856d7..d086a61 100644
--- a/ide/IDE.pri
+++ b/ide/IDE.pri
@@ -18,14 +18,16 @@
     $$PWD/CellModel.cpp \
     $$PWD/IdeMain.cpp \
     $$PWD/NbRuntime.cpp \
-    $$PWD/Notebook.cpp
+    $$PWD/Notebook.cpp \
+    $$PWD/RecentModel.cpp
 
 HEADERS += \
     $$PWD/Cell.h \
     $$PWD/CellModel.h \
     $$PWD/IdeMain.h \
     $$PWD/NbRuntime.h \
-    $$PWD/Notebook.h
+    $$PWD/Notebook.h \
+    $$PWD/RecentModel.h
 
 RESOURCES += \
     $$PWD/resources.qrc
diff --git a/ide/IdeMain.cpp b/ide/IdeMain.cpp
index ff8025f..7efe5fa 100644
--- a/ide/IdeMain.cpp
+++ b/ide/IdeMain.cpp
@@ -5,6 +5,7 @@
 #include <QTranslator>
 
 #include "CellModel.h"
+#include "RecentModel.h"
 
 int ideMain(Application *app)
 {
@@ -14,11 +15,17 @@
 
     qRegisterMetaType<CellModel>();
     qRegisterMetaType<CellModel *>();
+    qRegisterMetaType<RecentModel>();
+    qRegisterMetaType<RecentModel *>();
 
     QTranslator translator;
     qInfo() << "loading translations" << translator.load(QLocale(), "refal", "_", ":/ts/", ".qm");
     app->installTranslator(&translator);
 
+    app->setOrganizationName("swissChili");
+    app->setOrganizationDomain("swisschili.sh");
+    app->setApplicationName("REFAL Studio");
+
     const QUrl url(QStringLiteral("qrc:/qml/main.qml"));
     QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                      app, [url](QObject *obj, const QUrl &objUrl)
diff --git a/ide/NbRuntime.cpp b/ide/NbRuntime.cpp
index a2111a7..debda5b 100644
--- a/ide/NbRuntime.cpp
+++ b/ide/NbRuntime.cpp
@@ -10,6 +10,12 @@
     StdLib().load(_eval);
 }
 
+void NbRuntime::reset()
+{
+    _eval.reset();
+    _ctx = {};
+}
+
 void NbRuntime::queueCell(Cell *cell)
 {
     if (!_cells.contains(cell))
diff --git a/ide/NbRuntime.h b/ide/NbRuntime.h
index e7a4b3d..d98daa3 100644
--- a/ide/NbRuntime.h
+++ b/ide/NbRuntime.h
@@ -16,6 +16,8 @@
 public:
     explicit NbRuntime(QObject *parent = nullptr);
 
+    void reset();
+
 public slots:
     void queueCell(Cell *cell);
     void unqueueCell(Cell *cell);
diff --git a/ide/Notebook.cpp b/ide/Notebook.cpp
index 36cc0a3..a5baa0c 100644
--- a/ide/Notebook.cpp
+++ b/ide/Notebook.cpp
@@ -56,6 +56,21 @@
 void Notebook::quitCell(QUuid uuid)
 {
     _rt->unqueueCell(Cell::cellFromUuid(uuid));
+    _runningAll = false;
+}
+
+void Notebook::runAll()
+{
+    if (_cells.size() > 0)
+    {
+        _rt->queueCell(_cells.first());
+        _runningAll = true;
+    }
+}
+
+void Notebook::reset()
+{
+    _rt->reset();
 }
 
 void Notebook::fromJson(QJsonDocument doc)
@@ -118,7 +133,7 @@
 {
     if (_savePath == "")
     {
-        setSavePath(QFileDialog::getSaveFileName(nullptr, "Open Refal Notebook", "", "Refal Notebooks (*.refnb)"));
+        setSavePath(QFileDialog::getSaveFileName(nullptr, "Open REFAL Notebook", "", "REFAL Notebook (*.refnb)"));
     }
 
     QJsonDocument doc = toJson();
@@ -133,6 +148,8 @@
 
     save.write(doc.toJson(QJsonDocument::Indented));
     save.close();
+
+    emit saved();
 }
 
 bool Notebook::savePathSet()
@@ -157,6 +174,21 @@
     cell->setResult(pprint(result));
     cell->setStatus(Cell::IDLE);
     cell->setResultType(Cell::EXPRESSION);
+
+    if (_runningAll)
+    {
+        int index = _cells.indexOf(cell);
+
+        // not last
+        if (index < _cells.size() - 1)
+        {
+            _rt->queueCell(_cells[index + 1]);
+        }
+        else
+        {
+            _runningAll = false;
+        }
+    }
 }
 
 void Notebook::cellFailedToParse(Cell *cell, ParseResult result, Parser parser)
@@ -165,6 +197,8 @@
     cell->setResult(pprint(result, parser, PPrint::HTML));
     cell->setStatus(Cell::IDLE);
     cell->setResultType(Cell::DIAGNOSTIC);
+
+    _runningAll = false;
 }
 
 void Notebook::cellWaiting(Cell *cell)
@@ -184,4 +218,6 @@
     qInfo() << "cellQuit" << cell->uuid();
     cell->setResult("");
     cell->setStatus(Cell::IDLE);
+
+    _runningAll = false;
 }
diff --git a/ide/Notebook.h b/ide/Notebook.h
index 6a6541d..83f9fc7 100644
--- a/ide/Notebook.h
+++ b/ide/Notebook.h
@@ -25,6 +25,8 @@
 
     Q_INVOKABLE void runCell(QUuid uuid);
     Q_INVOKABLE void quitCell(QUuid uuid);
+    Q_INVOKABLE void runAll();
+    Q_INVOKABLE void reset();
 
     Q_INVOKABLE void fromJson(QJsonDocument doc);
     Q_INVOKABLE void open(QString path);
@@ -41,6 +43,7 @@
     void cellModelChanged();
     void saveError(QString message);
     void savePathChanged(QString savePath);
+    void saved();
 
 protected slots:
     void cellFinishedRunning(Cell *cell, RuntimeResult result);
@@ -57,6 +60,7 @@
     QThread *_rtThread;
     NbRuntime *_rt;
     QString _savePath = "";
+    bool _runningAll = false;
 };
 
 Q_DECLARE_METATYPE(Notebook)
diff --git a/ide/RecentModel.cpp b/ide/RecentModel.cpp
new file mode 100644
index 0000000..30824ed
--- /dev/null
+++ b/ide/RecentModel.cpp
@@ -0,0 +1,62 @@
+#include "RecentModel.h"
+#include <QSettings>
+
+RecentModel::RecentModel(QObject *parent)
+    : QAbstractListModel(parent)
+{
+    _recents = _settings.value("recents").toStringList();
+}
+
+RecentModel::RecentModel(const RecentModel &other, QObject *parent)
+    : RecentModel(parent)
+{
+    _recents = other._recents;
+}
+
+int RecentModel::rowCount(const QModelIndex &parent) const
+{
+    if (parent.isValid())
+        return 0;
+
+    return _recents.size();
+}
+
+QVariant RecentModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid())
+        return QVariant();
+
+    if (role == PathRole)
+        return _recents[index.row()];
+
+    return QVariant();
+}
+
+QHash<int, QByteArray> RecentModel::roleNames() const
+{
+    return {{PathRole, "path"}};
+}
+
+void RecentModel::add(QString path)
+{
+    remove(path);
+
+    beginInsertRows(QModelIndex(), 0, 0);
+    _recents.prepend(path);
+    endInsertRows();
+
+    _settings.setValue("recents", _recents);
+}
+
+void RecentModel::remove(QString path)
+{
+    if (_recents.contains(path))
+    {
+        int index = _recents.indexOf(path);
+        beginRemoveRows(QModelIndex(), index, index);
+        _recents.removeAt(index);
+        endRemoveRows();
+
+        _settings.setValue("recents", _recents);
+    }
+}
diff --git a/ide/RecentModel.h b/ide/RecentModel.h
new file mode 100644
index 0000000..76cd461
--- /dev/null
+++ b/ide/RecentModel.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <QAbstractListModel>
+#include <qqml.h>
+#include <QSettings>
+
+class RecentModel : public QAbstractListModel
+{
+    Q_OBJECT
+    QML_ELEMENT
+
+public:
+    explicit RecentModel(QObject *parent = nullptr);
+    RecentModel(const RecentModel &other, QObject *parent = nullptr);
+
+    enum
+    {
+        PathRole = Qt::UserRole + 1
+    };
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+    QHash<int, QByteArray> roleNames() const override;
+
+    Q_INVOKABLE void add(QString path);
+    Q_INVOKABLE void remove(QString path);
+
+private:
+    QStringList _recents;
+    QSettings _settings;
+};
+
+Q_DECLARE_METATYPE(RecentModel)
+Q_DECLARE_METATYPE(RecentModel *)
diff --git a/ide/qml/NbWindow.qml b/ide/qml/NbWindow.qml
index 5710c9e..858fb5e 100644
--- a/ide/qml/NbWindow.qml
+++ b/ide/qml/NbWindow.qml
@@ -15,7 +15,8 @@
     Material.theme: Material.Light
     Material.accent: Material.Orange
 
-    minimumWidth: column.implicitWidth
+    minimumWidth: 600
+    minimumHeight: 400
 
     required property ApplicationWindow welcomeWindow
 
@@ -92,10 +93,14 @@
 
             Action {
                 text: qsTr("Run &All")
+
+                onTriggered: notebook.runAll();
             }
 
             Action {
                 text: qsTr("&Reset Runtime State")
+
+                onTriggered: notebook.reset();
             }
         }
     }
@@ -107,6 +112,8 @@
         {
             console.error(message)
         }
+
+        onSaved: welcomeWindow.recentModel.add(notebook.savePath)
     }
 
     ColumnLayout {
@@ -137,7 +144,7 @@
                         ColumnLayout {
                             Label {
                                 font.pointSize: 18
-                                text: qsTr("Notebook")
+                                text: notebook.savePath != "" ? notebook.savePath.split("/").pop().split(".").slice(0,-1).join('.') : qsTr("Notebook")
                             }
 
                             Label {
diff --git a/ide/qml/RecentNotebook.qml b/ide/qml/RecentNotebook.qml
index d0b1120..194424c 100644
--- a/ide/qml/RecentNotebook.qml
+++ b/ide/qml/RecentNotebook.qml
@@ -8,6 +8,7 @@
     property string name: "Hello.refnb"
     property alias containsMouse: mouseArea.containsMouse
     signal clicked()
+    signal removeClicked()
 
     Image {
         id: nbIcon
@@ -27,7 +28,24 @@
             anchors.fill: parent
             hoverEnabled: true
 
-            onClicked: root.clicked()
+            acceptedButtons: Qt.LeftButton | Qt.RightButton
+
+            onClicked: {
+                if (mouse.button == Qt.LeftButton)
+                    root.clicked();
+                else if (mouse.button == Qt.RightButton)
+                    contextMenu.popup();
+            }
+        }
+
+        Menu {
+            id: contextMenu
+
+            MenuItem {
+                text: qsTr("Remove")
+
+                onClicked: root.removeClicked()
+            }
         }
     }
 }
diff --git a/ide/qml/main.qml b/ide/qml/main.qml
index 23f8926..210640c 100644
--- a/ide/qml/main.qml
+++ b/ide/qml/main.qml
@@ -2,6 +2,9 @@
 import QtQuick.Controls 2.15
 import QtQuick.Controls.Material 2.0
 import QtQuick.Layouts 1.11
+import Qt.labs.settings 1.0
+
+import sh.swisschili.REFAL 1.0
 
 ApplicationWindow {
     id: root
@@ -19,6 +22,8 @@
 
     visible: true
 
+    property alias recentModel: recents
+
     function openNotebook(path=null) {
         let NbWindow = Qt.createComponent("qrc:///qml/NbWindow.qml");
         let window = NbWindow.createObject(null, {welcomeWindow: root});
@@ -36,6 +41,10 @@
             show();
     }
 
+    RecentModel {
+        id: recents
+    }
+
     Label {
         id: textRefal
         text: qsTr("REFAL")
@@ -125,21 +134,20 @@
                 Layout.fillWidth: true
                 Layout.fillHeight: false
 
-                model: [
-                    // "~/Documents/Hello.refnb", "~/Downloads/stuff/Goodbye.refnb", "/home/ch/dev/REFAL/build/test.refnb"
-                ]
+                model: recents
 
                 delegate: RecentNotebook {
                     Layout.leftMargin: 8
                     Layout.rightMargin: 8
 
-                    name: modelData.split("/").pop()
+                    name: path.split("/").pop()
 
-                    ToolTip.text: modelData
+                    ToolTip.text: path
                     ToolTip.visible: containsMouse
                     ToolTip.delay: 1000
 
-                    onClicked: root.openNotebook(modelData)
+                    onClicked: root.openNotebook(path)
+                    onRemoveClicked: recents.remove(path)
                 }
             }
 
diff --git a/ts/refal_en_US.qm b/ts/refal_en_US.qm
index 71c6570..899dbe0 100644
--- a/ts/refal_en_US.qm
+++ b/ts/refal_en_US.qm
Binary files differ
diff --git a/ts/refal_en_US.ts b/ts/refal_en_US.ts
index cf241b8..a22f35a 100644
--- a/ts/refal_en_US.ts
+++ b/ts/refal_en_US.ts
@@ -21,27 +21,27 @@
         <translation>&amp;New</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="35"/>
+        <location filename="../ide/qml/NbWindow.qml" line="39"/>
         <source>&amp;Save</source>
         <translation>&amp;Save</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="44"/>
+        <location filename="../ide/qml/NbWindow.qml" line="48"/>
         <source>&amp;Open</source>
         <translation>&amp;Open</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="54"/>
+        <location filename="../ide/qml/NbWindow.qml" line="58"/>
         <source>&amp;View</source>
         <translation>&amp;View</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="57"/>
+        <location filename="../ide/qml/NbWindow.qml" line="61"/>
         <source>&amp;Welcome Window</source>
         <translation>&amp;Welcome Window</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="69"/>
+        <location filename="../ide/qml/NbWindow.qml" line="73"/>
         <source>&amp;Variable Inspector</source>
         <translation>&amp;Variable Inspector</translation>
     </message>
@@ -61,22 +61,22 @@
         <translation>Run &amp;All</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="98"/>
+        <location filename="../ide/qml/NbWindow.qml" line="100"/>
         <source>&amp;Reset Runtime State</source>
         <translation>&amp;Reset Runtime State</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="140"/>
+        <location filename="../ide/qml/NbWindow.qml" line="146"/>
         <source>Notebook</source>
         <translation>Notebook</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="146"/>
+        <location filename="../ide/qml/NbWindow.qml" line="152"/>
         <source>Looks like you haven&apos;t created any cells yet. Click the + button below to create one.</source>
         <translation>Looks like you haven&apos;t created any cells yet. Click the + button below to create one.</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="208"/>
+        <location filename="../ide/qml/NbWindow.qml" line="214"/>
         <source>Variables</source>
         <translation>Variables</translation>
     </message>
@@ -95,29 +95,37 @@
     </message>
 </context>
 <context>
+    <name>RecentNotebook</name>
+    <message>
+        <location filename="../ide/qml/RecentNotebook.qml" line="45"/>
+        <source>Remove</source>
+        <translation>Remove</translation>
+    </message>
+</context>
+<context>
     <name>main</name>
     <message>
-        <location filename="../ide/qml/main.qml" line="41"/>
+        <location filename="../ide/qml/main.qml" line="50"/>
         <source>REFAL</source>
         <translation>REFAL</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="55"/>
+        <location filename="../ide/qml/main.qml" line="64"/>
         <source>Studio</source>
         <translation>Studio</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="106"/>
+        <location filename="../ide/qml/main.qml" line="115"/>
         <source>New Notebook</source>
         <translation>New Notebook</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="117"/>
+        <location filename="../ide/qml/main.qml" line="126"/>
         <source>Open Existing</source>
         <translation>Open Existing</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="151"/>
+        <location filename="../ide/qml/main.qml" line="159"/>
         <source>Your recent notebooks will appear here</source>
         <translation>Your recent notebooks will appear here</translation>
     </message>
diff --git a/ts/refal_ru_RU.qm b/ts/refal_ru_RU.qm
index ca42b3a..dc0fcd2 100644
--- a/ts/refal_ru_RU.qm
+++ b/ts/refal_ru_RU.qm
Binary files differ
diff --git a/ts/refal_ru_RU.ts b/ts/refal_ru_RU.ts
index fbf55af..214753f 100644
--- a/ts/refal_ru_RU.ts
+++ b/ts/refal_ru_RU.ts
@@ -21,27 +21,27 @@
         <translation>Создать &amp;Новую Тетрадь</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="35"/>
+        <location filename="../ide/qml/NbWindow.qml" line="39"/>
         <source>&amp;Save</source>
         <translation>&amp;Сохранить</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="44"/>
+        <location filename="../ide/qml/NbWindow.qml" line="48"/>
         <source>&amp;Open</source>
         <translation>&amp;Открыть</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="54"/>
+        <location filename="../ide/qml/NbWindow.qml" line="58"/>
         <source>&amp;View</source>
-        <translation>&amp;Видеть</translation>
+        <translation>&amp;Вид</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="57"/>
+        <location filename="../ide/qml/NbWindow.qml" line="61"/>
         <source>&amp;Welcome Window</source>
         <translation>&amp;Стартовая Страниця</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="69"/>
+        <location filename="../ide/qml/NbWindow.qml" line="73"/>
         <source>&amp;Variable Inspector</source>
         <translation>Инспектор &amp;Переменных</translation>
     </message>
@@ -61,22 +61,22 @@
         <translation>Запустить &amp;Все Ячейки</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="98"/>
+        <location filename="../ide/qml/NbWindow.qml" line="100"/>
         <source>&amp;Reset Runtime State</source>
         <translation>Востоновить &amp;Исходное Состояние</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="140"/>
+        <location filename="../ide/qml/NbWindow.qml" line="146"/>
         <source>Notebook</source>
         <translation>Тетрадь</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="146"/>
+        <location filename="../ide/qml/NbWindow.qml" line="152"/>
         <source>Looks like you haven&apos;t created any cells yet. Click the + button below to create one.</source>
         <translation>Вы еще не создали ячейку, нажмите кнопку + снизы что бы её создать.</translation>
     </message>
     <message>
-        <location filename="../ide/qml/NbWindow.qml" line="208"/>
+        <location filename="../ide/qml/NbWindow.qml" line="214"/>
         <source>Variables</source>
         <translation>Переменные</translation>
     </message>
@@ -95,29 +95,37 @@
     </message>
 </context>
 <context>
+    <name>RecentNotebook</name>
+    <message>
+        <location filename="../ide/qml/RecentNotebook.qml" line="45"/>
+        <source>Remove</source>
+        <translation>Убрать</translation>
+    </message>
+</context>
+<context>
     <name>main</name>
     <message>
-        <location filename="../ide/qml/main.qml" line="41"/>
+        <location filename="../ide/qml/main.qml" line="50"/>
         <source>REFAL</source>
         <translation>РЕФАЛ</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="55"/>
+        <location filename="../ide/qml/main.qml" line="64"/>
         <source>Studio</source>
         <translation>Студия</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="106"/>
+        <location filename="../ide/qml/main.qml" line="115"/>
         <source>New Notebook</source>
         <translation>Создать Тетрадь</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="117"/>
+        <location filename="../ide/qml/main.qml" line="126"/>
         <source>Open Existing</source>
         <translation>Открыть</translation>
     </message>
     <message>
-        <location filename="../ide/qml/main.qml" line="151"/>
+        <location filename="../ide/qml/main.qml" line="159"/>
         <source>Your recent notebooks will appear here</source>
         <translation>Ваши недавние тетради появится здесь</translation>
     </message>