Re: shell output plugin



On 20 Jul 2001 06:38:07 +0200, Roberto Majadas wrote:
> 
> Hi everyone :
> 
> With this plugin we can use command like in a shell . And pipe it with
> the current documents of gide . This only run if you are using
> scintillia component at the moment .

Comments inline in attachment. The plugin also seems to have problems if
you don't have Scinttilla (or and Editor-Buffer capable) default
component for text.

-JP
--
--
=======================================================================
JP Rosevear				jpr arcavia com
Arcavia Software Ltd.			http://www.arcavia.com
(905) 853-7714
Index: plugins/shell-output/shell-output-tool.c
===================================================================
RCS file: shell-output-tool.c
diff -N shell-output-tool.c
--- /dev/null	Tue May  5 16:32:27 1998
+++ shell-output-tool.c	Fri Jul 20 00:23:18 2001
@@ -0,0 +1,564 @@
+/*
+ * gIDE Shell Output plugin
+ *
+ * With this plugin yo can run command like in a shell .
+ * An you can use pipes and pipe gide's documents .
+ *
+ * Roberto Majadas "telemaco" <phoenix nova es>
+ */
+
+#include <config.h>
+
+#include <liboaf/liboaf.h>
+#include <libgide/libgide.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <gdl/GDL.h>
+
+#define SHELL_OUTPUT_COMPONENT_IID "OAFIID:GNOME_Development_Plugin:shelloutput"
+
+#define SHELL_OUTPUT_BUFFER_SIZE 1024
+#define SHELL_OUTPUT_SH_NAME "sh"
+#define SHELL_OUTPUT_SH_PATH "/bin/sh"
+
+typedef struct _shell_output_dialog shell_output_dialog ;
+typedef struct _shell_output_info shell_output_info ;
+
+struct _shell_output_dialog {	
+	GtkWidget *dialog;
+	GtkWidget *dialog_vbox;
+	GtkWidget *vbox;
+	GtkWidget *label1;
+	GtkWidget *table;
+	GtkWidget *label2;
+	GtkWidget *label3;
+	GtkWidget *optionmenu;
+	GtkWidget *optionmenu_menu;
+	GtkWidget *entry;
+	GtkWidget *fileentry1;
+	GtkWidget *combo_entry1;
+	GtkWidget *fileentry2;
+	GtkWidget *combo_entry2;
+	GtkWidget *dialog_action_area;
+	GtkWidget *ok_button;
+	GtkWidget *cancel_button;	
+};
+
+struct _shell_output_info {
+	GNOME_Development_Environment_DocumentManager_DocumentList *doclist ;
+	GNOME_Development_Environment_Document doc ;
+	gchar *work_directory;
+	gchar *temp_file_name;	
+};
+
+static shell_output_dialog *sod ;
+static shell_output_info *soi ;
+static GideTool* shell_output_tool ;
+
+
+/* Shell Output prototipes */
+
+static void shell_output (GtkWidget *widget, gpointer data);
+static void shell_output_create_dialog_table ();
+static void shell_output_create_dialog ();
+static void shell_output_add_dialog_options ();
+static void shell_output_activate_option (GtkWidget *widget, gpointer data);
+static void shell_output_close_dialog (GtkWidget *widget, gpointer data);
+static void shell_output_popen (GString *buffer_to_pipe, gchar *command);
+GString * shell_output_data_for_pipe () ;
+static void shell_output_command_run (GtkWidget *widget, gpointer data);
+static void shell_output_open_output_file (gchar *file);
+static void shell_output_error_box (gchar *message);
+gboolean command_out_cb (GIOChannel *chan, GIOCondition cond, gpointer data);
+
+static void
+shell_output_create_dialog_table ()
+{
+	gchar *temp_file_name = NULL ;
+	
+	sod->table = gtk_table_new (3, 2, FALSE);
+	gtk_box_pack_end (GTK_BOX (sod->vbox), sod->table, FALSE, FALSE, 0);
+	gtk_table_set_col_spacings (GTK_TABLE (sod->table), 5);
+	sod->label2 = gtk_label_new (_("Work directory"));
+	gtk_table_attach (GTK_TABLE (sod->table), sod->label2, 0, 1, 1, 2,
+				   (GtkAttachOptions) (GTK_FILL),
+				   (GtkAttachOptions) (0), 0, 0);
+	gtk_widget_set_usize (sod->label2, 175, -2);
+	gtk_misc_set_alignment (GTK_MISC (sod->label2), 0, 0.5);
+	sod->label3 = gtk_label_new (_("Temporal output file"));
+	gtk_table_attach (GTK_TABLE (sod->table), sod->label3, 0, 1, 2, 3,
+				   (GtkAttachOptions) (GTK_FILL),
+				   (GtkAttachOptions) (0), 0, 0);
+	gtk_widget_set_usize (sod->label3, 175, -2);

Setting the usize of a widget (especially a label) because of
variances in different languages, fonts, etc.  You also don't need to
track label3 in the structure if you don't need it later, the widget
will be destroyed when the parent is.  You can just reused a generic
label variable inside this function.

+	gtk_misc_set_alignment (GTK_MISC (sod->label3), 0, 0.5);	
+	sod->optionmenu = gtk_option_menu_new ();
+	gtk_table_attach (GTK_TABLE (sod->table), sod->optionmenu, 0, 1, 0, 1,
+				   (GtkAttachOptions) (GTK_FILL),
+				   (GtkAttachOptions) (0), 0, 0);
+	gtk_widget_set_usize (sod->optionmenu, 175, 25);
+	sod->optionmenu_menu = gtk_menu_new ();
+	gtk_option_menu_set_menu (GTK_OPTION_MENU (sod->optionmenu), sod->optionmenu_menu);
+	sod->entry = gtk_entry_new ();
+	gtk_table_attach (GTK_TABLE (sod->table), sod->entry, 1, 2, 0, 1,
+				   (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+				   (GtkAttachOptions) (0), 0, 0);	
+	sod->fileentry1 = gnome_file_entry_new (NULL, NULL);
+	gtk_table_attach (GTK_TABLE (sod->table), sod->fileentry1, 1, 2, 1, 2,
+				   (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+				   (GtkAttachOptions) (0), 0, 0);
+	gnome_file_entry_set_directory (GNOME_FILE_ENTRY (sod->fileentry1), TRUE);
+	gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (sod->fileentry1),
+								g_get_home_dir ());
+	sod->combo_entry1 = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (sod->fileentry1));
+	gtk_entry_set_text (GTK_ENTRY(sod->combo_entry1),g_get_home_dir ()); 
+	sod->fileentry2 = gnome_file_entry_new (NULL, NULL);
+	gtk_table_attach (GTK_TABLE (sod->table), sod->fileentry2, 1, 2, 2, 3,
+				   (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+				   (GtkAttachOptions) (0), 0, 0);
+	gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (sod->fileentry2),
+								g_get_tmp_dir ());
+	sod->combo_entry2 = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (sod->fileentry2));
+		
+	gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (sod->fileentry2),
+								g_get_tmp_dir ());
+	gtk_entry_set_text (GTK_ENTRY(sod->combo_entry2), tempnam (g_get_tmp_dir (),"gide-"));
+
+	g_free (temp_file_name);
+}
+
+static void
+shell_output_add_dialog_options ()
+{
+
+	GNOME_Development_Environment_DocumentManager docman;
+	GNOME_Development_Environment_Document var_doc ;
+	CORBA_Environment ev;
+	GtkWidget *optionmenu_menu_item ;
+	gchar *moniker;
+	gchar *cat_option;
+	gchar *filename;
+	gint i ;
+
+	soi->doc = NULL ; /* inicialization of this */
+		
+	optionmenu_menu_item = gtk_menu_item_new_with_label (_("run command"));	
+	gtk_menu_append (GTK_MENU (sod->optionmenu_menu), optionmenu_menu_item);
+	gtk_signal_connect (GTK_OBJECT (optionmenu_menu_item), "activate",
+					GTK_SIGNAL_FUNC (shell_output_activate_option),NULL);	
+
+	CORBA_exception_init (&ev);
+	moniker = g_strdup_printf ("gide:%s!DocumentManager", shell_output_tool->shell_id);
+	docman = bonobo_get_object (moniker,
+						   "IDL:GNOME/Development/Environment/DocumentManager:1.0",
+						   &ev);
+	g_free (moniker);
+	if (ev._major != CORBA_NO_EXCEPTION && !CORBA_Object_is_nil (soi->doc, &ev))
+		return ;
+   
+	soi->doclist = GNOME_Development_Environment_DocumentManager_getOpenFiles (docman,&ev);
+	if (ev._major != CORBA_NO_EXCEPTION)
+		return ;
+
+
+	for (i=0 ; i< soi->doclist->_length ; i++)
+	{		
+		var_doc = soi->doclist->_buffer[i] ;
+	
+		filename = g_strdup (GNOME_Development_Environment_Document_getFilename (var_doc,&ev));
+		if (ev._major != CORBA_NO_EXCEPTION)
+		return ;				
+
+		cat_option = g_strdup_printf ("cat %s |", g_basename(filename));
+	    		
+		optionmenu_menu_item = gtk_menu_item_new_with_label (cat_option);
+		gtk_menu_append (GTK_MENU (sod->optionmenu_menu), optionmenu_menu_item);
+		gtk_signal_connect (GTK_OBJECT (optionmenu_menu_item), "activate",
+						GTK_SIGNAL_FUNC (shell_output_activate_option),
+						soi->doclist->_buffer[i]);
+		g_free(filename);
+		g_free(cat_option);
+	}
+
+	gtk_option_menu_set_history (GTK_OPTION_MENU(sod->optionmenu), 0);
+
+	bonobo_object_release_unref(docman, &ev);
+
+	CORBA_exception_free(&ev);		
+}
+
+
+static void
+shell_output_create_dialog ()
+{		
+	sod->dialog = gnome_dialog_new (NULL, NULL);
+	gtk_widget_set_usize (sod->dialog, 450, 200);
+	sod->dialog_vbox = GNOME_DIALOG (sod->dialog)->vbox;
+	sod->vbox = gtk_vbox_new (FALSE, 0);
+	gtk_box_pack_start (GTK_BOX (sod->dialog_vbox), sod->vbox, TRUE, FALSE, 0);
+	sod->label1 = gtk_label_new (_("Please , insert command that you want to run\nRemember , you can pipe documents and commands like in a shell\n"));
+	gtk_label_set_justify (GTK_LABEL(sod->label1), GTK_JUSTIFY_LEFT);
+	gtk_box_pack_start (GTK_BOX (sod->vbox), sod->label1, FALSE, FALSE, 0);
+
+	shell_output_create_dialog_table ();
+	
+	sod->dialog_action_area = GNOME_DIALOG (sod->dialog)->action_area;
+	gtk_button_box_set_layout (GTK_BUTTON_BOX (sod->dialog_action_area), GTK_BUTTONBOX_END);
+	gtk_button_box_set_spacing (GTK_BUTTON_BOX (sod->dialog_action_area), 8);
+	gnome_dialog_append_button (GNOME_DIALOG (sod->dialog), GNOME_STOCK_BUTTON_OK);
+	sod->ok_button = GTK_WIDGET (g_list_last (GNOME_DIALOG (sod->dialog)->buttons)->data);
+	GTK_WIDGET_SET_FLAGS (sod->ok_button, GTK_CAN_DEFAULT);
+	gnome_dialog_append_button (GNOME_DIALOG (sod->dialog), GNOME_STOCK_BUTTON_CANCEL);
+	sod->cancel_button = GTK_WIDGET (g_list_last (GNOME_DIALOG (sod->dialog)->buttons)->data);
+	GTK_WIDGET_SET_FLAGS (sod->cancel_button, GTK_CAN_DEFAULT);

You can add all these buttons during the gnome_dialog_new call.  It
will set all the spacing and such properly itself.

+	gtk_signal_connect (GTK_OBJECT (sod->dialog), "delete_event",
+					GTK_SIGNAL_FUNC  (shell_output_close_dialog), NULL);
+	gtk_signal_connect (GTK_OBJECT (sod->cancel_button), "pressed",
+					GTK_SIGNAL_FUNC (shell_output_close_dialog), NULL);
+	gtk_signal_connect (GTK_OBJECT (sod->ok_button), "pressed",
+					GTK_SIGNAL_FUNC (shell_output_command_run), NULL);

You can use gnome_dialog_button_connect here.

+	shell_output_add_dialog_options ();
+	gtk_widget_show_all (sod->dialog);
+}
+
+
+static void
+shell_output_activate_option (GtkWidget *widget, gpointer data)
+{
+	soi->doc = data ;
+}
+
+gboolean
+command_out_cb (GIOChannel *chan, GIOCondition cond, gpointer data)
+{
+	
+	FILE *temp_file;
+	gchar c;
+	gint read = 1;
+
+	temp_file = fopen (soi->temp_file_name, "w");
+	
+	while (read > 0)
+	{
+		g_io_channel_read (chan, &c, 1, &read);		
+		if (read > 0)
+		{			
+			fputc (c, temp_file);
+		}		
+	}
+	
+	fclose (temp_file);
+
+	shell_output_open_output_file (soi->temp_file_name);
+	g_free (soi);
+
+	return TRUE;
+}
+
+GString *
+shell_output_data_for_pipe ()
+{	
+	GNOME_Development_EditorBuffer	buffer;
+	GNOME_Development_EditorBuffer_iobuf   *iobuf;
+	CORBA_Environment ev;
+	glong length;
+	GString *result = g_string_new (NULL);
+	
+
+	if (soi->doc == NULL)
+	{
+		return result;
+	}
+	else		
+	{
+		CORBA_exception_init(&ev);
+						
+		buffer = GNOME_Development_Environment_Document_getEditorInterface(
+			soi->doc, "IDL:GNOME/Development/EditorBuffer:1.0", &ev);				
+		if(CORBA_Object_is_nil(buffer, &ev))
+		{
+			g_print("not an editor buffer\n");
+			CORBA_exception_free(&ev);
+			return NULL;			
+		}		
+		length = GNOME_Development_EditorBuffer_getLength (buffer, &ev);
+		if (length == 0)
+			return result ;
+		GNOME_Development_EditorBuffer_getChars (buffer, 0, length, &iobuf, &ev);
+		result = g_string_append (result, g_strndup (iobuf->_buffer, iobuf->_length));

g_strndup allocates a new string which must be freed.

+		CORBA_free (iobuf);
+		bonobo_object_release_unref (buffer, &ev);
+
+		CORBA_exception_free (&ev);
+		
+		return result;
+	}
+}
+
+static void
+shell_output_command_run (GtkWidget *widget, gpointer data)
+{
+	
+	gchar    *command_string = NULL;	
+	GString  *buffer_to_pipe = NULL;
+		
+	command_string = gtk_entry_get_text (GTK_ENTRY (sod->entry));
+
+	soi->work_directory = g_strdup (gnome_file_entry_get_full_path
+						  (GNOME_FILE_ENTRY (sod->fileentry1),
+						   TRUE));
+	soi->temp_file_name = g_strdup (gnome_file_entry_get_full_path
+							  (GNOME_FILE_ENTRY (sod->fileentry2),
+							   FALSE));
+    	if (soi->work_directory == NULL)
+	{
+		shell_output_error_box (_("There aren't any work directory"));
+		return;
+	}
+	
+	if (soi->temp_file_name == NULL)
+	{
+		shell_output_error_box (_("There aren't any temporal file"));
+		return;
+	}
+	
+	if (command_string == NULL || (strlen (command_string) == 0))
+	{
+		shell_output_error_box (_("There aren't any command"));
+		return;
+	}
+		
+	buffer_to_pipe = shell_output_data_for_pipe ();
+	chdir (soi->work_directory);
+	
+	shell_output_popen (buffer_to_pipe, command_string);
+	
+	gnome_dialog_close (GNOME_DIALOG (sod->dialog));
+	g_free (sod);
+	
+}
+
+static void
+shell_output_popen (GString *buffer_to_pipe, gchar *command)
+{
+	FILE     *stream ;
+	GIOChannel *chan_out;
+	gint     fdpipe [2];
+	gint     fdpipe2 [2];
+	gchar    *arg[4] ;
+	gchar    *command_to_run;
+	gint     pid;
+	
+	if (pipe (fdpipe) == -1)	
+		return;
+
+	if (pipe (fdpipe2) == -1)
+		return;
+
+	if (buffer_to_pipe->len > 0)
+		command_to_run = g_strdup_printf ("cat | %s", command);
+	else
+		command_to_run = g_strdup_printf (" %s ", command);
+	
+	pid = fork();
+	if (pid == 0)
+	{
+		dup2(fdpipe[0], 0);
+		close (fdpipe[0]);
+		close (fdpipe[1]);
+		dup2(fdpipe2[1], 1);
+		close (fdpipe2[0]);
+		close (fdpipe2[1]);
+
+		chan_out = g_io_channel_unix_new (fdpipe2[0]);
+		g_io_add_watch (chan_out, G_IO_IN, command_out_cb, NULL);	
+		
+		arg[0]=SHELL_OUTPUT_SH_NAME;
+		arg[1]="-c";
+		arg[2]=command_to_run;
+		arg[3]=NULL;
+		
+		execvp (SHELL_OUTPUT_SH_PATH, arg);
+
+		g_warning ("A undetermined PIPE problem occurred");
+		_exit (1);
+	}
+	else
+	{
+		close (fdpipe[0]);
+		close (fdpipe2[1]);
+		
+		chan_out = g_io_channel_unix_new (fdpipe2[0]);
+		g_io_add_watch (chan_out, G_IO_IN, command_out_cb, NULL); 
+
+		if (buffer_to_pipe->len > 0)
+		{
+			fcntl (fdpipe[1], F_SETFD, FD_CLOEXEC);
+			stream = fdopen (fdpipe[1], "w");
+			fprintf (stream, buffer_to_pipe->str);
+			fclose (stream);
+		}		
+		g_string_free ( buffer_to_pipe, TRUE ) ;			
+	}
+}
+
+static void
+shell_output_open_output_file (gchar *file)
+{
+	GNOME_Development_Environment_DocumentManager docman;
+	GNOME_Development_Environment_Document var_doc ;
+	CORBA_Environment ev;
+	gchar *moniker = NULL ;
+	
+	CORBA_exception_init (&ev);
+
+	moniker = g_strdup_printf ("gide:%s!DocumentManager", shell_output_tool->shell_id);
+	docman = bonobo_get_object (moniker,
+						   "IDL:GNOME/Development/Environment/DocumentManager:1.0",
+						   &ev);
+	g_free (moniker);
+	var_doc = GNOME_Development_Environment_DocumentManager_openFile (docman, file, &ev);
+	bonobo_object_release_unref (docman, &ev);
+
+	CORBA_exception_free (&ev);
+
+}
+
+static void
+shell_output_error_box (gchar *message)
+{
+	 GtkWidget *messagebox;
+	 GtkWidget *dialog_vbox;
+	 GtkWidget *ok_button;
+	 GtkWidget *dialog_action_area;	 	
+
+	 messagebox = gnome_message_box_new (message, GNOME_MESSAGE_BOX_WARNING,
+								  GNOME_STOCK_BUTTON_OK, NULL);
+	 gtk_container_remove (GTK_CONTAINER (GNOME_DIALOG (messagebox)->action_area),
+					   GNOME_DIALOG (messagebox)->buttons->data);
+	 GNOME_DIALOG (messagebox)->buttons = NULL;	 
+	 gtk_window_set_policy (GTK_WINDOW (messagebox), FALSE, FALSE, FALSE);
+	 dialog_vbox = GNOME_DIALOG (messagebox)->vbox;	 
+	 gnome_dialog_append_button (GNOME_DIALOG (messagebox), GNOME_STOCK_BUTTON_OK);
+	 ok_button = GTK_WIDGET (g_list_last (GNOME_DIALOG (messagebox)->buttons)->data);
+	 GTK_WIDGET_SET_FLAGS (ok_button, GTK_CAN_DEFAULT);
+	 dialog_action_area = GNOME_DIALOG (messagebox)->action_area;
+	 gtk_widget_show_all (messagebox);
+}

