KKEdit Plugins

KKEdit now supports a simple 'c' plugin system, which allows you to add your own menus, call the built in doc viewer, and a few other things, this will be expanded as time goes on.
All the plugins here have been translated to French courtesy of:
Nguyen Thanh Tung thngtong@gmail.com

An example plugin is provided that displays this help.
First off when the plugin is loaded/unloaded if you have a function called 'g_module_check_init' and/or 'g_module_unload' these functions will be run automatically and should be used for any initialization/clean up etc.

If your module has a function called 'addToGui' then this function is called when KKEdit has finished setting up it's own GUI and your plugin can then add to the existing GUI, the structure that is passed to the 'addToGui' functions is defined in 'kkedit-plugins.h' which is installed in /usr/include, the basic structure is this:

struct moduleData
char*         name;
bool         enabled;
GModule*         module;
bool         loaded;
char*         path;
bool         unload;

struct plugMenuList
GtkWidget* menuBar;
GtkWidget* menuFile;
GtkWidget* menuEdit;
GtkWidget* menuFunc;
GtkWidget* menuNav;
GtkWidget* menuTools;
GtkWidget* menuHelp;
GtkWidget* menuBookMark;
GtkWidget* menuView;

struct plugData
plugMenuList         mlist;
moduleData* modData;
// GList* plugins;
//install location of KKEdit data
const char* dataDir;
//global plugin folder defaults to DATADIR/plugins
char* gPlugFolder;
//local plugin folder defaults to ~/.KKEdit/plugins
char* lPlugFolder;
//kkedit version string
char* kkeditVersion;
char* htmlFile;
//location of variable that holds the uri to be disp[layed by showDoc
char** thePage;
//main notebook
GtkNotebook* notebook;
//current page MAYBE NULL!!
pageStruct* page;
//cuurent tab
int currentTab;
//KKEdits temp folder
char* tmpFolder;
//kkedits main window user box's
GtkWidget* topUserBox;
GtkWidget* mainWindowVPane;
GtkWidget* leftUserBox;
GtkWidget* mainWindowHPane;
GtkWidget* rightUserBox;
GtkWidget* secondWindowHPane;
GtkWidget* bottomUserBox;
GtkWidget* secondWindowVPane;
//kkedit main window
GtkWidget* mainWindow;
//tool output window buffer;
GtkTextBuffer* toolOutBuffer;
//tool output window
GtkWidget* toolOutWindow;
//tab popup menu
GtkWidget* tabPopUpMenu;
//right click popup menu
GtkWidget* contextPopUpMenu;

//leftright user box visiblity ref
int leftShow;
int rightShow;
//topbottom user box visiblity ref
int topShow;
int bottomShow;

The 'plugMenuList' structure is fairly self explanatory, the menBar is where you would add a new main menu, or you can add a menu item to the others, like the example plugin adds a menuitem to the 'Help' menu.
The other items in the struct are:

dataDir=The install location of KKEdit's data usually /usr/share/KKEdit.
gPlugFolder=The global plugin folder, defaults to dataDir/plugins.
lPlugFolder=The local plugin folder, defaults to  ~/.KKEdit/plugins.
thePage=The location to store the uri for use in the docviewer.
page=A pointer to a data structure conatining all the info about the current tab, filename, filepath, source buffer etc, like so:
currentTab=The currentlt active tab number;
tmpFolder=KKEdits tempory folder.
topUserBox, leftUserBox, mainWindowHPane, rightUserBox, secondWindowHPane, bottomUserBox, mainWindow=The user GtkWidgets for adding to the GUI.
toolOutBuffer=The GtkTextbuffer of the tool output pane.
toolOutWindow=The tool output window.
tabPopUpMenu=The menu supplied to the plugin for use when the 'tab' is clicked to add to the menu, ( used by the file browser ).
contextPopUpMenu=The menu supplied to the plugin when a right click pops up the context menu.
leftShow, rightShow=Private.

