[Geany] GITdiff plugin, need help

Yura Siamashka yurand2 at xxxxx
Sat Nov 3 01:51:36 UTC 2007


Hi

Inspired by Enrico plugin wishlist and svn diff plugin, I decided to write 
git (http://git.or.cz/) diff plugin. 

Plugin should works the following way:

On button click (Any idea is it possible to make shortcut to plugin?):

1) If no diff output tab create *GIT-DIFF* tab and place diff there
2) If *GIT-DIFF* already exists, update it's content to latest diff and give focus to it

Well it almost works, exept few things:

1) if I click GITdiff button 2 times and try to close *GIT-DIFF* geany will crash. If I comment
geany_data->sci->set_text line it won't crash, Any idea what I am doing wrong?

2) How can I make tab active after I click GITdiff button? One of idea was always close 
previous *GIT-DIFF* and open new document. But if I try to use documents->remove with index
It close tab with my program I want do make diff to instead of *GIT-DIFF*

Best regards,
Yura Semashko
-------------- next part --------------
Index: plugins/Makefile.am
===================================================================
--- plugins/Makefile.am	(revision 2011)
+++ plugins/Makefile.am	(working copy)
@@ -11,6 +11,7 @@
 htmlchars_la_LDFLAGS     = -module -avoid-version
 export_la_LDFLAGS        = -module -avoid-version
 svndiff_la_LDFLAGS       = -module -avoid-version
+gitdiff_la_LDFLAGS       = -module -avoid-version
 filebrowser_la_LDFLAGS   = -module -avoid-version
 
 if PLUGINS
@@ -21,6 +22,7 @@
 	htmlchars.la \
 	export.la \
 	svndiff.la \
+	gitdiff.la \
 	filebrowser.la
 
 # Plugins not to be installed
@@ -32,6 +34,7 @@
 htmlchars_la_SOURCES     = htmlchars.c
 export_la_SOURCES        = export.c
 svndiff_la_SOURCES       = svndiff.c
+gitdiff_la_SOURCES       = gitdiff.c
 filebrowser_la_SOURCES   = filebrowser.c
 
 demoplugin_la_LIBADD    = $(GTK_LIBS)
@@ -39,6 +42,7 @@
 htmlchars_la_LIBADD     = $(GTK_LIBS)
 export_la_LIBADD        = $(GTK_LIBS)
 svndiff_la_LIBADD       = $(GTK_LIBS)
+gitdiff_la_LIBADD       = $(GTK_LIBS)
 filebrowser_la_LIBADD   = $(GTK_LIBS)
 
 endif # PLUGINS
