aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-04-19 17:56:03 +0530
committerAkshay Nair <phenax5@gmail.com>2025-04-19 17:56:03 +0530
commit0e95e99e72237058465959d55b77750a9d7c1bef (patch)
tree5b99cd64f7c49b949a6381c4654ec253822934b5
parent7a458b424c2c1a6ed251211b25261acffef59b7f (diff)
downloadnull-browser-0e95e99e72237058465959d55b77750a9d7c1bef.tar.gz
null-browser-0e95e99e72237058465959d55b77750a9d7c1bef.zip
Add web.search and search text implemnetation
-rw-r--r--TODO.org29
-rw-r--r--config.lua10
-rw-r--r--lua/null-browser/api.lua18
-rw-r--r--src/AsyncEventLoop.cpp2
-rw-r--r--src/LuaRuntime.hpp3
-rw-r--r--src/LuaRuntimeApi.hpp29
-rw-r--r--src/WindowActionRouter.cpp17
-rw-r--r--src/WindowActionRouter.hpp1
-rw-r--r--src/WindowMediator.hpp1
-rw-r--r--src/widgets/WebView.hpp1
-rw-r--r--src/widgets/WebViewStack.cpp20
-rw-r--r--src/widgets/WebViewStack.hpp1
12 files changed, 128 insertions, 4 deletions
diff --git a/TODO.org b/TODO.org
index 96e9eb4..bf2511e 100644
--- a/TODO.org
+++ b/TODO.org
@@ -1,6 +1,6 @@
** Usable
- [ ] Tests for api
-- [ ] Search text in page
+- [X] Search text in page
- [ ] Dev tools
- [ ] Fullscreen
- [ ] Zoom in/out
@@ -10,6 +10,7 @@
- [ ] Notifications
** Bugs
+- [ ] INVESTIGATE: segfault on api module error
- [ ] INVESTIGATE: Check why urlchanged doesnt fire for first url open
- [ ] INVESTIGATE: Segfault on close
- [ ] INVESTIGATE: Errors in keymap/thread segfaults
@@ -84,4 +85,30 @@ web.history.back(1, { win = 1 }) -- Back for current view in win 1
web.keymap.set('n', '<c-r>', ..., { view = 1 }) -- Set keymap for view 1
web.keymap.set('n', '<c-r>', ..., { win = 1 }) -- Set keymap for win 1
web.opt.new_tab_url = 'https://duckduckgo.com'
+
+-- Search api
+web.search.set_search_text('whatever')
+web.search.next()
+web.search.prev()
+web.search.get_search_text()
+web.search.current()
+web.search.total()
+
+web.keymap.set('n', '/', function()
+ dmenu.input({ prompt = 'Search:' }, function(err, input)
+ if err or not input then return end
+ web.search.set_search_text(input)
+ end)
+end)
+web.keymap.set('n', 'n', function() web.search.next() end)
+web.keymap.set('n', 'p', function() web.search.prev() end)
+
+web.event.add_listener('SearchChanged', {
+ callback = function()
+ local label =
+ web.search.get_search_text() .. ': ' .. web.search.current() .. '/' .. web.search.total()
+ -- CALL notify-send
+ -- OR inject js into view to show ui
+ end,
+})
#+end_src
diff --git a/config.lua b/config.lua
index 68bd01b..79ab751 100644
--- a/config.lua
+++ b/config.lua
@@ -41,6 +41,16 @@ local function to_url(url)
return "https://" .. trim(url)
end
+web.keymap.set('n', '<esc>', function() web.search.set_text('') end)
+web.keymap.set('n', 'n', function() web.search.next() end)
+web.keymap.set('n', '<s-n>', function() web.search.previous() end)
+web.keymap.set('n', '<c-f>', function()
+ dmenu.input({ prompt = 'Search:' }, function(err, input)
+ if err or not input then return end
+ web.search.set_text(input)
+ end)
+end)
+
-- Open in new view
web.keymap.set('n', 'o', function()
print(web.get('new_view_url'), web.get('user_agent'))
diff --git a/lua/null-browser/api.lua b/lua/null-browser/api.lua
index ac7aa08..5e4beab 100644
--- a/lua/null-browser/api.lua
+++ b/lua/null-browser/api.lua
@@ -3,6 +3,7 @@ __internals = __internals
--- @type table
_G.web = _G.web or {
+ search = {},
keymap = {},
view = {},
history = {},
@@ -171,4 +172,21 @@ function web.history.back(count, view_id) return __internals.history_back(count,
--- ```
function web.history.forward(count, view_id) return __internals.history_forward(count, view_id) end
+--- Search
+---
+--- @param text string Text to search
+--- @param view_id? number Id of the view
+---
+--- @example
+--- ```lua
+--- web.search.set_text('whatever')
+--- ```
+function web.search.set_text(text, view_id) return __internals.search_set_text(text, view_id) end
+
+-- TODO: Documentation please
+function web.search.next(view_id) return __internals.search_next(view_id) end
+
+-- TODO: Documentation please
+function web.search.previous(view_id) return __internals.search_previous(view_id) end
+
print("api loaded")
diff --git a/src/AsyncEventLoop.cpp b/src/AsyncEventLoop.cpp
index f11babb..12e0351 100644
--- a/src/AsyncEventLoop.cpp
+++ b/src/AsyncEventLoop.cpp
@@ -74,7 +74,7 @@ AsyncEventLoop::~AsyncEventLoop() {
uv_run(loop, UV_RUN_DEFAULT);
if (uv_loop_alive(loop) > 0)
- qDebug() << "WARNING: Loop still has active handles!";
+ qWarning() << "WARNING: Loop still has active handles!";
free(loop);
loop = nullptr;
diff --git a/src/LuaRuntime.hpp b/src/LuaRuntime.hpp
index f684409..0855570 100644
--- a/src/LuaRuntime.hpp
+++ b/src/LuaRuntime.hpp
@@ -52,6 +52,9 @@ signals:
void webview_closed(WebViewId webview_id);
void webview_selected(WebViewId webview_id);
void config_updated(const QString &key, const QVariant &value);
+ void search_requested(const QString &text, WebViewId webview_id);
+ void search_next_requested(WebViewId webview_id);
+ void search_previous_requested(WebViewId webview_id);
protected:
LuaRuntime();
diff --git a/src/LuaRuntimeApi.hpp b/src/LuaRuntimeApi.hpp
index 809b579..b6302ff 100644
--- a/src/LuaRuntimeApi.hpp
+++ b/src/LuaRuntimeApi.hpp
@@ -5,7 +5,7 @@
#include "LuaRuntime.hpp"
#include "WindowActionRouter.hpp"
-int lua_api_open_url(lua_State *state) {
+int lua_api_view_set_url(lua_State *state) {
const char *url = lua_tostring(state, 1);
WebViewId view_id = lua_isnoneornil(state, 2) ? 0 : lua_tointeger(state, 2);
auto &runtime = LuaRuntime::instance();
@@ -187,6 +187,28 @@ int lua_event_register(lua_State *state) {
return 1;
}
+int lua_api_search_set_text(lua_State *state) {
+ const char *text = lua_tostring(state, 1);
+ WebViewId view_id = lua_isnoneornil(state, 1) ? 0 : lua_tointeger(state, 1);
+ auto &runtime = LuaRuntime::instance();
+ emit runtime.search_requested(text, view_id);
+ return 1;
+}
+
+int lua_api_search_next(lua_State *state) {
+ WebViewId view_id = lua_isnoneornil(state, 1) ? 0 : lua_tointeger(state, 1);
+ auto &runtime = LuaRuntime::instance();
+ emit runtime.search_next_requested(view_id);
+ return 1;
+}
+
+int lua_api_search_previous(lua_State *state) {
+ WebViewId view_id = lua_isnoneornil(state, 1) ? 0 : lua_tointeger(state, 1);
+ auto &runtime = LuaRuntime::instance();
+ emit runtime.search_previous_requested(view_id);
+ return 1;
+}
+
// NOLINTNEXTLINE
static luaL_Reg internals_api[] = {
luaL_Reg{"event_add_listener", &lua_event_register},
@@ -198,8 +220,11 @@ static luaL_Reg internals_api[] = {
luaL_Reg{"view_current", &lua_api_view_current},
luaL_Reg{"view_list", &lua_view_list},
luaL_Reg{"view_select", &lua_view_select},
- luaL_Reg{"view_set_url", &lua_api_open_url},
+ luaL_Reg{"view_set_url", &lua_api_view_set_url},
luaL_Reg{"history_back", &lua_history_back},
luaL_Reg{"history_forward", &lua_history_forward},
+ luaL_Reg{"search_set_text", &lua_api_search_set_text},
+ luaL_Reg{"search_previous", &lua_api_search_previous},
+ luaL_Reg{"search_next", &lua_api_search_next},
luaL_Reg{nullptr, nullptr},
};
diff --git a/src/WindowActionRouter.cpp b/src/WindowActionRouter.cpp
index d0b529b..5f787c0 100644
--- a/src/WindowActionRouter.cpp
+++ b/src/WindowActionRouter.cpp
@@ -58,6 +58,23 @@ void WindowActionRouter::initialize(Configuration *config) {
WITH_WEBVIEW_WINDOW(webview_id, window,
{ emit window->mediator()->webview_selected(webview_id); });
});
+ connect(&runtime, &LuaRuntime::search_requested, this,
+ [this](const QString &text, WebViewId webview_id) {
+ WITH_WEBVIEW_WINDOW(webview_id, window, {
+ this->current_search_text = text;
+ win_match.second->mediator()->set_search_text(text, webview_id, true);
+ })
+ });
+ connect(&runtime, &LuaRuntime::search_next_requested, this, [this](WebViewId webview_id) {
+ WITH_WEBVIEW_WINDOW(webview_id, window, {
+ win_match.second->mediator()->set_search_text(this->current_search_text, webview_id, true);
+ })
+ });
+ connect(&runtime, &LuaRuntime::search_previous_requested, this, [this](WebViewId webview_id) {
+ WITH_WEBVIEW_WINDOW(webview_id, window, {
+ win_match.second->mediator()->set_search_text(this->current_search_text, webview_id, false);
+ })
+ });
}
void WindowActionRouter::add_window(BrowserWindow *window) {
diff --git a/src/WindowActionRouter.hpp b/src/WindowActionRouter.hpp
index 17b935f..c1e6ecc 100644
--- a/src/WindowActionRouter.hpp
+++ b/src/WindowActionRouter.hpp
@@ -54,4 +54,5 @@ private:
Configuration *configuration;
EventQueue event_queue;
+ QString current_search_text;
};
diff --git a/src/WindowMediator.hpp b/src/WindowMediator.hpp
index b2ecb77..17190b3 100644
--- a/src/WindowMediator.hpp
+++ b/src/WindowMediator.hpp
@@ -16,6 +16,7 @@ public:
DELEGATE(webview_stack, has_webview, has_webview)
DELEGATE(webview_stack, current_webview_id, current_webview_id)
DELEGATE(webview_stack, get_webview_list, get_webview_list)
+ DELEGATE(webview_stack, set_search_text, set_search_text)
signals:
void history_back_requested(WebViewId webview_id, qsizetype history_index);
diff --git a/src/widgets/WebView.hpp b/src/widgets/WebView.hpp
index 3f73316..98dceba 100644
--- a/src/widgets/WebView.hpp
+++ b/src/widgets/WebView.hpp
@@ -3,6 +3,7 @@
#include <QWebEngineView>
#include <QtCore>
#include <cstdint>
+#include <qtypes.h>
#include "utils.hpp"
diff --git a/src/widgets/WebViewStack.cpp b/src/widgets/WebViewStack.cpp
index 258fbc6..16fd3e9 100644
--- a/src/widgets/WebViewStack.cpp
+++ b/src/widgets/WebViewStack.cpp
@@ -1,4 +1,5 @@
#include <QStackedLayout>
+#include <QWebEngineFindTextResult>
#include <QWebEngineHistory>
#include <QWebEngineNewWindowRequest>
#include <QWebEngineProfile>
@@ -198,6 +199,25 @@ void WebViewStack::focus_webview(WebViewId webview_id) {
layout->setCurrentIndex((int)webview_index);
}
+void WebViewStack::set_search_text(const QString &text, WebViewId webview_id, bool forward) {
+ auto *webview = get_webview(webview_id);
+ if (webview == nullptr) {
+ qDebug() << "Webview does not exist";
+ return;
+ }
+
+ QString search_text = text.trimmed();
+
+ auto flags =
+ search_text.isLower() ? QWebEnginePage::FindFlags() : QWebEnginePage::FindCaseSensitively;
+ if (!forward)
+ flags |= QWebEnginePage::FindBackward;
+
+ webview->page()->findText(search_text, flags, [](const QWebEngineFindTextResult &result) {
+ qDebug() << result.numberOfMatches() << result.activeMatch();
+ });
+}
+
WebView *WebViewStack::get_webview(WebViewId webview_id) {
auto webview_index = get_webview_index(webview_id);
if (webview_index < 0)
diff --git a/src/widgets/WebViewStack.hpp b/src/widgets/WebViewStack.hpp
index 05362d6..e41af43 100644
--- a/src/widgets/WebViewStack.hpp
+++ b/src/widgets/WebViewStack.hpp
@@ -65,6 +65,7 @@ public slots:
void webview_history_forward(WebViewId webview_id, qsizetype history_index);
void close(WebViewId webview_id);
void focus_webview(WebViewId webview_id);
+ void set_search_text(const QString &text, WebViewId webview_id, bool forward = true);
protected slots:
void on_new_webview_request(const QWebEngineNewWindowRequest &request);