KKEdit routines available to the plugin:
void showDocView(int howtodisplay,char* text,const char* title);
pageStruct* getPageStructPtr(int pagenum);
void showToolOutput(bool immediate);
void hideToolOutput(bool immediate);
void showSide(bool left);
void hideSide(bool left);
void showTop(bool top);
void hideTop(bool top);
void runCommand(char* commandtorun,void* ptr,bool interm,int flags,int useroot,char* title);
void debugFree(gpointer ptr,const char* message);
bool openFile(const gchar *filepath,int linenumber,bool warn);
bool saveFile(GtkWidget* widget,gpointer data);
void newFile(GtkWidget* widget,gpointer data);
void loadVarsFromFile(char* filepath,args* dataptr);
void saveVarsToFile(char* filepath,args* dataptr);

showDocView(USEURI,(char*)"KKEdit Plugin Help",(char*)"KKEdit Plugin Help"); Where USEURI is the uri contained in thePage, the text in the second param is used as a search term if thePage is empty, and the final param sets the title of the doc viewer.

pageStruct* getPageStructPtr(int pagenum);
Returns a pageStruct* for the document in tab number pagenum, if pagenum is -1 the current tab is used.

void showToolOutput(bool immediate);
Show the tool output window.

void hideToolOutput(bool immediate);
Hide the tool output window.

void showSide(bool left);
void hideSide(bool left);
void showTop(bool top);
void hideTop(bool top);
Show/Hide the left /right/top/bottom user panes, this should be used instead of gtk_widget_show etc as it allows multiple plugins to hide/show the panes.

void runCommand(char* commandtorun,void* ptr,bool interm,int flags,int useroot,char* title);
Use the KKEdit run command as used by the external tools, allowing to run syn/async, in a terminal etc.

void debugFree(gpointer ptr,const char* message);

bool openFile(const gchar *filepath,int linenumber,bool warn);
Open a file in a new tab, filepath=path to file to open, linenumber=Place cursor on this line, warn=Warn if the file can't be opened.

bool saveFile(GtkWidget* widget,gpointer data);
Save the current page.

void newFile(GtkWidget* widget,gpointer data);
Create a new untitled document.

void loadVarsFromFile(char* filepath,args* dataptr);
Parse and load a config file.
void saveVarsToFile(char* filepath,args* dataptr);
Save cofig data to file.
See the TerminalPane plugin for an example of how to use these functions.

The main page structure that stores all the info for the current document.
GtkWidget* pane;
GtkScrolledWindow*         pageWindow;
GtkScrolledWindow*         pageWindow2;
GtkSourceBuffer*         buffer;
GtkSourceView*         view;
GtkSourceView*         view2;
char* filePath;
char* realFilePath;
char* dirName;
GtkMenuItem*         navSubMenu;
bool rebuildMenu;
GtkWidget* tabName;
GtkTextIter iter;
GtkTextIter match_start;
GtkTextIter match_end;
bool isFirst;
char* fileName;
GFile* gFile; 
GFileMonitor*         monitor;
bool itsMe;
GList* markList;
bool inTop;
bool isSplit;
const char* lang;
GtkWidget* tabVbox;
bool showingChanged;
GtkTextMark*         backMark;
GtkTextTag* highlightTag;
GList* userDataList;
gpointer reserved1;
gpointer reserved2;
gpointer reserved3;
gpointer reserved4;

So this call back in the example plugin is setup and called like so:
First add the extra GUI elements:
extern "C" int addToGui(gpointer data)
    GtkWidget*       menu;
    plugData*        plugdata=(plugData*)data;

    printf("Adding to GUI from example-plugin\n");

    gtk_menu_item_set_label((GtkMenuItem*)examplemenu,"Plugin Help");

    leftButton=gtk_button_new_with_label("left side button\nat top");

    rightButton=gtk_button_new_with_label("right side button\nat bottom");

    topLabel=gtk_label_new("Top user vbox demo label");

    bottomLabel=gtk_label_new("Bottom user vbox demo label");

    printf("Done adding GUI from example-plugin\n");

Add a callback like so:
void openPlugHelp(GtkWidget* widget,gpointer data)
    plugData*    pdata=(plugData*)data;
    showDocView(USEURI,(char*)"KKEdit Plugin Help",(char*)"KKEdit Plugin Help");

The data structure is supplied to the following functions as 'gpointer data' the same way as the 'addToGui' function above, and should be cast to a 'plugData*' pointer.

