geany/doc/plugins.dox

589 lines
23 KiB
Plaintext
Raw Normal View History

/*
* plugins.dox - this file is part of Geany, a fast and lightweight IDE
*
* Copyright 2008-2010 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* Copyright 2008-2010 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
* Copyright 2009-2010 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
*
* 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.
*
* $Id$
*
* This file contains additional plugin documentation like the signal system and a small howto.
* It is best viewed when filetype is set to C or C++.
*/
/**
*
* @mainpage Geany Plugin API Documentation
*
* @author Enrico Tröger, Nick Treleaven, Frank Lanitz
* @date $Date$
*
* @section Intro
* This is the Geany API documentation. It should be considered work in progress.
* We will try to document as many functions and structs as possible.
*
* To get started, see the @link howto Plugin Howto @endlink.
*
* Other pages:
* - @link pluginsymbols.c Plugin Symbols @endlink
* - @link plugindata.h Main Datatypes and Macros @endlink
* - @link signals Plugin Signals @endlink
* - @link pluginutils.c Plugin Utility Functions @endlink
* - @link guidelines Plugin Writing Guidelines @endlink
* - <b>plugins/demoplugin.c</b> - in Geany's source, bigger than the howto example
* - Header files for functions and types - see <b>Files</b> link at the top
* - Deprecated symbols - see <b>Related Pages</b> link at the top
*
* @warning Do not use any symbol not in the documentation - it may change.
* @note See the HACKING file for information about developing the plugin API and
* other useful notes.
*/
/**
* @page signals Plugin Signals
*
*
* @section Usage
*
* To use plugin signals in Geany, you have two options:
*
* -# Create a PluginCallback array with the @ref plugin_callbacks symbol. List the signals
* you want to listen to and create the appropiate signal callbacks for each signal.
* The callback array is read @a after plugin_init() has been called.
* -# Use plugin_signal_connect(), which can be called at any time and can also connect
* to non-Geany signals (such as GTK widget signals).
*
* The following code demonstrates how to use signals in Geany plugins. The code can be inserted
* in your plugin code at any desired position.
*
* @code
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
static void on_document_open(GObject *obj, GeanyDocument *doc, gpointer user_data)
{
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
printf("Example: %s was opened\n", DOC_FILENAME(doc));
}
PluginCallback plugin_callbacks[] =
{
{ "document-open", (GCallback) &on_document_open, FALSE, NULL },
{ NULL, NULL, FALSE, NULL }
};
* @endcode
* @note The PluginCallback array has to be ended with a final @c NULL entry.
*
* @section Signals
*
* @signaldef document-new
* @signalproto
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent when a new document is created.
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* @param doc the new document.
* @param user_data user data.
* @endsignaldef
*
* @signaldef document-open
* @signalproto
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent when a new document is opened.
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* @param doc the opened document.
* @param user_data user data.
* @endsignaldef
*
* @signaldef document-before-save
* @signalproto
* void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent before a document is saved.
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
* @param doc the document to be saved.
* @param user_data user data.
* @endsignaldef
*
* @signaldef document-save
* @signalproto
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent when a new document is saved.
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* @param doc the saved document.
* @param user_data user data.
* @endsignaldef
*
* @signaldef document-filetype-set
* @signalproto
* void user_function(GObject *obj, GeanyDocument *doc, GeanyFiletype *filetype_old, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent after the filetype of a document has been changed.
* The previous filetype object is passed but it can be NULL (e.g. at startup).
* The new filetype can be read with: @code
* GeanyFiletype *ft = doc->file_type;
* @endcode
*
* @param obj a GeanyObject instance, should be ignored.
* @param doc the saved document.
* @param filetype_old the previous filetype of the document.
* @param user_data user data.
* @endsignaldef
*
* @signaldef document-activate
* @signalproto
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent when switching notebook pages.
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
Merge the document-pointer branch. Note: this breaks the plugin API for document functions, document signal callbacks, msgwin_msg_add() and navqueue_goto_line(). Make all DocumentFuncs use a GeanyDocument* instead of an integer index, so there's no need to access the documents array or use DOC_IDX_VALID() - usually just check for non-NULL. Pass a document pointer to the callbacks of all document-* signals. Add GeanyDocument::index field for use with the documents array. Remove DocumentFuncs::get_cur_idx() - use get_current() instead. Replace DocumentFuncs::get_n_idx() with get_from_page(). Rename DocumentFuncs::find_by_realpath() to find_by_real_path(). Replace DocumentFuncs::remove() with remove_page(). Add 'changed' argument for DocumentFuncs::set_text_changed(). Make NavQueueFuncs and MsgWinFuncs use a GeanyDocument* instead of an integer index. Add DOC_VALID() macro. Add deprecated DOC_IDX() macro to get the document index from a possibly NULL pointer; deprecate macro DOC_IDX_VALID. These macros can make porting outside plugins easier; of course, it is better to rewrite the code to use document pointers. Use document pointer instead of an index to the documents array everywhere in the core code. Rename utils_check_disk_status() in document_check_disk_status() and move it into document.c. Adjust plugins to work with these changes. Add dox for document_set_filetype(). Rename debugging function doc() doc_at() to avoid conflicts. Update plugin signals dox. git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2705 ea778897-0a13-0410-b9d1-a72fbfd435f5
2008-06-18 17:03:08 +00:00
* @param doc the current document.
* @param user_data user data.
* @endsignaldef
*
* @signaldef document-close
* @signalproto
* void user_function(GObject *obj, GeanyDocument *doc, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent before closing a document.
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
* @param doc the document about to be closed.
* @param user_data user data.
* @endsignaldef
*
* @signaldef project-open
* @signalproto
* void user_function(GObject *obj, GKeyFile *config, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent after a project is opened but before session files are loaded.
* @param obj a GeanyObject instance, should be ignored.
* @param config an exising GKeyFile object which can be used to read and write data.
* It must not be closed or freed.
* @param user_data user data.
* @endsignaldef
*
* @signaldef project-save
* @signalproto
* void user_function(GObject *obj, GKeyFile *config, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent when a project is saved(happens when the project is created, the properties
* dialog is closed or Geany is exited). This signal is emitted shortly before Geany
* will write the contents of the GKeyFile to the disc.
* @param obj a GeanyObject instance, should be ignored.
* @param config an exising GKeyFile object which can be used to read and write data.
* It must not be closed or freed.
* @param user_data user data.
* @endsignaldef
*
* @signaldef project-close
* @signalproto
* void user_function(GObject *obj, gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent after a project is closed.
* @param obj a GeanyObject instance, should be ignored.
* @param user_data user data.
* @endsignaldef
*
* @signaldef update-editor-menu
* @signalproto
* void user_function(GObject *obj, const gchar *word, gint pos, GeanyDocument *doc,
* gpointer user_data);
* @endsignalproto
* @signaldesc
* Sent before the popup menu of the editing widget is shown. This can be used to modify or extend
* the popup menu.
*
* @note You can add menu items from @c plugin_init() using @c geany->main_widgets->editor_menu,
* remembering to destroy them in @c plugin_cleanup().
*
* You need to include "document.h" for the declaration of GeanyDocument.
*
* @param obj a GeanyObject instance, should be ignored.
* @param word the current word (in UTF-8 encoding) below the cursor position
where the popup menu will be opened.
* @param click_pos the cursor position where the popup will be opened.
* @param doc the current document.
* @param user_data user data.
* @endsignaldef
*
* @signaldef editor-notify
* @signalproto
* gboolean user_function(GObject *obj, GeanyEditor *editor, SCNotification *nt,
* gpointer user_data);
* @endsignalproto
* @signaldesc
* This signal is sent whenever something in the editor widget changes (character added,
* fold level changes, clicks to the line number margin, ...).
* A detailed description of possible notifications and the SCNotification can be found at
* http://www.scintilla.org/ScintillaDoc.html#Notifications.
*
* If you connect to this signal, you must check @c nt->nmhdr.code for the notification type
* to prevent handling unwanted notifications. This is important because for instance SCN_UPDATEUI
* is sent very often whereas you probably don't want to handle this notification.
*
* By default, the signal is sent before Geany's default handler is processing the event.
* Your callback function should return FALSE to allow Geany processing the event as well. If you
* want to prevent this for some reason, return TRUE.
* Please use this with care as it can break basic functionality of Geany.
*
* The signal can be sent after Geany's default handler has been run when you set
* PluginCallback::after field to TRUE.
*
* An example callback implemention of this signal can be found in the Demo plugin.
*
* @warning This signal has much power and should be used carefully. You should especially
* care about the return value; make sure to return TRUE only if it is necessary
* and in the correct situations.
*
* You need to include "editor.h" for the declaration of GeanyEditor and "Scintilla.h" for
* SCNotification.
*
* @param obj a GeanyObject instance, should be ignored.
* @param editor The current GeanyEditor.
* @param nt A pointer to the SCNotification struct which holds additional information for
* the event.
* @param user_data user data.
* @return @c TRUE to stop other handlers from being invoked for the event.
* @c FALSE to propagate the event further.
*
* @since 0.16
* @endsignaldef
*
*
*
* @page guidelines Plugin Writing Guidelines
*
* @section intro Introduction
*
* The following hints and guidelines are only recommendations. Nobody is forced to follow
* them at all.
*
* @section general General notes
*
* @subsection ideas Getting a plugin idea
*
* If you want to write a plugin but don't know yet what it should do, have a look at
* http://www.geany.org/Support/PluginWishlist to get an idea about what users wish.
*
* @subsection code Managing the source code
*
* For authors of plugins for Geany, we created a dedicated @a geany-plugins project at
* Sourceforge to ease development of plugins and help new authors.
* Project website: http://sourceforge.net/projects/geany-plugins
*
* Each plugin author is welcome to use these services. To do so, you need an account at
* Sourceforge. You can easily register at (http://sourceforge.net/account/registration/).
* After you successfully created an account,
* tell your account name Enrico or Nick and you will write access to the SVN repository
* (http://geany-plugins.svn.sourceforge.net/viewvc/geany-plugins/).
* Then you can use the repository for your own plugin.
*
* Authors using this service should subscribe to the
* geany-plugins-commits at uvena.de and geany-plugins-tracker at uvena.de
* mailing lists(see my previous post) to stay up to date with changes.
* General plugin discussion can happen on the normal geany at uvena.de or
* geany-devel at uvena.de lists.
*
* At time of writing, there are some plugins already available in the
* repository. Feel free to use any of these plugins as a start for your own,
* maybe by copying the directory structure and the autotools files
* (Makefile.am, configure.in, ...). Most of the available plugins are also ready for
* i18n support, just for reference.
*
* New plugins should be imported into a new directory inside the trunk/
* directory. There are also the common branches and tags directories, use
* them as needed, use always a subdirectory for your own plugin.
*
* We encourage authors using this service to only commit changes to their
* own plugin and not to others' plugins. Instead just send patches to
* geany-devel at uvena.de or the plugin author directly.
*
* (the full announcement of this service can be found at
* http://lists.uvena.de/geany/2008-April/003225.html)
*
*
* @section paths Installation paths
*
* - The plugin binary (@c pluginname.so) should be installed in Geany's libdir. This is
* necessary so that Geany can find the plugin.
* An easy way to retrieve Geany's libdir is to use the pkg-config tool, e.g. @code
* `$PKG_CONFIG --variable=libdir geany`/ geany
* @endcode
* - If your plugin creates other binary files like helper programs or helper libraries,
* they should go into @c $prefix/bin (for programs, ideally prefixed with @a geany),
* additional libraries should be installed in Geany's libdir, maybe in a subdirectory.
* - Plugins should install their documentation files (README, NEWS, ChangeLog, licences and
* other documentation files) into the common documentation directory
* @c $prefix/share/doc/geany-plugins/$pluginname/
* - Translation files should be installed normally into @c $prefix/share/locale. There is no
* need to use Geany's translation directory. To set up translation support properly and
* for additional information, see main_locale_init().
* - Do @a never install anything into a user's home directory like installing
* the plugin binary in @c ~/.config/geany/plugins/.
*
*
* @page howto Plugin Howto
*
* @section intro Introduction
*
* Since Geany 0.12 there is a plugin interface to extend Geany's functionality and
* add new features. This document gives a brief overview about how to add new
* plugins by writing a simple "Hello World" plugin in C.
*
*
* @section buildenv Build environment
*
* To be able to write plugins for Geany, you need the source code and some development
* packages for GTK and its dependencies. The following will only describe the way to compile and
* build plugins on Unix-like systems [1].
* If you already have the Geany source code and compiled it from them, you can skip the
* following.
*
* First you need to have Geany installed. Then install the development files for GTK
* and its dependencies. The easiest way to do this is to use your distribution's package
* management system, e.g. on Debian and Ubuntu systems you can use
* @code apt-get install libgtk2.0-dev intltool @endcode
* This will install all necessary files to be able to compile plugins for Geany. On other
* distributions, the package names and commands to use may differ.
*
* Basically, you are done at this point and could continue with writing the plugin code.
*
* [1] For Windows, it is basically the same but you might have some more work on setting up
* the general build environment(compiler, GTK development files, ...). This is described on
* Geany's website at http://www.geany.org/Support/BuildingOnWin32.
*
* @section helloworld "Hello World"
*
* When writing a plugin, you will find a couple of functions or macros which are mandatory
* and some which are free to use for implementing some useful feature once your plugin
* becomes more powerful like including a configuration or help dialog.
*
* You should start your plugin with including some of the needed C header files and defining
* some basic global variables which will help you to access all needed functions of the plugin
* API in a more comfortable way.
*
* Let's start with the very basic headers and add more later if necessary.
* @code
#include "geanyplugin.h"
* @endcode
*
* @a geanyplugin.h includes all of the Geany API and also the necessary GTK header files,
* so there is no need to include @a gtk/gtk.h yourself.
*
* @note
* @a plugindata.h contains the biggest part of the plugin API and provides some basic macros.
* @a geanyfunctions.h provides some macros for convenient access to plugin API functions.
*
* The you should define three basic variables which will give access to data fields and
* functions provided by the plugin API.
* @code
GeanyPlugin *geany_plugin;
GeanyData *geany_data;
GeanyFunctions *geany_functions;
* @endcode
*
* Now you can go on and write your first lines for your new plugin. As mentioned before,
* you will need to implement and fill out a couple of functions/macros to make the plugin work.
* So let's start with PLUGIN_VERSION_CHECK().
*
* PLUGIN_VERSION_CHECK() is a convenient way to tell Geany which version of Geany's plugin API
* is needed at minimum to run your plugin. The value is defined in
* @a plugindata.h by @a GEANY_API_VERSION. In most cases this should be your minimum.
* Nevertheless when setting this value, you should choose the lowest possible version here to
* make the plugin compatible with a bigger number of versions of Geany.
*
* For the next step, you will need to tell Geany some basic information about your plugin
* which will be shown in the plugin manager dialog.
*
* For doing this, you should use PLUGIN_SET_INFO() which expects 4 values:
* - Plugin name
* - Short description
* - Version
* - Author
*
* Based on this, the line could look like:
* @code
PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world",
"1.0", "John Doe <john.doe@example.org>");
* @endcode
*
* Once this is done, you will need to implement the function which will be executed when the
* plugin is loaded. Part of that function could be adding and removing of an item to
* Geany's Tools menu, setting up keybindings or registering some callbacks. Also you will
* need to implement the function that is called when your plugin is unloaded.
* These functions are called plugin_init() and plugin_cleanup(). Let's see how it could look like:
* @code
PLUGIN_VERSION_CHECK(147)
PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world",
"1.0", "Joe Doe <joe.doe@example.org>");
void plugin_init(GeanyData *data)
{
}
void plugin_cleanup(void)
{
}
* @endcode
*
* If you think this plugin seems not to implement any functionality right now and only wastes
* some memory, you are right. But it should compile and load/unload in Geany nicely.
* Now you have the very basic layout of a new plugin. Great, isn't it?
*
* Let's go on and implement some real functionality.
*
* As mentioned before, plugin_init() will be called when the plugin is loaded in Geany.
* So it should implement everything that needs to be done during startup. In this case,
* we'd like to add a menu item to Geany's Tools menu which runs a dialog printing "Hello World".
* @code
void plugin_init(GeanyData *data)
{
GtkWidget *main_menu_item;
// Create a new menu item and show it
main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World");
gtk_widget_show(main_menu_item);
// Attach the new menu item to the Tools menu
gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
main_menu_item);
// Connect the menu item with a callback function
// which is called when the item is clicked
g_signal_connect(main_menu_item, "activate",
G_CALLBACK(item_activate_cb), NULL);
}
* @endcode
*
* This will add an item to the Tools menu and connect this item to a function which implements
* what should be done when the menu item is activated by the user.
* This is done by g_signal_connect(). The Tools menu can be accessed with
* geany->main_widgets->tools_menu. The structure @a main_widgets contains pointers to the
* main GUI elements in Geany.
*
* Geany has a simple API for showing message dialogs. So our function contains
* only a few lines:
* @code
void item_activate_cb(GtkMenuItem *menuitem, gpointer user_data)
{
dialogs_show_msgbox(GTK_MESSAGE_INFO, "Hello World");
}
* @endcode
*
* For the moment you don't need to worry about the parameters of that function.
*
* Now we need to clean up properly when the plugin is unloaded.
*
* To remove the menu item from the Tools menu, you can use gtk_widget_destroy().
* gtk_widget_destroy() expects a pointer to a GtkWidget object.
*
* First you should add gtk_widget_destroy() to your plugin_cleanup() function.
* The argument for gtk_widget_destroy() is the widget object you created earlier in
* plugin_init(). To be able to access this pointer in plugin_cleanup(), you need to move
* its definition from plugin_init() into the global context so its visibility will increase
* and it can be accessed in all functions.
* @code
static GtkWidget *main_menu_item = NULL;
// ...
void plugin_init(GeanyData *data)
{
main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World");
gtk_widget_show(main_menu_item);
// ...
}
void plugin_cleanup(void)
{
gtk_widget_destroy(main_menu_item);
}
* @endcode
*
* This will ensure your menu item is removed from the Tools menu as well as from
* memory once your plugin is unloaded, so you don't leave any memory leaks.
* Once this is done, your first plugin is ready. Congratulations!
*
* The complete listing (without comments):
* @code
#include "geanyplugin.h"
GeanyPlugin *geany_plugin;
GeanyData *geany_data;
GeanyFunctions *geany_functions;
PLUGIN_VERSION_CHECK(147)
PLUGIN_SET_INFO("HelloWorld", "Just another tool to say hello world",
"1.0", "John Doe <john.doe@example.org>");
static GtkWidget *main_menu_item = NULL;
static void item_activate_cb(GtkMenuItem *menuitem, gpointer gdata)
{
dialogs_show_msgbox(GTK_MESSAGE_INFO, "Hello World");
}
void plugin_init(GeanyData *data)
{
main_menu_item = gtk_menu_item_new_with_mnemonic("Hello World");
gtk_widget_show(main_menu_item);
gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
main_menu_item);
g_signal_connect(main_menu_item, "activate",
G_CALLBACK(item_activate_cb), NULL);
}
void plugin_cleanup(void)
{
gtk_widget_destroy(main_menu_item);
}
* @endcode
*
*
* Now you might like to look at Geany's source code for core plugins such as
* @a plugins/demoplugin.c.
**/