aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CommandParser.hpp29
-rw-r--r--src/Configuration.hpp13
-rw-r--r--src/InputMediator.hpp33
-rw-r--r--src/LuaRuntime.cpp20
-rw-r--r--src/LuaRuntime.hpp29
-rw-r--r--src/keymap/KeySeqParser.hpp44
-rw-r--r--src/keymap/KeymapEvaluator.hpp42
-rw-r--r--src/utils.hpp11
-rw-r--r--src/widgets/MainWindow.hpp19
-rw-r--r--src/widgets/WebView.hpp13
-rw-r--r--src/widgets/WebViewStack.hpp55
11 files changed, 296 insertions, 12 deletions
diff --git a/src/CommandParser.hpp b/src/CommandParser.hpp
new file mode 100644
index 0000000..9197df5
--- /dev/null
+++ b/src/CommandParser.hpp
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <QtCore/qcontainerfwd.h>
+#include <QtCore>
+
+enum CommandType {
+ Noop,
+ LuaEval,
+ Open,
+ TabOpen,
+ TabNext,
+ TabPrev,
+ TabSelect,
+};
+
+struct Cmd {
+ CommandType command;
+ QString argsString;
+ QString rawInput;
+};
+
+class CommandParser {
+public:
+ CommandParser();
+ Cmd parse(QString command);
+
+private:
+ CommandType toCommandType(QString cmd);
+};
diff --git a/src/Configuration.hpp b/src/Configuration.hpp
new file mode 100644
index 0000000..cc68803
--- /dev/null
+++ b/src/Configuration.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <QtCore>
+#include <cstdio>
+
+class Configuration : public QObject {
+ Q_OBJECT
+
+public:
+ using QObject::QObject;
+
+ QUrl newTabUrl = QUrl("https://lite.duckduckgo.com");
+};
diff --git a/src/InputMediator.hpp b/src/InputMediator.hpp
new file mode 100644
index 0000000..7194ff9
--- /dev/null
+++ b/src/InputMediator.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <QWidget>
+#include <QtCore>
+
+#include "LuaRuntime.hpp"
+#include "keymap/KeymapEvaluator.hpp"
+#include "utils.hpp"
+#include "widgets/WebViewStack.hpp"
+
+class InputMediator : public QObject {
+ Q_OBJECT
+
+public:
+ InputMediator(WebViewStack *webViewStack, LuaRuntime *luaRuntime,
+ KeymapEvaluator *keymapEvaluator);
+ ~InputMediator();
+
+ DELEGATE(webViewStack, openUrl, openUrl)
+ DELEGATE(webViewStack, currentUrl, currentUrl)
+ DELEGATE(webViewStack, next, nextWebView)
+ DELEGATE(webViewStack, previous, previousWebView)
+ DELEGATE(webViewStack, closeCurrent, closeCurrentWebView)
+ DELEGATE(keymapEvaluator, evaluate, evaluateKeymap)
+
+private:
+ void evaluateCommand(QString command);
+
+private:
+ WebViewStack *webViewStack;
+ LuaRuntime *luaRuntime;
+ KeymapEvaluator *keymapEvaluator;
+};
diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp
index e66c591..d89f7dc 100644
--- a/src/LuaRuntime.cpp
+++ b/src/LuaRuntime.cpp
@@ -1,24 +1,20 @@
+#include <QtCore>
#include <lua.hpp>
-
-#include "LuaRuntime.hpp"
-
extern "C" {
#include <luv.h>
-// Forward declare luv registration function
-// LUALIB_API int luaopen_luv(lua_State *L);
}
+#include "LuaRuntime.hpp"
+
LuaRuntime::LuaRuntime() {
state = luaL_newstate();
luaL_openlibs(state);
- luaopen_luv(state);
- if (luaL_dostring(state, "_G.uv = require'luv'")) {
- qDebug() << "Unable to load luv: " << lua_tostring(state, -1);
- } else {
- qDebug() << "succ";
- }
+ // Load `uv` (luv)
+ luaopen_luv(state);
+ lua_setglobal(state, "uv");
+ // Load `web`
luaL_Reg weblib[] = {
{"open", &LuaRuntime::lua_onUrlOpen},
{"tabopen", &LuaRuntime::lua_onUrlTabOpen},
@@ -43,7 +39,7 @@ LuaRuntime::LuaRuntime() {
// auto pp = R"(
// print('Hello -- ');
// local t = uv.new_timer();
- // uv.timer_start(t, 7000, 0, function()
+ // uv.timer_start(t, 4000, 0, function()
// print('after time')
// end);
// uv.run();
diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp
new file mode 100644
index 0000000..5bfc82c
--- /dev/null
+++ b/src/LuaRuntime.hpp
@@ -0,0 +1,29 @@
+#pragma once
+#include <QtCore>
+#include <lua.hpp>
+
+#include "widgets/WebViewStack.hpp"
+
+class LuaRuntime : public QObject {
+ Q_OBJECT
+
+public:
+ static LuaRuntime *instance() {
+ static LuaRuntime inst;
+ return &inst;
+ }
+
+ void evaluate(QString code);
+
+signals:
+ void urlOpened(QString url, OpenType openType);
+
+protected:
+ LuaRuntime();
+ ~LuaRuntime();
+ static int lua_onUrlOpen(lua_State *state);
+ static int lua_onUrlTabOpen(lua_State *state);
+
+private:
+ lua_State *state;
+};
diff --git a/src/keymap/KeySeqParser.hpp b/src/keymap/KeySeqParser.hpp
new file mode 100644
index 0000000..fac2546
--- /dev/null
+++ b/src/keymap/KeySeqParser.hpp
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <QtCore/qnamespace.h>
+#include <QtCore>
+#include <cmath>
+
+struct KeyChord {
+ Qt::KeyboardModifiers mod;
+ Qt::Key key;
+};
+bool operator==(const KeyChord a, const KeyChord b);
+
+typedef QList<KeyChord> KeySequence;
+
+enum KeyMatchType {
+ NoMatch,
+ Match,
+ Pending,
+};
+
+class KeySeqParser {
+public:
+ static const KeyMatchType keySequenceMatch(const KeySequence target,
+ const KeySequence current) {
+ for (int i = 0; i < target.length(); i++) {
+ if (current.length() <= i)
+ return KeyMatchType::Pending;
+
+ if (target[i].key != current[i].key ||
+ !target[i].mod.testFlags(current[i].mod))
+ return KeyMatchType::NoMatch;
+ }
+
+ return KeyMatchType::Match;
+ }
+
+public:
+ KeySeqParser();
+
+ KeySequence parse(QString keySequence);
+
+private:
+ Qt::Key parseKey(QString keyName);
+};
diff --git a/src/keymap/KeymapEvaluator.hpp b/src/keymap/KeymapEvaluator.hpp
new file mode 100644
index 0000000..db93900
--- /dev/null
+++ b/src/keymap/KeymapEvaluator.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <QWidget>
+#include <QtCore/qmap.h>
+#include <QtCore/qnamespace.h>
+#include <QtCore>
+#include <functional>
+
+#include "keymap/KeySeqParser.hpp"
+#include "utils.hpp"
+
+typedef std::function<void()> KeyAction;
+
+struct KeyMap {
+ KeySequence keySequence;
+ KeyAction action;
+};
+
+enum KeyMode { Normal, Insert };
+
+class KeymapEvaluator : public QObject {
+ Q_OBJECT
+
+public:
+ KeymapEvaluator();
+
+ void addKeymap(KeyMode mode, QString key, KeyAction action);
+ bool evaluate(Qt::KeyboardModifiers modifiers, Qt::Key key);
+
+ DEFINE_SETTER(setCurrentMode, currentMode)
+ DEFINE_GETTER(getCurrentMode, currentMode)
+
+private:
+ const QList<KeyMap> *currentModeKeys();
+ bool isInsertableMode();
+
+private:
+ QMap<KeyMode, QList<KeyMap>> modalKeys;
+ KeySeqParser keySeqParser;
+ KeyMode currentMode = KeyMode::Normal;
+ KeySequence activeKeySequence;
+};
diff --git a/src/utils.hpp b/src/utils.hpp
new file mode 100644
index 0000000..0650ac2
--- /dev/null
+++ b/src/utils.hpp
@@ -0,0 +1,11 @@
+
+#define DELEGATE(OBJ, METHOD, METHOD_AS) \
+ template <typename... Args> decltype(auto) METHOD_AS(Args &&...args) { \
+ return OBJ->METHOD(std::forward<Args>(args)...); \
+ }
+
+#define DEFINE_SETTER(METHOD, PROPERTY) \
+ template <typename Arg> void METHOD(Arg val) { PROPERTY = val; }
+
+#define DEFINE_GETTER(METHOD, EXPR) \
+ template <typename Arg> decltype(auto) METHOD() { return EXPR; }
diff --git a/src/widgets/MainWindow.hpp b/src/widgets/MainWindow.hpp
new file mode 100644
index 0000000..2bbc42e
--- /dev/null
+++ b/src/widgets/MainWindow.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <QMainWindow>
+
+#include "Configuration.hpp"
+#include "InputMediator.hpp"
+
+class MainWindow : public QMainWindow {
+public:
+ MainWindow();
+
+private:
+ void keyPressEvent(QKeyEvent *event) override;
+ bool eventFilter(QObject *object, QEvent *event) override;
+
+private:
+ InputMediator *inputMediator;
+ Configuration configuration;
+};
diff --git a/src/widgets/WebView.hpp b/src/widgets/WebView.hpp
new file mode 100644
index 0000000..8a95139
--- /dev/null
+++ b/src/widgets/WebView.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <QKeyEvent>
+#include <QWebEngineView>
+#include <QWidget>
+#include <QtCore>
+
+class WebView : public QWebEngineView {
+ Q_OBJECT
+
+public:
+ WebView(QWebEngineProfile *profile);
+};
diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp
new file mode 100644
index 0000000..e5b7ecc
--- /dev/null
+++ b/src/widgets/WebViewStack.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <QStackedLayout>
+#include <QWebEngineProfile>
+#include <sys/types.h>
+
+#include "Configuration.hpp"
+#include "widgets/WebView.hpp"
+
+enum OpenType { OpenUrl, OpenUrlInTab, OpenUrlInBgTab, OpenUrlInWindow };
+
+struct Tab {
+ QString url;
+ QString title;
+};
+
+class WebViewStack : public QWidget {
+ Q_OBJECT
+
+public:
+ inline static const QUrl NewtabURL = QUrl("about:blank");
+
+public:
+ WebViewStack(const Configuration *configuration,
+ QWebEngineProfile *profile = new QWebEngineProfile,
+ QWidget *parent = nullptr);
+
+ void openUrl(QUrl url, OpenType openType = OpenType::OpenUrl);
+
+ std::vector<QUrl> urls();
+ QList<Tab> getTabList();
+ u_int32_t currentWebViewIndex();
+ u_int32_t count();
+ QUrl currentUrl();
+
+ void focusWebView(long index);
+ void next();
+ void previous();
+
+ void close(long index);
+ void closeCurrent();
+
+private:
+ void setCurrentUrl(QUrl url);
+ WebView *createNewWebView(QUrl url, bool focus = false);
+
+private slots:
+ void onNewWebViewRequest(QWebEngineNewWindowRequest &request);
+
+private:
+ const Configuration *configuration;
+ QWebEngineProfile *profile;
+ QStackedLayout *layout;
+ QList<WebView *> webViewList;
+};