Ueli: Support for plugins

Created on 21 Jan 2019  路  9Comments  路  Source: oliverschwendener/ueli

For both wox and alferd, plug-ins are a essential part of the app and improves usability by a great deal.

Please support developing plug-ins.

feature request

Most helpful comment

Ok I totally see the need for a plugin system now. People start to have needs for special usecases and this is where custom plugins come in. It would be really cool if there would be a easy way to develop plugins for ueli and install them. I just have no clue how to implement this. I just really want to avoid compatibility problems when adding updates/changes to the "core" of ueli.

I guess I have to look into this in the nearer future. Maybe this is something for v9.0.0. I'll reopen this issue.

Thanks for the input @NickSeagull

All 9 comments

Here is some documentation on how wox handles plugins:

http://doc.wox.one/en/plugin/create_plugin.html
http://doc.wox.one/en/plugin/plugin_json.html


Basically, in each plugin there is a plugin.json specifies all the basic metadata including version, name, etc. There are two things worth noting:

  1. UUID: I don't know whether this is necessary, many modern package managers no longer use UUID as id. For example, npm and choco.
  2. Executable file: This is the file specifying the executable, for example the python file or the compiled executable. In our case I think we can support typescript and javascript plugin first and then explore the possibility of supporting other type of plugins (python plugin or executable plugin).

wox gains all its functionality from plugins. I think this is a really robust and useful idea.

This idea gives user full control of the functionality they want (if they don't want certain functionality, they can just disable or uninstall that plugin), and makes the code much more modularized and extendable.

If we build the plugin system, then all the searcher and builder can be isolated and become plugins. also operating-system-settings and programs-plugin will be in their respective plugin folder. Results in a much cleaner src folder.

Some functionality to keep in mind while developing plugins:

  1. Plugins should be able to install external packages if they want. For example when developing a calendar plugin, a library to generate ics file will be really helpful. Therefore, we need to handle installing dependency when installing and updating a plugin.
  2. We cannot simply invoke a command to the main file, because in a plugin, there might be other helper files and dependency. We need to find an elegant way to load in the plugin and then invoke the query and contextMenu function.
  3. Relevance of results. When two plugin have the same activation keyword, we need to sort these results by relevance of these results. This is very hard.
  4. Language options. The ueli should send in a config input or a config global constant to the plugin to tell them about some user options, including languages. There is also privacy concerns, user should be able to control what will sent into the plugin.

Ueli looks like currently best launcher i have found. But it really needs simple way to create own plugins and features. Currently hain seems to be best option for me, but for some reason I like ueli more.

Maybe I can somehow help with plugins?

In my opinion implementing a plugin manager is too overkill for now and will complicate stuff too much. If someone wants to implement a new plugin/feature it can be integrated directly to the app by making a pull request. Closing this for now until I really see the need for plugin system or someone else wants to implement this.

Hey @oliverschwendener, +1 to this. My biggest uses of Alfred on Mac were:

  • Quick search of AWS dashboards
  • Quick search of GitHub repos
  • Manage Spotify within the launcher
  • Fast switch to a Slack channel
  • Switch between open windows

I think that these features should not be a main part of Ueli, because they are not something that everyone will want to use.

I drafted a possible implementation of a plugin manager, and it could be quite simple in practice. Instead of going with all the full pledged package repo, UI for the packages, etc... We can start with a configuration file where the user can specify github repos for the plugins in the format user/repo.

Ueli would then clone/download the repo and dynamically require the main module on load.

When that module is loaded, it would add itself to the list of built-in plugins. What do you think?

Ok I totally see the need for a plugin system now. People start to have needs for special usecases and this is where custom plugins come in. It would be really cool if there would be a easy way to develop plugins for ueli and install them. I just have no clue how to implement this. I just really want to avoid compatibility problems when adding updates/changes to the "core" of ueli.

I guess I have to look into this in the nearer future. Maybe this is something for v9.0.0. I'll reopen this issue.

Thanks for the input @NickSeagull

I think that the first step is already well setup, which is setting up an interface, and there is already one called ExecutionPlugin.

The next step would be how to indicate Ueli to load the plugin. The approach that Wox takes is to make all plugins have a class named Main, in order to know how to load them.

We could create an @*Plugin decorator that loads the class of the plugin perhaps?

I'm thinking that making each plugin a separate repo/project makes sense, so it looks like so:

plugin-repo
|- index.ts
|- package.json
|- ... more stuff

The contents of index.ts would be:

@ExecutionPlugin
export class CalculatorPlugin {    // no need for `extends` here, as the decorator can enforce it
  ...
}

in the package.json a main file is specified. so we can make Ueli aware of which file it would load.


Regarding distribution, I'd start with a .ueli.yaml file in $HOME and inside, some contents that look like:

plugins:
  - oliverschwendener/ueli-calculator-plugin@master

When Ueli starts, it would:

  1. Check that file for the plugins
  2. Download the zip from the tag in GitHub
  3. Extract it into the folder where Ueli stores its assets, perhaps to plugins/ueli-calculator-plugin
  4. Run npm run pack (or build, or compile, whatever command to generate the main file)
  5. Check the package.json inside of that folder for knowing where the main file is located
  6. require that main file
  7. The decorator then executes the needed code, where it pushes the class into the appropriate list at search-engine.ts

How does that sound?

What is the progress on this feature? Are there any updates since December 2019?

I have just started working on this at my fork. I will also provide a sample plugin repository that can be used for this purpose.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TobiasDev picture TobiasDev  路  4Comments

gabriel-peracio picture gabriel-peracio  路  3Comments

amrbashir picture amrbashir  路  5Comments

thatKaran picture thatKaran  路  5Comments

cosimochellini picture cosimochellini  路  5Comments