If your plugin contains a function called 'setSensitive' when the text buffer changes or a file is open or saved etc, it will be called with data->page set to the current page ( may be NULL ), this allows your plugin to do stuff depending on the file state.

If your plugin contains a function called 'openFile' when a file is opened it will be called with data->page set to the new page, this allows your plugin to do stuff immediately after a new file is opened.

If your plugin contains a function called 'saveFile' when a file is saved it will be called with data->page set to the saved page, this allows your plugin to do stuff immediately after a file is saved.

If your plugin contains a function called 'newFile' when a new file is created it will be called with data->page set to the new page, this allows your plugin to do stuff immediately after a new file is created

If your plugin contains a function called 'closeFile' when a file is closed it will be called with data->page set to the closing page, this allows your plugin to do stuff immediately before a file that is closing is destroyed.

If your plugin contains a function called 'newTab' when a file is closed it will be called with data->page set to the newly created page, this happens before 'openFile' and 'newFile'.

If your plugin contains a function called 'switchTab' when the notebook switches tab either manually or programmatically this function is called with data->currentTab set to the new current tab.

If your plugin contains a function called 'showAbout' it will be run when the 'About' button is clicked from the Edit->Plugin Prefs dialog.

  If your plugin contains a function called 'plugPrefs' it will be run when the 'Preferences' button is clicked from the Edit->Plugin Prefs dialog, this should only be used for user settings, the 'g_module_check_init' function should be used for setting the original preferences for the plugin ( if any ).

If your plugin contains a function called 'enablePlug' it wil be run when enableing/disabling the plugin from the prefs menu, if it is safe for the plugin to be unloaded, do whatever needs to be done and return 0, any non-zero return result will inform KKEdit not to unload the plugin but it will be disabled at the next start up of KKEdit.
To see what gets run and when run KKEdit from the command line and brief messages will be printed as the various plugin functions are called, these messages are printed by the example plugin not KKEdit.

See the kkedit-plugins.h file for a documented list of structures and also the various routines that can be called from kkedit itself. 

Example Plugin

This is the example plugin that was included with KKEdit, it doesn't really do anything except show how to add some GUI elements and use the built in doc viewer.

New Project Plugin

This plugin will add a new menu to the menu bar called ( surprisingly! ) 'Projects' and what it allow you to do is to create a skeleton project of various types like so:

To install simply download the tarball exract it,cd into the folder and run make, then to install it locally ( ie into ~/.KKEdit/plugins ) run make install, to install globally ( ie to /usr/share/KKEdit/plugins ) run sudo make install.

First you should set the preferences of where you want to store your new project, do this by opening the plug prefs menu from the 'Edit' menu select 'newproject' and click 'Preferences' like so:

 and you will get a small dialog like so:

This allows you to set the folder where the projects are stored ( defaults to ~/Projects and ~/SVN ) and also a folder for a local subversion repo ( you must have subversion installed for this ) , click 'Apply' to set the prefs.
Now when you select a new project type from the projects menu a dialog will popup and ask you to name the project, you can use upper or lower case or mixed but no spaces like so:

A new folder will be created in ~/Projects ( or whatever you have set the prefs to ) and if you have left the 'Create SVN Repo' box checked a subversion repo will be created ( the project will be checked out as a svn project ), then you cd into the folder run ./configure ( on most of the skeleton projects ) make, and sudo make install.
Most of the included skeletons are autotool projects and use the normal ./configure,make,sudo make install, the plugin project just has a make file which should be edited to your own system, basically just do make, make install or sudo make install, if you don't run make install as root then the plugin will be installed in ~/.KKEdit/plugins, if you run make install as root it will be installed in /usr/share/KKEdit/plugins, this is the bit you may have to change in the make file if you have not installed KKEdit into /usr.

You can add your own skeleton projects by just making a new archive of the skeleton folder and call it bonesSOMEPROJECT and also a file called SOMEPROJECT.info which is just a text file containing a short description of the project type.
The archive should contain all the needed skeleton files with various place holders like so any occurrence of <>PROJ<> in a file name will be replaced with the projects name keeping the case, any occurrence of <>APP<> in a file name will be replaced with the lower cased project name, ALL occurrence's IN a file file of <>PROJ<> or <>APP<> will do the same, binary files like pngs etc will not be changed ( except for the file name ).
Just extract one of the archives to see how it all works, it's really quite simple.

