luakit / luakit

Fast, small, webkit based browser framework extensible by Lua.
https://luakit.github.io/
GNU General Public License v3.0
2.09k stars 251 forks source link

External client for controlling luakit from scripts #572

Open aidanholm opened 6 years ago

aidanholm commented 6 years ago

As a shell script and/or a lua module. Would communicate over DBus with the running instance of luakit, evaluate code in its lua state, and return the results.

Similar to awesomewm's awesome-client:

Issues:

c0dev0id commented 5 years ago

What about sticking to IPC sockets and use something like i3-msg? https://github.com/i3/i3/blob/next/i3-msg/main.c

hippi777 commented 5 years ago

hi :)

maybe the debug api of webkit that is used by the brackets editor can be a thing for whatevere u wanna achieve, but i think that is restricted and already around some of the tickets iirc.

otoh i dunno enough about dbus nor shared memory but i think maybe the latter is more lightweight and most likely easy to use, however i cant give more than these pointers to consider, so thats all from me now :D

bests! :)

pataquets commented 2 years ago

Wanting to automate/remote control the browser from an external program.

taobert commented 2 years ago

What is it you're wanting to automate @pataquets? While it's not as sophisticated as the schemes proposed above, it's fairly easy to pass information into luakit using the command line and the unique functionality. Bidirectional communication will take some thought and some work, which i suspect is why this ticket's been open for 5 years.

If you don't need to get information back, then extending unique_instance.lua:

