# Scripting guide: writing modules in scripting languages

## Introduction

In this document we will learn how to write plugins for LeechCraft in different scripting languages, how to make plugins for other plugins (for example, for the Poshuku web browser) and learn to package this plugins for them to be put in the public plugins repo.

The following languages will be considered:

- Qt Script (basically, JavaScript or ECMA-262 with minor modifications);
- Python.

Please note that only Qt Script scripting backend comes by default on most platforms and has less dependencies then all others, so scripting in Qt Script is encouraged.

## Basic information

### Directory layout

Scripting plugins are located at a directory corresponding to the plugin language in `~/.leechcraft/plugins/scriptable/`. The following list summarizes the mapping from language to subdirectory name:

- Qt Script (JavaScript, ECMA-262) → `qtscript`;

- Python → `python`.

Thus, Python plugins, for example, would be in `~/.leechcraft/plugins/scriptable/python/`.

Each separate plugin is located in its own directory. Any directory name is possible allowed, but only those names consisting only of latin letters, numbers, dashes and underscores are encouraged. Then, for the given `directoryname` a file named `directoryname.py` with the extension corresponding to the language is searched and loaded as main plugin file by LeechCraft. If there is no such file, that directory would be skipped. So, for example, if a plugin is named URL Complete and it is written in Python, then one may name the directory as `urlcomplete`, and write the code in `~/.leechcraft/plugins/scriptable/python/urlcomplete/urlcomplete.py`. The following summarizes the mapping from language to possible extensions:

- Qt Script → `.es` (encouraged, `.qs`, `.js` are also possible though not recommended);
- Python → `.py`.

Except this (and a couple of other special files), you may lay out files in the directory of your plugin as you wish. You may have other files with code, load them from your main plugin file, and, of course.

### Prerequesites

For all scripting languages, you will need LeechCraft with Qross plugin, which depends upon Qrosp, found at . Some languages may have additional dependencies.

#### Qt Script

For writing modules in Qt Script, you will need the following:

- qrossqts module for Qrosp, which usually comes with main Qrosp libraries.

#### Python

For writing modules in Python, you will need the following:

- qrosspython module for Qrosp;
- Python 2.x (Python 3.x is not supported yet).

### Simplest plugin

The only functions that any plugin must have are `GetName` and `GetUniqueID` from the IInfo interface. First one should return a human-readable name of the plugin (like URL Complete for the plugin mentioned earlier), and the second should return an unique ID among all plugins. URI-like notation is strongly recommended for the ID string, for example org.SomeCompany.URLComplete for that plugin. Only upper- and lowercase latin letters, numbers, dots, plus and minus signs are allowed in the ID string.

.

Of course, you may implement other functions defined in IInfo, but scripting support in LeechCraft would provide reasonable defaults if you don't.

#### Qt Script pecularity

Because Qt Scripts cannot request what parts of Qt they want like Python ones can via `import` directive, Qt Script plugins should implement `Requires` function that returns list of strings with the required modules. For example:

#### Requiring some Qt parts from Qt Script.

    function Requires()
    {
        return ["qt", "qt.core", "qt.network", "qt.gui"];
    }

After you've saved the code in the corresponding plugin file, you can start up LeechCraft and see your plugin in the settings in Plugins tab.

### Implementing interfaces

Almost all plugins will need to implement more interfaces than just IInfo. In order to designate that your plugin supports other interfaces, you should implement the `SupportedInterfaces` function, which should return the list of interfaces supported by your plugin. Both short name (the name of the interface class) and fully-qualified one are requred. If the interface is one of predefined in LeechCraft, you can find the fully-qualified name in the bottom of interface file in `/src/interfaces/`.

#### Example `SupportedInterfaces` of a Qt Script plugin

    def SupportedInterfaces():
        return ["IPlugin2", "org.Deviant.LeechCraft.IPlugin2/1.0"]

#### Example `SupportedInterfaces` of a Python plugin

    function SupportedInterfaces()
    {
        return ["IPlugin2", "org.Deviant.LeechCraft.IPlugin2/1.0"];
    }

### Signals & slots

Due to restrictions in Python scripting backend, you should explicitly mark which signals and slots your plugin instance object has. This is done via the `ExportedSignals` and `ExportedSlots` files which should be (capitalization is important) in the directory of your plugin. In those files, you write a C++ signatures of signals and slots respectively, one per line, just like you would write it in `SIGNAL` or `SLOT` macro.

#### Example `ExportedSlots`

Example `ExportedSlots` of a plugin with only one exported slot.

    hookURLCompletionNewStringRequested (LeechCraft::IHookProxy_ptr, QObject*, const QString&, int)

Then, for each slot you just define the function with the same name and the same number of arguments as the slot, and it gets called whenever needed.

To emit signals you exported from your plugin with the `ExportedSignals` file, you need to call the corresponding function (the one with the name of the signal you want to emit and corresponding parameters) on `Signals` object. To use the `Signals` object in Python, you need to `import` it explicitly.

Of course, you don't have to (and in fact, should not) export signals and slots that should not be exposed to the outside world, like the ones you use in your plugin internally.

### Standalone plugins

Standalone plugins are pretty self-sufficient: they are not for other plugins, like Poshuku CleanWeb is for the Poshuku browser.

Topics like creating tabs in the main LeechCraft window, embedding into toolbars and handling download entities are covered in the corresponding documentation for C++ plugins.

## Advanced topics

### Translations

### Packaging