Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for python or javascript plugins? #13

Closed
monotasker opened this issue Jan 30, 2015 · 18 comments
Closed

Support for python or javascript plugins? #13

monotasker opened this issue Jan 30, 2015 · 18 comments
Labels
Help wanted Much appreciated!

Comments

@monotasker
Copy link

I'd really like to be able to write new action modules myself and share them back to the community. I think this kind of plugin ecosystem is really important for an app like this to thrive in the long run. But there are a lot more of us who can use a language like python (my mainstay) or even javascript. If plugins can only be written (or new functionality added) in C++ I think that's going to reduce the pool of contributers a lot. So what do you think? Would a python plugin api be feasible in future?

@ManuelSchneid3r
Copy link
Member

I looked around for an easy to implement solution, but it seams to be tricky to embed python. Do you have any suggestions? For now I decided to push this option to the end of the TODO queue, but the idea of a plugin system is fine. I will try to make the application capable of using compiled c++ plugins.

@mxdevmanuel
Copy link

I've been lookin forward to work on this, I really love Albert and would love to contribute to its development, I have some experience in embeding python into C++ apps, I was waiting till the backend was rewrited so I could peek into the code and make a pull request or something, but maybe, if it's a really desired feature, it could be a good begining to define what kind of things would you like a plugin system allow you to do, for example I would like to search inside zeal docs( https://github.com/zealdocs/zeal, a very interesting project) from within albert, so "custom search engines" or something like that idk but I would love to help make this feature reality.

@monotasker
Copy link
Author

At minimum I think a plugin system should allow plugin writers to

  • expose new data sources (e.g., specific search engines [online or local] or specific regions of the file system)
  • define arbitrary new actions to perform on a search result item (launch with a particular program, open in a browser, export to a new text file, send by email, etc.)

I have been impressed by the power of the plugin system for Kupfer. Its API documentation is here: http://engla.github.io/kupfer/Documentation/PluginAPI.html Obviously the abstractions involved depend on the logical structure of the language (and particularly the two-stage or three-stage actions Kupfer makes possible) but I like the way it abstracts generic classes for Item, Source, Action and allows fairly free creation of each. At the same time, the Kupfer API also exposes generic Actions like opening a URL in the default browser or opening a file with its default application. That way, if all you want to do is define a new Source you don't have to re-create the logic for handling the Items it provides.

@ManuelSchneid3r
Copy link
Member

This is something that bugs me since months. I really would like to get python running but there are some caveats: The extensions have to be capable of Qt since they return QIcons (less of a problem) and their settings widget (huge problem). Which means that there has to be PySide/PyQt/PythonQt or similiar. From what I read integrating Python/Qt into C++/Qt is not straightforward, since Python/Qt is essentially a wrapper around the C++ stuff. This means integrating Python/Qt into C++/Qt, would be like wrapping C++ in Python and then again C++. I had problems finding something near a solution. Particularly since I never did any embedding before. When you have ideas let me know.

@ManuelSchneid3r ManuelSchneid3r added the Help wanted Much appreciated! label Oct 6, 2015
@nightscape
Copy link

+1 on this. Wouldn't it be possible to go the way Alfred on Mac does it? Plugins are just arbitrary executables and the convention is that they are called with the query text the user entered and literally print all completion proposals for the given query to STDOUT in an XML format.
Personally, I'd rather use JSON instead of XML, but apart from that this idea is quite clever as you can write extensions in any language you want with very little effort. I wrote several Alfred extensions myself and it was a breeze!

@nightscape
Copy link

Reconsidering: Supporting the XML definition of completion proposals from Alfred would probably allow one to reuse many of the existing Alfred workflows. E.g. My ssh completion workflow should be platform independent and would immediately fix #89 :D

@ManuelSchneid3r
Copy link
Member

This approach would be pretty flexible but it would be inefficient and would not support offline indexing. This is a nice idea, but I will try embedded plugins first.

@emielmolenaar
Copy link

+1 on this. I've been looking through the code and issue list to see if I can contribute to this project (Albert is awesome!), but my C++ skills suck :-)

@ManuelSchneid3r
Copy link
Member

From 0.9 the frontend is written in QML and the view uses paths instead of QIcons for the icons. This solves the problem described above and opens the door for plugins that require gluecode (Python, JS, executables... just everything not native). Further QML uses JS for the UI logic. This is the reason why 0.9 takes so much time (because I suck at JS 😄). I will push the devel branch in the next days. Regards

@nightscape
Copy link

Hi @ManuelSchneid3r,

I've been working on a similar project called rrun and implemented the proposal I made above. It's all working out quite nicely, just check how easy it is to define custom commands:
https://github.com/buster/rrun/wiki/Config-Snippets
I solved the caching problem by just storing the completion text in a .cache text file in the same format as required for the completions and cat mycachedcommands.cache | grep {} them to filter down to completions that match the query ({} gets replaced by the matched group from the regex).
I have to admit it's not too beginner friendly because you have to know at least some command line stuff and at least one scripting language with which to write your extensions, but for a programmer it's easy as pie to add new completions and runners.
Maybe this would be an approach for Albert as well? One could even share custom completions between rrun and Albert 😄

@ManuelSchneid3r
Copy link
Member

I dont know what you mean by the caching problem. But since the goal is to be completely independant (pure Qt/C++, no system libs), using bash in the core app is not possible. Any dependencies have to be shifted to the plugins.
The idea of the executables is nice, but I want to design some abstraction about the plugin system so integrating other pluginloaders is easy. This will take some time and is subject to 0.10. When the plugin loader abstraction is implemeted, an other smart idea is not to write plugin loaders, but plugin adapters that make e.g "krunner", "kupfer" and even "rrun" plugins available to albert. This would save a serious amount of man months in the development of a fullfledged launcher.

@marklap
Copy link

marklap commented Mar 9, 2016

Does the plugin solution have to be "fully integrated" with the GUI? My thought is that the WebSearch plugin could simply be made to be more generic to give your fans what they're looking for in the near term.

Leave the implementation of the plugin up to the plugin writer. That enables plugin writers that create plugins right now with minimal effort - both plugins that are written in high level languages (Python, Lua, etc) and executable binaries. Obviously this solution wouldn't natively enable plugin writers to contribute to Albert data sets however, how much demand is there for that? This would be a glorified 'Windows Run' plugin. But, I'm guessing that's probably ok for now.

If there is a significant demand to update Albert data sets, perhaps there's an opportunity for an offline data ingest command (something like: albert-indexer my.plugin.namespace my=list of=key value=pairs to=be indexed=thanks). And then you expect end-users and plugin devs to rely on cron-type solutions to keep the data updated (something like: 0 * * * * python my_cool_plugin_indexer.py | albert-indexer --truncate my.plugin.namespace).

The point being, it seems there's a solution that is smaller effort than your robust (and very cool btw) plugin ideas that puts most of the burden on plugin developers and end-users to ensure it's working properly and efficient. And... that's ok (I think). My guess is they'll take that in lieu of nothing right now and then will anxiously await the better solution you envision for a future release.

Just my $0.02

@coxley
Copy link

coxley commented Sep 15, 2016

I would use and recommend Albert in a heartbeat if I could write plugins in Python

@ManuelSchneid3r
Copy link
Member

ManuelSchneid3r commented Sep 29, 2016

Interesting (but not breaking) news. v0.8.11 contains the experimental feature of external extensions. I decided to not make it public since it most likely will change in the next releases, but actually it is working. So you can make a directory in ~/.local/share/albert/external and put random binaries in there. They have to follow the specific protocol defined in the header of externalextensions.h.

As an example rename goldendict.txt to e.g goldendict.sh, make it executable and put it into the directory mentioned above.

Have fun with it but do not use it ecessively overuse it. Although this allows to use whatever language you want to, these scripts are dead meaning the executables are called and terminated. This means that they have no chance to store a state unless saved to disk, which is too expensive. This is why I decided to first use the QJSEngine to make albert scriptable.

@coxley
Copy link

coxley commented Sep 30, 2016

@ManuelSchneid3r Will try to play with this some! In the meantime I may just "cache" by saving state to tmpfs. :P

@idkCpp
Copy link
Contributor

idkCpp commented Oct 6, 2016

@coxley Try this. Maybe it helps you. Up until now it crashes now and then... Still working on this one.

@coxley
Copy link

coxley commented Oct 6, 2016

@idkCpp Ooo. I will indeed!

@ManuelSchneid3r
Copy link
Member

ManuelSchneid3r commented Jan 22, 2017

Hey folks 0.9 finally made the external extensions stable and gives you possibility to save state over the core application. tmpfs is still an option though. There will be a real scripting interface in the future but currently I am not sure which I should choose. (Perl, Python, Ruby, Lua...). Ill have to investigate the experience with scripting in the nets...

However, although it feels clumsy albert is now scriptable by all languages that can form an executable, therefore 0.9 closes this issue.

I will make a folder in the repo where you can put your cool script and send a PR. I will also note this here and in the docu when the time comes.

Happy scripting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help wanted Much appreciated!
Development

No branches or pull requests

8 participants