diff --git a/lib/unique_instance.lua b/lib/unique_instance.lua
index b64a8ae6..5c8e4f73 100644
--- a/lib/unique_instance.lua
+++ b/lib/unique_instance.lua
@@ -66,7 +66,12 @@ unique.add_signal("message", function (message, screen)

         if not _M.open_links_in_new_window then
             for _, uri in ipairs(u) do
-                w:new_tab(uri)
+                cmd  = uri:match("command://(.*)")
+                if (cmd) then
+                    w:new_tab() w:run_cmd(":" .. cmd)
+                else
+                    w:new_tab(uri)
+                end
             end
         end
     elseif cmd == "tabopen" then

allows any user defined command to be triggered from the shell. For example, I have:

modes.add_cmds({
    { ":restart",   "restart browser, reloading config.",
                    function (w)  
                        w:close_tab();
                        w:restart();
                    end },
})

and can call it in the existing luakit instance by running luakit command://restart.

Edit: #295 is similar enough to this that it's worth linking to.

pataquets commented 2 years ago

Thanks for the prompt response, @taobert! I'm trying to send a handful of commands mainly for web browsing (:open and :tabopen) and also for session control (restore/save). I guess I need no reading back any infos (maybe error/success responses?), but this might change in the future. I've looked for communication mechanisms in the docs and found nothing. However, by looking at the code, I'm guessing that some sort of IPC/socket/dbus mechanism is available, albeit not documented. I'm trying to talk to the socket file created in the /tmp dir without any success, so far. My socat attempts have failed, but I'm still figuring out the kind of socket I must talk to when calling socat. Any help here would be much appreciated (and documented, if pointed where to).

taobert commented 2 years ago

Well, i don't have much more information than i gave above.

I think the ipc functionality is there to communicate between processes (luakit, WebKitWebProcess, WebKitNetworkProcess) within luakit rather than to accept input from external processes, so it's probably more accurate to say "some sort of IPC/socket/dbus mechanism is used" rather than "available". You might be able to hack into that, but you'd need to do the reading to figure out the protocols yourself. I'm not at all convinced that hacking into the existing ipc infrastructure would be productive, but it could perhaps be extended to allow for extrinsic messaging, and if a separate system needs to be implemented, it may be optimal (from an ease-of-learning perspective) if it was constructed as analogously to the intra-application signalling as possible. So understanding how things currently work is probably a good thing regardless. I can see from ipc_send in common/ipc.c that the g_async_... suite is being used, but i've never worked with it. Further, the message being sent appears to be a (pointer to a?) struct rather than a string, which would probably complicate the task.

WRT your stated aims, by default you can open a url in a new tab(/window) from the command line. I see that my script for mutt to load html bits sets $DBUS_SESSION_BUS_ADDRESS before doing this, so i assume DBUS is required, but i don't recall specifics(, or indeed whether i ever knew specifics). The patch i offered above would allow you to call arbitrary (save/restore/etc) command bindings, albeit with no feedback about the operation's success.

You're correct that the api docs are rather lacking in this area (and others). If you do put some time into reading and understanding how this works, even if you get distracted and never get a full understanding, recording that information would help the next person and improve the project, and i'm sure pull requests would be accepted.

pataquets commented 2 years ago

Well, i don't have much more information than i gave above.

I think the ipc functionality is there to communicate between processes (luakit, WebKitWebProcess, WebKitNetworkProcess) within luakit rather than to accept input from external processes, so it's probably more accurate to say "some sort of IPC/socket/dbus mechanism is used" rather than "available". You might be able to hack into that, but you'd need to do the reading to figure out the protocols yourself. I'm not at all convinced that hacking into the existing ipc infrastructure would be productive, but it could perhaps be extended to allow for extrinsic messaging, and if a separate system needs to be implemented, it may be optimal (from an ease-of-learning perspective) if it was constructed as analogously to the intra-application signalling as possible. So understanding how things currently work is probably a good thing regardless. I can see from ipc_send in common/ipc.c that the g_async_... suite is being used, but i've never worked with it. Further, the message being sent appears to be a (pointer to a?) struct rather than a string, which would probably complicate the task.

So, that rules out an easy, plain text control mechanism, so I'm out of luck. Although I [sort of] understand what you mean here, it's way too involved for my plans.

WRT your stated aims, by default you can open a url in a new tab(/window) from the command line. I see that my script for mutt to load html bits sets $DBUS_SESSION_BUS_ADDRESS before doing this, so i assume DBUS is required, but i don't recall specifics(, or indeed whether i ever knew specifics). The patch i offered above would allow you to call arbitrary (save/restore/etc) command bindings, albeit with no feedback about the operation's success.

From what you say, maybe DBus is available at might work. I've browsed your Github profile for repos and gists with the script you mention and found nothing. Would you care to share the script? It might come handy. In fact, I tried a little with DBus, but since I don't have any topic/message/etc details to send, it felt too much for me.

You're correct that the api docs are rather lacking in this area (and others). If you do put some time into reading and understanding how this works, even if you get distracted and never get a full understanding, recording that information would help the next person and improve the project, and i'm sure pull requests would be accepted.

Sure, at least just a link to this issue will be useful for sure to others who might follow. Any advice where would be a good place?

Thanks a lot again for such a detailed response, @taobert.

taobert commented 2 years ago

Erm...

From what you say, maybe DBus is available at might work. I've browsed your Github profile for repos and gists with the script you mention and found nothing. Would you care to share the script? It might come handy. In fact, I tried a little with DBus, but since I don't have any topic/message/etc details to send, it felt too much for me.

I've attached the script i mentioned for completeness, but it a) is fugly, and b) doesn't do anything useful/interesting. (Which is why it's tucked away in a private gitlab repo.) It doesn't use DBUS, just luakit's "open this url in the already running instance" command line functionality. I mentioned that it sets the DBUS environment variable only because that hinted that DBUS was involved in some way, and that you may find yourself in that area if you went down the rabbit warren of figuring the ipc out, not because i thought that what i had done would be directly helpful to you.

Sure, at least just a link to this issue will be useful for sure to others who might follow. Any advice where would be a good place?

Well, i'd imagined that if you were spending time to read and understand the various functions, you'd perhaps take the opportunity to add some commentary to the code, but if that's not something you're up for, that's fair enough.