This is easier to do with a gnome_error_dialog
(http://developer.gnome.org/doc/API/libgnomeui/gnomeui-gnome-dialog-util.html)

+
+static void
+shell_output_close_dialog (GtkWidget *widget, gpointer data)
+{
+ 	gnome_dialog_close (GNOME_DIALOG (sod->dialog));
+ 	g_free (sod);
+ 	g_free (soi);
+}

You can't just free the structures, you need to free any memory
pointed to by pointers in the struct, like work_directory.

+static void
+shell_output(
+	GtkWidget*			widget,
+	gpointer			data
+)
+{
+	shell_output_tool = GIDE_TOOL(data);	
+
+	sod = g_new (shell_output_dialog, 1);
+	soi = g_new (shell_output_info, 1);
+		
+	shell_output_create_dialog ();
+		
+}
+
+/*
+ * Define the verbs in this plugin
+ */
+static BonoboUIVerb verbs[] = {
+	BONOBO_UI_UNSAFE_VERB("ShellOutput", shell_output),
+	BONOBO_UI_VERB_END
+};
+
+/*
+ * Boilerplate initialization function
+ */
+static gboolean
+impl_init(
+	GideTool*			tool,
+	gpointer			closure
+)
+{
+	BonoboUIComponent*		uic;
+	CORBA_Environment		ev;
+
+	g_return_val_if_fail(tool != NULL, FALSE);
+	g_return_val_if_fail(GIDE_IS_TOOL(tool), FALSE);
+
+	CORBA_exception_init(&ev);
+
+	uic = bonobo_ui_component_new("gide-shelloutput-plugin");
+	bonobo_ui_component_set_container(uic, tool->ui_container);
+	bonobo_ui_util_set_ui(uic, GIDE_DATADIR, "gide-shelloutput-plugin.xml",
+		"gide-shelloutput-plugin");
+
+	bonobo_ui_component_add_verb_list_with_data(uic, verbs, tool);
+
+	CORBA_exception_free(&ev);
+
+	return TRUE;
+}
+
+/*
+ * Boilerplace cleanup function
+ */
+static void
+impl_cleanup(
+	GideTool*			tool,
+	gpointer			closure
+)
+{
+}
+
+/*
+ * Boilerplate creation function
+ */
+static CORBA_Object
+make_object(
+	PortableServer_POA		poa,
+	const char*			iid,
+	gpointer			impl_ptr,
+	CORBA_Environment*		ev
+)
+{
+	GideTool*			tool;
+
+	tool = gide_tool_new(impl_init, impl_cleanup, NULL);
+
+	oaf_plugin_use(poa, impl_ptr);
+
+	return bonobo_object_corba_objref(BONOBO_OBJECT(tool->props));
+}
+
+/*
+ * List of plugins
+ */
+static const OAFPluginObject plugin_list[] =
+{
+	{
+		SHELL_OUTPUT_COMPONENT_IID,
+		make_object
+	},
+	{
+		NULL
+	}
+};
+
+/*
+ * Plugin description
+ */
+const OAFPlugin OAF_Plugin_info = {
+	plugin_list,
+	"gIDE Shell Output Plugin"
+};


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]