Re: [Geany-Devel] My non-C plugin roadmap

2015-03-28 Thread Lex Trotman
Thomas,

Thanks for that, it now makes it clearer where you are going, and
allows the individual steps to make more sense.

I agree with your four problems (shortened):

- linkage
- keybindings
- plugin context
- allow for proxies

My concern is that the solutions seem complex, though, having followed
your attempts over time to address these issues, I do understand that
some of the "simple" options don't actually cut it.

Will need to think on it further.

Cheers
Lex

On 29 March 2015 at 10:23, Thomas Martitz  wrote:
> Hello,
>
> I was asked to share a bit about my roadmap regarding plugins. I'll try to
> give you a better idea with this post.
>
> My ultimate goal is to implement a clean and maintainable way to support
> non-C plugins, preferably using existing widely used techniques. I concluded
> that libpeas[1] in conjunction with gobject-introspection can provide the
> base for this. Since Geany is not at all prepared for this I have several
> infrastructure which I do want to get merged into Geany. When Geany core is
> sufficiently setup for this, the non-C plugin enablement can happen outside
> the core, as a plugin, to stabilize there.
>
> So, here's the set of infrastructure changes for the core. Please let me
> stress that all of this will happen in backward-compatible manner, no
> existing plugins break as part of this.
>
> - linkage-cleanup (PR#429) - This changes the way plugins access Geany API
> functions. Instead of exporting a pointer to a struct of structs of API
> function pointers, now the APIs are exported directly. This work also
> includes an effort to stop exporting all function (we do this currently as a
> workaround to allow gtkbuilder to work), so *only* API function are exported
> and plugins cannot call internal function anymore. This change is also
> required to allow gobject-introspection to find geany functions at runtime
> (through g_module_symbol()) in the future.
> - new API functions for registering keybindings (PR#376). The current API
> functions do not allow context information to be stored and passed to the
> key handler function. This makes it very hard for non-C plugins to use these
> function. So what's  needed are key handlers that get the necessary context
> information. This allows interprepted language plugins to register
> keybindings.
> - A new plugin loader mechanism (a thread about this is already running on
> the devel list): Similarly to the keybindings, the plugin_* functions
> implemented by plugins do not carry any context information, making it hard
> for non-C plugins to implement them properly. Therefore a new loader
> mechaism is needed so that the context information can be passed. The loader
> works such that an API function is called to register a function pointer
> table. This is crucial to possibly support plugins that register other
> plugins (so called pluxies) which is simply not possible with the current
> mechaism. The current loader is kept for backwards compatibility (but will
> not receive new features).
> - New API functions to allow plugins to act as proxy plugins (pluxies).
> These pluxies can then implement whatever is needed to execute code in the
> in the actual plugin, like invoking an interpreter or firing up a java vm.
> The pluxies call the new loader's API function on behalf of the actual
> plugin. The API function to implement the pluxies is a simple
> geany_register_pluxy() that, much like the normal plugin loader, that
> pluxies use to pass a function pointer table which implements the necessary
> hooks (probe(), load() and unload())
>
> Once this is in place in the core, my roadmap contains the following items,
> which are implemented (at least initially) in a plugin, so no further
> changes to the cure should be necessary.
> - Modify geanypy to use the new pluxy APIs. This will finally enable geanypy
> to show the python plugins in the normal PM dialog and support keybindings
> - Create a new pluxy that supports libpeas-based plugins (codename: peasy).
> Peasy will use libpeas to load plugins and their metadata.
> - Part of the peasy work is also work on creating vala and
> gobject-introspection bindings for Geany's API functions, so that we can
> support python, javascript and lua out of the box.
>
> This is my roadmap so far. It changed quite a bit since I started this
> non-C-plugins effort a year ago, but I hope it will be good for everyone.
> Please share your opinions on this or ask questions.
>
> Best regards.
> ___
> Devel mailing list
> Devel@lists.geany.org
> https://lists.geany.org/cgi-bin/mailman/listinfo/devel
___
Devel mailing list
Devel@lists.geany.org
https://lists.geany.org/cgi-bin/mailman/listinfo/devel


[Geany-Devel] My non-C plugin roadmap

2015-03-28 Thread Thomas Martitz

Hello,

I was asked to share a bit about my roadmap regarding plugins. I'll try 
to give you a better idea with this post.


My ultimate goal is to implement a clean and maintainable way to support 
non-C plugins, preferably using existing widely used techniques. I 
concluded that libpeas[1] in conjunction with gobject-introspection can 
provide the base for this. Since Geany is not at all prepared for this I 
have several infrastructure which I do want to get merged into Geany. 
When Geany core is sufficiently setup for this, the non-C plugin 
enablement can happen outside the core, as a plugin, to stabilize there.


So, here's the set of infrastructure changes for the core. Please let me 
stress that all of this will happen in backward-compatible manner, no 
existing plugins break as part of this.


- linkage-cleanup (PR#429) - This changes the way plugins access Geany 
API functions. Instead of exporting a pointer to a struct of structs of 
API function pointers, now the APIs are exported directly. This work 
also includes an effort to stop exporting all function (we do this 
currently as a workaround to allow gtkbuilder to work), so *only* API 
function are exported and plugins cannot call internal function anymore. 
This change is also required to allow gobject-introspection to find 
geany functions at runtime (through g_module_symbol()) in the future.
- new API functions for registering keybindings (PR#376). The current 
API functions do not allow context information to be stored and passed 
to the key handler function. This makes it very hard for non-C plugins 
to use these function. So what's  needed are key handlers that get the 
necessary context information. This allows interprepted language plugins 
to register keybindings.
- A new plugin loader mechanism (a thread about this is already running 
on the devel list): Similarly to the keybindings, the plugin_* functions 
implemented by plugins do not carry any context information, making it 
hard for non-C plugins to implement them properly. Therefore a new 
loader mechaism is needed so that the context information can be passed. 
The loader works such that an API function is called to register a 
function pointer table. This is crucial to possibly support plugins that 
register other plugins (so called pluxies) which is simply not possible 
with the current mechaism. The current loader is kept for backwards 
compatibility (but will not receive new features).
- New API functions to allow plugins to act as proxy plugins (pluxies). 
These pluxies can then implement whatever is needed to execute code in 
the in the actual plugin, like invoking an interpreter or firing up a 
java vm. The pluxies call the new loader's API function on behalf of the 
actual plugin. The API function to implement the pluxies is a simple 
geany_register_pluxy() that, much like the normal plugin loader, that 
pluxies use to pass a function pointer table which implements the 
necessary hooks (probe(), load() and unload())


Once this is in place in the core, my roadmap contains the following 
items, which are implemented (at least initially) in a plugin, so no 
further changes to the cure should be necessary.
- Modify geanypy to use the new pluxy APIs. This will finally enable 
geanypy to show the python plugins in the normal PM dialog and support 
keybindings
- Create a new pluxy that supports libpeas-based plugins (codename: 
peasy). Peasy will use libpeas to load plugins and their metadata.
- Part of the peasy work is also work on creating vala and 
gobject-introspection bindings for Geany's API functions, so that we can 
support python, javascript and lua out of the box.


This is my roadmap so far. It changed quite a bit since I started this 
non-C-plugins effort a year ago, but I hope it will be good for 
everyone. Please share your opinions on this or ask questions.


Best regards.
___
Devel mailing list
Devel@lists.geany.org
https://lists.geany.org/cgi-bin/mailman/listinfo/devel


Re: [Geany-Devel] New plugin loader mechanisms

2015-03-28 Thread Thomas Martitz

Hello,

based on the discussion I refined my proposal (see below). Additionally 
I have implemented all of this, including updating demoplugin.c, see 
[1]. And last but not least, I have a fully working implementation of 
proxy plugins aka pluxies (in fact, I simply updated my year-old branch 
to use the new hooks) plus a real-world pluxy for libpeas-based plugins, 
see [2], [3].


I also formally suggest this work for merging. I havent done a pull 
request yet, though, because it depends on the linkage-cleanup work, 
which should be merged first. I do target the 1.25 release still, and 
I'd absolutely love to if we can make this happen.



The changes since my initial proposal summed up:
- geany_plugin_register() now additionally takes the API version the 
plugin is compiled against (in addition to the minimum API it needs and 
the ABI version). This gives Geany full insight of what the plugin can 
be expected to work with.
- set_info() is removed from the hooks. version_check() is obviously 
obsolete (the checks are performed within geany_plugin_register()). The 
plugin is expected to full plugin->info before calling 
geany_plugin_register() which makes set_info() superfluous
- The conceptual role of geany_load_module() is extended: It should also 
check for plugin-specific runtime dependencies, and return FALSE if such 
checks fail (as a result the plugin will be hidden from the PM dialog). 
Otherwise call geany_plugin_register() appropriately.
- geany_load_module() passes Geany's API version, sos that plugins can 
perform their own specific checks based on the API of the currently 
running Geany instance (this can very well be != the plugins 
GEANY_API_VERSION)
- The GeanyData pointer is now part of GeanyPlugin structure for plugins 
to access (not passed to init anymore). Actually it was this way in my 
first version too, but I didn't explicitly mention it.

- PluginHooks is renamed to GeanyPluginHooks

Now to the (updated) proposal:

Please see my initial mail [4] about the motivation and advantages of 
this work.


gboolean geany_load_module(GeanyPlugin *plugin, GModule *module, gint 
geany_api_version);
gboolean geany_plugin_register(GeanyPlugin *plugin, gint api_version, 
gint min_api_version,
   gint abi_version, GeanyPluginHooks 
*hooks, gpointer pdata);


typedef struct _GeanyPluginHooks
{
/** Array of plugin-provided signal handlers (@see PluginCallback) */
PluginCallback *callbacks;
/** Called when the plugin is enabled by the user */
void(*init)  (GeanyPlugin *plugin, gpointer pdata);
/** plugins configure dialog, optional (can be @c NULL) */
GtkWidget*  (*configure) (GeanyPlugin *plugin, GtkDialog *dialog, 
gpointer pdata);
/** Called when the plugin should show some help, optional (can be 
@c NULL) */

void(*help)  (GeanyPlugin *plugin, gpointer pdata);
/** Called when the plugin is disabled or when Geany exits */
void(*cleanup)   (GeanyPlugin *plugin, gpointer pdata);
}
GeanyPluginHooks;


Plugins from now on define a single global function, 
geany_load_module(), which is called by Geany via pointer obtained from 
g_module_symbol(). In this function the plugin should perform the 
following steps:


- Test against the passed geany_api_version if it can function under the 
current Geany.

- Test for any additional runtime dependencies
- Call geany_plugin_register() appropate and test the return value

If any of the above steps fail FALSE should be returned, else TRUE.

The plugin shall pass a statically allocated instance of 
GeanyPluginHooks as part of the geany_plugin_register() call. The 
function pointers should point to function that are semantically the 
same as the current plugin_{init,configure,help,cleanup}. Except these 
function get other parameters and can make use of them.


This proposal does not implement pluxies by itself, however I have done 
the work to implement pluxies on top of the new loader. I will post 
another mail about this when we finalized the new loader.


[1] https://github.com/kugel-/geany/tree/new_hooks
[2] https://github.com/kugel-/geany/tree/pluxy
[3] https://github.com/kugel-/peasy
[4] http://lists.geany.org/pipermail/devel/2015-March/009299.html

Please reply with your options or other ideas.

Best regards
___
Devel mailing list
Devel@lists.geany.org
https://lists.geany.org/cgi-bin/mailman/listinfo/devel