Currently there are skeleton projects for:
Command - A command line 'Hello World' project.
GTK2 - A Gtk2 app that just opens a window.
GtkDialog.info - A BASH script that uses GtkDialog to run a simple dialogbox.
QT5 - A qt5  demo that opens a window with a button.
GtkQt5Cross - A Gtk/Qt5 project select what to build with a configure option.
KKEditPlugin - A basic KKEdit plugin, no configure just make.
XForms - a Simple XForms windowwith two buttons, no configure just make.
Theme - The basics of a Gtk/Metacity/Xfwm4 theme, probably a bit out of date now as I don't do much themeing.

Download New Project Plugin

File Browser Plugin

This plugin will add a simple Tree View file browser to the left of the main window like so:

To install simply download the tarball exract it,cd into the folder and run make, then to install it locally ( ie into ~/.KKEdit/plugins ) run make install, to install globally ( ie to /usr/share/KKEdit/plugins ) run sudo make install.

You can double click on an item to open it with the default application for that mimetype.
The browser pane width will be expanded/contracted automatically depending on what is being shown, you can hide/show the browser via the 'View' main menu, the visibility of the browser pane is remembered for the next start up of KKEdit.
It also adds a menu item to the tab menu so that you can open the current file in the browser.

Edit Remote File

This plugin will allow you to edit a remote file over ssh using the scp command.
The plugin will import to a local file the remote file, and you can then edit the file and re-export the file to the remote location, to export the file you of course need write privileges for the remote file.

You can sync local file saves ( using the 'Save' menu ) to the remote file in the prefs like so:

Of course you will be asked for the password to export the file.
You can re-load the remote file from the sub menu entry for the remote file and also export to the remote file.
If you don't want to keep entering your password you can set up ssh to use security files on the remote and local machine, see the ssh/ssl man page and home page's.

Terminal Pane

The Terminal pane plugin adds a simple terminal to the bottom pane like so:

You can Show/Hide the terminal from the view menu or the context menu.
The terminal has a simple context menu, just right click like so:

'CD To Page' will cd into the enclosing folder of the currently selected document.
Forground and background colurs can be set from the prefs like so:
The terminal pane needs KKEdit to be restarted after disabling from the 'Plugin Prefs' dialog.
You will need to install the libvte package for this plugin, debian based distros use:
sudo apt-get install libvte-dev

Sessions Manager

The Sessions Managet plugin will add a sub menu to the 'Save Session/Restore Session' menus allowing up to 8 different named sessions to be saved loaded, like so:

Saving a session will give you the opportunity to rename it:

If you have set the automatic save/restore of the session in the main prefs this will continue to operate as normal.


The Clipboard plugin stores the last 10 pieces of text copied to the clipboard, selecting an item from the clipboard menu will re-copy the text to the clipboard.
Menu text for the clipboard menu is truncated for convenience but the whole of the copied text is stored.

Open Uri

The Open URI will attempt to open a piece of selected text in the default  application like so:

This would then open "http://keithhedger.hostingsiteforfree.com/index.html" in the default browser, if no default application is available or the selection is not a valid URI nothing will happen, you can also open email addresses in the default email reader or file locations in the default file manager etc.

Building The Plugins

The method of building and installing the plugins is the same for all of them.
You can either do a local install in which case just do:
make install
This will place the plug in in ~/.KKEdit/plugins.
To do a global install use:
make install GLOBAL=1
This will place the files in /usr/share/KKEdit/plugins, you will need to run these commands as root, to stage the install ie for package manages you can use the DESTDIR variable with make install as normal ie:
make install DESTDIR=/tmp/plugins GLOBAL=1
If you want to install to a folder other than /usr you can add the PREFIX variable like so:
make install GLOBAL=1 PREFIX=/opt
You may or may not need to run this as root depending on the install location, non-standard install locations may be a problem, if you find a problem with a non-standard location please let me know.
I would STRONGLY suggest onlt doing a local install of the plugins, unless you are building a package.