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
Proxy plugins #629
Merged
Merged
Proxy plugins #629
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
d008675
plugins: introduce load and unload functions for plugins
kugel- bdaab9c
plugins: generic load_data instead of module pointer in Plugin struct
kugel- 203644a
plugins: refactor GtkListStore population code into separate function
kugel- e5bb657
plugins: when loading active ones, loop until no more proxy plugins a…
kugel- 3ccf959
plugins: introduce probe() for proxy plugins
kugel- 6e5ca69
plugins: add geany_plugin_register_proxy() to the plugin API
kugel- 8ac9d56
plugins: reselect when toggling the current plugin
kugel- bbf8e88
demoproxy: add a demo proxy showcasing how to create a proxy plugin
kugel- 7ac89de
plugins: improve PM dialog for proxy and sub-plugins
kugel- 6dfe5ce
plugins: use GQueue to restore GLib compatibility
kugel- 6cb443e
plugins: enforce geany_plugin_register_proxy() can be called once
kugel- d0f9446
Bump plugin API version for proxy plugins support
b4n File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
/* | ||
* demoproxy.c - this file is part of Geany, a fast and lightweight IDE | ||
* | ||
* Copyright 2015 Thomas Martitz <kugel(at)rockbox(dot)org> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation; either version 2 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License along | ||
* with this program; if not, write to the Free Software Foundation, Inc., | ||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
*/ | ||
|
||
/** | ||
* Demo proxy - example of a basic proxy plugin for Geany. Sub-plugins add menu items to the | ||
* Tools menu and have a help dialog. | ||
* | ||
* Note: This is compiled but not installed by default. On Unix, you can install it by compiling | ||
* Geany and then copying (or symlinking) to the plugins/demoproxy.so and | ||
* plugins/demoproxytest.px files to ~/.config/geany/plugins | ||
* - it will be loaded at next startup. | ||
*/ | ||
|
||
/* plugin API, always comes first */ | ||
#include "geanyplugin.h" | ||
|
||
typedef struct { | ||
GKeyFile *file; | ||
gchar *help_text; | ||
GSList *menu_items; | ||
} | ||
PluginContext; | ||
|
||
|
||
static gboolean proxy_init(GeanyPlugin *plugin, gpointer pdata) | ||
{ | ||
PluginContext *data; | ||
gint i = 0; | ||
gchar *text; | ||
|
||
data = (PluginContext *) pdata; | ||
|
||
/* Normally, you would instruct the VM/interpreter to call into the actual plugin. The | ||
* plugin would be identified by pdata. Because there is no interpreter for | ||
* .ini files we do it inline, as this is just a demo */ | ||
data->help_text = g_key_file_get_locale_string(data->file, "Help", "text", NULL, NULL); | ||
while (TRUE) | ||
{ | ||
GtkWidget *item; | ||
gchar *key = g_strdup_printf("item%d", i++); | ||
text = g_key_file_get_locale_string(data->file, "Init", key, NULL, NULL); | ||
g_free(key); | ||
|
||
if (!text) | ||
break; | ||
|
||
item = gtk_menu_item_new_with_label(text); | ||
gtk_widget_show(item); | ||
gtk_container_add(GTK_CONTAINER(plugin->geany_data->main_widgets->tools_menu), item); | ||
gtk_widget_set_sensitive(item, FALSE); | ||
data->menu_items = g_slist_prepend(data->menu_items, (gpointer) item); | ||
g_free(text); | ||
} | ||
|
||
return TRUE; | ||
} | ||
|
||
|
||
static void proxy_help(GeanyPlugin *plugin, gpointer pdata) | ||
{ | ||
PluginContext *data; | ||
GtkWidget *dialog; | ||
|
||
data = (PluginContext *) pdata; | ||
|
||
dialog = gtk_message_dialog_new( | ||
GTK_WINDOW(plugin->geany_data->main_widgets->window), | ||
GTK_DIALOG_DESTROY_WITH_PARENT, | ||
GTK_MESSAGE_INFO, | ||
GTK_BUTTONS_OK, | ||
"%s", data->help_text); | ||
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), | ||
_("(From the %s plugin)"), plugin->info->name); | ||
|
||
gtk_dialog_run(GTK_DIALOG(dialog)); | ||
gtk_widget_destroy(dialog); | ||
} | ||
|
||
|
||
static void proxy_cleanup(GeanyPlugin *plugin, gpointer pdata) | ||
{ | ||
PluginContext *data = (PluginContext *) pdata; | ||
|
||
g_slist_free_full(data->menu_items, (GDestroyNotify) gtk_widget_destroy); | ||
g_free(data->help_text); | ||
} | ||
|
||
|
||
static gint demoproxy_probe(GeanyPlugin *proxy, const gchar *filename, gpointer pdata) | ||
{ | ||
/* We know the extension is right (Geany checks that). For demo purposes we perform an | ||
* additional check. This is not necessary when the extension is unique enough. */ | ||
gboolean match = FALSE; | ||
gchar linebuf[128]; | ||
FILE *f = fopen(filename, "r"); | ||
if (f != NULL) | ||
{ | ||
if (fgets(linebuf, sizeof(linebuf), f) != NULL) | ||
match = utils_str_equal(linebuf, "#!!PROXY_MAGIC!!\n"); | ||
fclose(f); | ||
} | ||
return match ? PROXY_MATCHED : PROXY_IGNORED; | ||
} | ||
|
||
|
||
static gpointer demoproxy_load(GeanyPlugin *proxy, GeanyPlugin *plugin, | ||
const gchar *filename, gpointer pdata) | ||
{ | ||
GKeyFile *file; | ||
gboolean result; | ||
|
||
file = g_key_file_new(); | ||
result = g_key_file_load_from_file(file, filename, 0, NULL); | ||
|
||
if (result) | ||
{ | ||
PluginContext *data = g_new0(PluginContext, 1); | ||
data->file = file; | ||
|
||
plugin->info->name = g_key_file_get_locale_string(data->file, "Info", "name", NULL, NULL); | ||
plugin->info->description = g_key_file_get_locale_string(data->file, "Info", "description", NULL, NULL); | ||
plugin->info->version = g_key_file_get_locale_string(data->file, "Info", "version", NULL, NULL); | ||
plugin->info->author = g_key_file_get_locale_string(data->file, "Info", "author", NULL, NULL); | ||
|
||
plugin->funcs->init = proxy_init; | ||
plugin->funcs->help = proxy_help; | ||
plugin->funcs->cleanup = proxy_cleanup; | ||
|
||
/* Cannot pass g_free as free_func be Geany calls it before unloading, and since | ||
* demoproxy_unload() accesses the data this would be catastrophic */ | ||
GEANY_PLUGIN_REGISTER_FULL(plugin, 225, data, NULL); | ||
return data; | ||
} | ||
|
||
g_key_file_free(file); | ||
return NULL; | ||
} | ||
|
||
|
||
static void demoproxy_unload(GeanyPlugin *proxy, GeanyPlugin *plugin, gpointer load_data, gpointer pdata) | ||
{ | ||
PluginContext *data = load_data; | ||
|
||
g_free((gchar *)plugin->info->name); | ||
g_free((gchar *)plugin->info->description); | ||
g_free((gchar *)plugin->info->version); | ||
g_free((gchar *)plugin->info->author); | ||
|
||
g_key_file_free(data->file); | ||
g_free(data); | ||
} | ||
|
||
|
||
/* Called by Geany to initialize the plugin. */ | ||
static gboolean demoproxy_init(GeanyPlugin *plugin, gpointer pdata) | ||
{ | ||
const gchar *extensions[] = { "ini", "px", NULL }; | ||
|
||
plugin->proxy_funcs->probe = demoproxy_probe; | ||
plugin->proxy_funcs->load = demoproxy_load; | ||
plugin->proxy_funcs->unload = demoproxy_unload; | ||
|
||
return geany_plugin_register_proxy(plugin, extensions); | ||
} | ||
|
||
|
||
/* Called by Geany before unloading the plugin. */ | ||
static void demoproxy_cleanup(GeanyPlugin *plugin, gpointer data) | ||
{ | ||
} | ||
|
||
|
||
G_MODULE_EXPORT | ||
void geany_load_module(GeanyPlugin *plugin) | ||
{ | ||
plugin->info->name = _("Demo Proxy"); | ||
plugin->info->description = _("Example Proxy."); | ||
plugin->info->version = "0.1"; | ||
plugin->info->author = _("The Geany developer team"); | ||
|
||
plugin->funcs->init = demoproxy_init; | ||
plugin->funcs->cleanup = demoproxy_cleanup; | ||
|
||
GEANY_PLUGIN_REGISTER(plugin, 225); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!!PLUXY_MAGIC!! | ||
|
||
[Init] | ||
item0 = Bam | ||
item1 = Foo | ||
item2 = Bar | ||
|
||
[Help] | ||
text = I'm a simple test. Nothing to see! | ||
|
||
[Info] | ||
name = Demo Pluxy Tester | ||
description = I'm a simple test. Nothing to see! | ||
version = 0.1 | ||
author = The Geany developer team |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't match the one in the docs, nor the one actually checked by the demoproxy