Index: plugins/gitdiff.c
===================================================================
--- plugins/gitdiff.c	(revision 0)
+++ plugins/gitdiff.c	(revision 0)
@@ -0,0 +1,178 @@
+/*
+ *      svndiff.c - this file is part of Geany, a fast and lightweight IDE
+ *
+ *      Copyright 2007 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
+ *      Copyright 2007 Enrico Tr?ger <enrico.troeger at uvena.de>
+ *      Copyright 2007 Nick Treleaven <nick.treleaven at btinternet.com>
+ *
+ *      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.
+ */
+
+/* GITdiff plugin */
+/* This small plugin uses git to generate a diff against the current
+ * version inside git tree.*/
+
+#include "geany.h"
+#include "support.h"
+#include "plugindata.h"
+#include "document.h"
+#include "filetypes.h"
+#include "utils.h"
+#include "project.h"
+#include "pluginmacros.h"
+
+PluginFields	*plugin_fields;
+GeanyData	*geany_data;
+
+VERSION_CHECK(25)
+
+PLUGIN_INFO(_("gitdiff"), _("Plugin to create a patch of a file against git"), VERSION)
+
+
+static int find_by_filename(const gchar* filename)
+{
+	gint i;
+	for (i = 0; i < doc_array->len; i++)
+	{
+		if ( DOC_IDX_VALID(i) && strcmp(doc_list[i].file_name, filename) == 0)
+			return i;
+	}
+	return -1;
+}
+
+/* name_prefix should be in UTF-8, and can have a path. */
+static void show_output(const gchar *std_output, const gchar *force_encoding)
+{
+	gchar	*text, *detect_enc = NULL;
+	gint idx;
+	gchar	*filename = "*GIT-DIFF*";
+
+	// need to convert input text from the encoding of the original file into
+	// UTF-8 because internally Geany always needs UTF-8
+	if (force_encoding)
+	{
+		text = geany_data->encoding->convert_to_utf8_from_charset(
+			std_output, -1, force_encoding, TRUE);
+	}
+	else
+	{
+		text = geany_data->encoding->convert_to_utf8(std_output, -1, &detect_enc);
+	}
+	if (text)
+	{
+		idx = find_by_filename(filename);
+		if ( idx == -1)
+		{
+			idx = geany_data->document->new_file(filename,
+			geany_data->filetypes[GEANY_FILETYPES_DIFF], text);
+		}
+		else
+		{
+			geany_data->sci->set_text(doc_list[idx].sci, text);
+		}
+				
+		geany_data->document->set_encoding(idx,
+			force_encoding ? force_encoding : detect_enc);
+	}
+	else
+	{
+		ui->set_statusbar(FALSE, _("Could not parse the output of git diff"));
+	}
+	g_free(text);
+	g_free(detect_enc);
+}
+
+
+static gchar *make_diff()
+{
+	gchar	*std_output = NULL;
+	gchar	*std_error = NULL;
+	gint	exit_code;
+	gchar	*command, *text = NULL;
+	gchar *argv[] = {"git", "diff", NULL};
+	gchar *env[] =  {"PAGER=cat", NULL};
+		
+	if (g_spawn_sync(NULL, argv, env,  G_SPAWN_SEARCH_PATH, NULL, NULL, &std_output, &std_error, &exit_code, NULL))
+	{
+		if (! exit_code)
+		{
+			if (NZV(std_output))
+			{
+				text = std_output;
+			}
+			else
+			{
+				ui->set_statusbar(FALSE, _("No changes were made."));
+			}
+		}
+		else
+		{	// GIT returns some error
+			dialogs->show_msgbox(1,
+				_("GIT exited with an error: \n%s."), g_strstrip(std_error));
+		}
+	}
+	else
+	{
+		ui->set_statusbar(FALSE,
+			_("Something went really wrong. Is there any git-binary in your path?"));
+	}
+	g_free(std_error);
+	return text;
+}
+
+/* Callback if menu item for a single file was activated */
+static void gitdiff_activated(GtkMenuItem *menuitem, gpointer gdata)
+{
+	gint	idx;
+	gchar	*text;
+
+	idx = documents->get_cur_idx();
+
+	g_return_if_fail(DOC_IDX_VALID(idx) && doc_list[idx].file_name != NULL);
+
+	if (doc_list[idx].changed)
+	{
+		documents->save_file(idx, FALSE);
+	}
+
+	text = make_diff();
+	if (text)
+		show_output(text, doc_list[idx].encoding);
+	g_free(text);
+}
+
+/* Called by Geany to initialize the plugin */
+void init(GeanyData *data)
+{
+	GtkWidget *gitdiff_item;
+
+	// Add an item to the Tools menu
+	gitdiff_item = gtk_menu_item_new_with_mnemonic(_("_GITdiff"));
+	gtk_widget_show(gitdiff_item);
+	gtk_container_add(GTK_CONTAINER(geany_data->tools_menu), gitdiff_item);
+	g_signal_connect(G_OBJECT(gitdiff_item), "activate", G_CALLBACK(gitdiff_activated), NULL);
+
+	// keep a pointer to the menu item, so we can remove it when the plugin is unloaded
+	plugin_fields->menu_item = gitdiff_item;
+
+}
+
+
+/* Called by Geany before unloading the plugin. */
+void cleanup()
+{
+	// remove the menu item added in init()
+	gtk_widget_destroy(plugin_fields->menu_item);
+}


More information about the Users mailing list