From f09f1aa704f06472ec134b40e2f69bf3279c3f06 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sat, 22 Mar 2025 00:51:46 +0530 Subject: Add web.keymap.set + test keymaps config.lua --- TODO.org | 13 ++++++++---- config.lua | 16 ++++++++++++++ src/InputMediator.cpp | 10 +++++++++ src/InputMediator.hpp | 3 ++- src/LuaRuntime.cpp | 47 +++++++++++++++++++++++++++++++++++++++++- src/LuaRuntime.hpp | 6 ++++++ src/keymap/KeymapEvaluator.cpp | 10 +++++++++ src/keymap/KeymapEvaluator.hpp | 1 + src/main.cpp | 4 ++++ src/widgets/MainWindow.cpp | 4 ++++ 10 files changed, 108 insertions(+), 6 deletions(-) create mode 100644 config.lua diff --git a/TODO.org b/TODO.org index b282cc7..a8db97a 100644 --- a/TODO.org +++ b/TODO.org @@ -1,12 +1,16 @@ ** Current - [X] Process spawning lua (+ stdio) -- [ ] Keybindings (lua api) +- [X] Keybindings (lua api) +- [ ] example: trigger dmenu for simple selection +- [ ] Config loading and runtime path - [ ] Tab history navigation -- [ ] Press tab for fill highlighted item in completion +- [ ] Tab next/prev +- [ ] Get tab list api - [ ] Assign ID to each tab (reference in lua api) -- [ ] Multi-window +- [ ] Tab select by id +- [X] event loop for async work - [ ] Fix segfault on quit -- [ ] event loop for async work +- [ ] Multi-window ** Next - [ ] Modal keys @@ -17,6 +21,7 @@ - [ ] Bookmarking ** Later +- [ ] Support multiple modes for keymap.set: `web.keymap.set({'n','i'}, ...)` - [ ] Search aliasing (lua api) - [ ] downloading - [ ] Search text in page diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..1c46da0 --- /dev/null +++ b/config.lua @@ -0,0 +1,16 @@ +print('hello starting up...') + +--- @type table +web = web +--- @type table +uv = uv + +web.keymap.set('n', 'm', function() + print('Hello world. Keypress test') +end) + +web.keymap.set('n', 'o', function() + web.tabopen('https://lite.duckduckgo.com') +end) + +print('ending...') diff --git a/src/InputMediator.cpp b/src/InputMediator.cpp index f935ad2..61ef125 100644 --- a/src/InputMediator.cpp +++ b/src/InputMediator.cpp @@ -5,14 +5,24 @@ #include "CommandParser.hpp" #include "InputMediator.hpp" #include "LuaRuntime.hpp" +#include "keymap/KeymapEvaluator.hpp" #include "widgets/WebViewStack.hpp" +// TODO: Rename this InputMediator::InputMediator(WebViewStack *webViewStack, LuaRuntime *luaRuntime, KeymapEvaluator *keymapEvaluator) : QObject(), webViewStack(webViewStack), luaRuntime(luaRuntime), keymapEvaluator(keymapEvaluator) { connect(luaRuntime, &LuaRuntime::urlOpened, webViewStack, &WebViewStack::openUrl); + connect(luaRuntime, &LuaRuntime::keymapAddRequested, this, + &InputMediator::addKeymap); +} + +void InputMediator::addKeymap(QString modeString, QString keyseq, + std::function action) { + KeyMode mode = keymapEvaluator->modeFromString(modeString); + keymapEvaluator->addKeymap(mode, keyseq, action); } void InputMediator::evaluateCommand(QString command) { diff --git a/src/InputMediator.hpp b/src/InputMediator.hpp index 7194ff9..87395d5 100644 --- a/src/InputMediator.hpp +++ b/src/InputMediator.hpp @@ -23,8 +23,9 @@ public: DELEGATE(webViewStack, closeCurrent, closeCurrentWebView) DELEGATE(keymapEvaluator, evaluate, evaluateKeymap) -private: +protected: void evaluateCommand(QString command); + void addKeymap(QString mode, QString keyseq, std::function action); private: WebViewStack *webViewStack; diff --git a/src/LuaRuntime.cpp b/src/LuaRuntime.cpp index e9a30b1..f83ee48 100644 --- a/src/LuaRuntime.cpp +++ b/src/LuaRuntime.cpp @@ -22,6 +22,14 @@ LuaRuntime::LuaRuntime() { }; luaL_newlib(state, weblib); lua_setglobal(state, web_global_name); + + lua_getglobal(state, web_global_name); + luaL_Reg keymaplib[] = { + {"set", &LuaRuntime::lua_addKeymap}, + }; + luaL_newlib(state, keymaplib); + lua_setfield(state, -2, "keymap"); + lua_pop(state, 1); } void LuaRuntime::startEventLoop() { @@ -51,7 +59,7 @@ void LuaRuntime::stopEventLoop() { void LuaRuntime::evaluate(QString code) { eventLoop->queueTask([this, code]() { - if (luaL_dostring(state, code.toStdString().c_str())) { + if (luaL_dostring(state, code.toStdString().c_str()) != LUA_OK) { auto value = lua_tostring(state, -1); lua_pop(state, 1); @@ -102,6 +110,43 @@ int LuaRuntime::lua_onUrlTabOpen(lua_State *state) { return 1; } +int LuaRuntime::lua_addKeymap(lua_State *state) { + const char *mode = lua_tostring(state, 1); + const char *keyseq = lua_tostring(state, 2); + qDebug() << "Adduing" << mode << keyseq; + + qDebug() << "---" << lua_isfunction(state, 3); + + lua_pushvalue(state, 3); + int functionRef = luaL_ref(state, LUA_REGISTRYINDEX); + auto action = [state, functionRef]() { + qDebug() << "Hello"; + + lua_rawgeti(state, LUA_REGISTRYINDEX, functionRef); + if (lua_pcall(state, 0, 0, 0) != LUA_OK) { + const char *error = lua_tostring(state, -1); + qDebug() << "Error calling Lua function:" << error; + lua_pop(state, 1); + } else { + qDebug() << "Done"; + } + lua_pop(state, 1); + }; + + auto runtime = LuaRuntime::instance(); + emit runtime->keymapAddRequested(mode, keyseq, action); + + return 1; +} + +void LuaRuntime::loadFile(QString path) { + qDebug() << "Loading: " << path; + if (luaL_dofile(state, path.toStdString().c_str()) != LUA_OK) { + qDebug() << "Load file error:" << lua_tostring(state, -1); + lua_pop(state, 1); + } +} + LuaRuntime::~LuaRuntime() { stopEventLoop(); lua_close(state); diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp index dd5c0ec..6c45ca5 100644 --- a/src/LuaRuntime.hpp +++ b/src/LuaRuntime.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "AsyncEventLoop.hpp" @@ -18,17 +19,21 @@ public: void evaluate(QString code); QVariant evaluateSync(QString code); + void loadFile(QString code); + void stopEventLoop(); void startEventLoop(); QVariant getValue(int idx); DELEGATE(eventLoop, queueTask, queueTask) + DEFINE_GETTER(getState, state) signals: void urlOpened(QString url, OpenType openType); void evaluationCompleted(QVariant value); void evaluationFailed(QString value); + void keymapAddRequested(QString mode, QString keyseq, std::function); // void outputProduced(QVariant value); protected: @@ -36,6 +41,7 @@ protected: ~LuaRuntime(); static int lua_onUrlOpen(lua_State *state); static int lua_onUrlTabOpen(lua_State *state); + static int lua_addKeymap(lua_State *state); private: lua_State *state; diff --git a/src/keymap/KeymapEvaluator.cpp b/src/keymap/KeymapEvaluator.cpp index baae819..b20aeda 100644 --- a/src/keymap/KeymapEvaluator.cpp +++ b/src/keymap/KeymapEvaluator.cpp @@ -11,6 +11,8 @@ void KeymapEvaluator::addKeymap(KeyMode mode, QString key, KeyAction action) { if (!modalKeys.contains(mode)) modalKeys.insert(mode, {}); + qDebug() << " " << mode << key; + auto keySeq = keySeqParser.parse(key); modalKeys[mode].append((KeyMap){.keySequence = keySeq, .action = action}); } @@ -57,3 +59,11 @@ const QList *KeymapEvaluator::currentModeKeys() { return &modalKeys[currentMode]; } + +KeyMode KeymapEvaluator::modeFromString(QString modeString) { + if (modeString == "n") + return KeyMode::Normal; + if (modeString == "i") + return KeyMode::Insert; + return KeyMode::Normal; +} diff --git a/src/keymap/KeymapEvaluator.hpp b/src/keymap/KeymapEvaluator.hpp index db93900..b98a881 100644 --- a/src/keymap/KeymapEvaluator.hpp +++ b/src/keymap/KeymapEvaluator.hpp @@ -26,6 +26,7 @@ public: void addKeymap(KeyMode mode, QString key, KeyAction action); bool evaluate(Qt::KeyboardModifiers modifiers, Qt::Key key); + KeyMode modeFromString(QString modeString); DEFINE_SETTER(setCurrentMode, currentMode) DEFINE_GETTER(getCurrentMode, currentMode) diff --git a/src/main.cpp b/src/main.cpp index a83408c..d86b484 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,15 @@ #include #include +#include "LuaRuntime.hpp" #include "widgets/MainWindow.hpp" int main(int argc, char *argv[]) { QApplication app(argc, argv); + auto lua = LuaRuntime::instance(); + lua->startEventLoop(); + MainWindow mainWindow; mainWindow.setWindowTitle("null-browser"); mainWindow.show(); diff --git a/src/widgets/MainWindow.cpp b/src/widgets/MainWindow.cpp index 32bde30..ca572e7 100644 --- a/src/widgets/MainWindow.cpp +++ b/src/widgets/MainWindow.cpp @@ -14,6 +14,7 @@ MainWindow::MainWindow() { setStyleSheet("background-color: #000; color: #fff;"); setCentralWidget(new QWidget()); // TODO: manage widget memory + // Global event filter qApp->installEventFilter(this); // Root stacked layout @@ -40,6 +41,9 @@ MainWindow::MainWindow() { inputMediator = new InputMediator(webViewStack, LuaRuntime::instance(), keymapEvaluator); + // NOTE: TMP + LuaRuntime::instance()->loadFile("./config.lua"); + // TODO: remove keymapEvaluator->addKeymap(KeyMode::Normal, "i", [keymapEvaluator]() { keymapEvaluator->setCurrentMode(KeyMode::Insert); -- cgit v1.3.1