[geany/geany-plugins] f0fa9e: lineoperations: added selection support

Sylvan Mostert git-noreply at xxxxx
Tue Jan 3 21:46:06 UTC 2017


Branch:      refs/heads/master
Author:      Sylvan Mostert <smostert.dev at gmail.com>
Committer:   Sylvan Mostert <smostert.dev at gmail.com>
Date:        Fri, 09 Sep 2016 05:45:32 UTC
Commit:      f0fa9e8c150b36ae6b1be241299ad70266cf5367
             https://github.com/geany/geany-plugins/commit/f0fa9e8c150b36ae6b1be241299ad70266cf5367

Log Message:
-----------
lineoperations: added selection support

If there is a selection, the Operation will be applied to the lines in
the selection, and if there is no selection, the Operation will be
applied to the whole file.

Adjusted `rmemtyln` and `rmwhspln` to accept first line and end line for
selection.


Modified Paths:
--------------
    lineoperations/src/linefunctions.c
    lineoperations/src/linefunctions.h
    lineoperations/src/lineoperations.c

Modified: lineoperations/src/linefunctions.c
219 lines changed, 62 insertions(+), 157 deletions(-)
===================================================================
@@ -22,21 +22,6 @@
 #include "linefunctions.h"
 
 
-/* altered from geany/src/editor.c, ensure new line at file end */
-static void ensure_final_newline(GeanyEditor *editor, gint max_lines)
-{
-	gint end_document       = sci_get_position_from_line(editor->sci, max_lines);
-	gboolean append_newline = end_document >
-					sci_get_position_from_line(editor->sci, max_lines - 1);
-
-	if (append_newline)
-	{
-		const gchar *eol = editor_get_eol_char(editor);
-		sci_insert_text(editor->sci, end_document, eol);
-	}
-}
-
-
 /* comparison function to be used in qsort */
 static gint compare_asc(const void * a, const void * b)
 {
@@ -52,235 +37,155 @@ static gint compare_desc(const void * a, const void * b)
 
 
 /* Remove Duplicate Lines, sorted */
-void rmdupst(GeanyDocument *doc) {
-	gint  total_num_chars;  /* number of characters in the document */
-	gint  total_num_lines;  /* number of lines in the document */
-	gchar **lines;          /* array to hold all lines in the document */
-	gchar *new_file;        /* *final* string to replace current document */
-	gchar *nf_end;          /* points to end of new_file */
-	gchar *lineptr;         /* temporary line pointer */
-	gint  i;                /* iterator */
-
-	total_num_chars = sci_get_length(doc->editor->sci);
-	total_num_lines = sci_get_line_count(doc->editor->sci);
-	lines           = g_malloc(sizeof(gchar *) * total_num_lines);
-	new_file        = g_malloc(sizeof(gchar)   * (total_num_chars+1));
-	new_file[0]     = '\0';
-	nf_end          = new_file;
-	lineptr         = (gchar *)"";
-
-
-	/* if file is not empty, ensure that the file ends with newline */
-	if(total_num_lines != 1)
-		ensure_final_newline(doc->editor, total_num_lines);
-
-	/* copy *all* lines into **lines array */
-	for(i = 0; i < total_num_lines; i++)
-		lines[i] = sci_get_line(doc->editor->sci, i);
+void
+rmdupst(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file)
+{
+	gchar *nf_end  = new_file;    /* points to last char of new_file */
+	gchar *lineptr = (gchar *)""; /* temporary line pointer */
+	gint  i        = 0;           /* iterator */
 
 	/* sort **lines ascending */
-	qsort(lines, total_num_lines, sizeof(gchar *), compare_asc);
+	qsort(lines, num_lines, sizeof(gchar *), compare_asc);
 
 	/* loop through **lines, join first occurances into one str (new_file) */
-	for(i = 0; i < total_num_lines; i++)
+	for(i = 0; i < num_lines; i++)
+	{
 		if(strcmp(lines[i], lineptr) != 0)
 		{
 			lineptr  = lines[i];
 			nf_end   = g_stpcpy(nf_end, lines[i]);
 		}
-
-	/* set new document */
-	sci_set_text(doc->editor->sci, new_file);
-
-	/* free used memory */
-	for(i = 0; i < total_num_lines; i++)
-		g_free(lines[i]);
-	g_free(lines);
-	g_free(new_file);
+	}
 }
 
 
 /* Remove Duplicate Lines, ordered */
-void rmdupln(GeanyDocument *doc) {
-	gint  total_num_chars;  /* number of characters in the document */
-	gint  total_num_lines;  /* number of lines in the document */
-	gchar **lines;          /* array to hold all lines in the document */
-	gchar *new_file;        /* *final* string to replace current document */
-	gchar *nf_end;          /* points to end of new_file */
-	gint  i;                /* iterator */
-	gint  j;                /* iterator */
-	gboolean *to_remove;    /* flag to 'mark' which lines to remove */
-
-	total_num_chars = sci_get_length(doc->editor->sci);
-	total_num_lines = sci_get_line_count(doc->editor->sci);
-	lines           = g_malloc(sizeof(gchar *) * total_num_lines);
-	new_file        = g_malloc(sizeof(gchar) * (total_num_chars+1));
-	new_file[0]     = '\0';
-	nf_end          = new_file;
-
-
-	/* if file is not empty, ensure that the file ends with newline */
-	if(total_num_lines != 1)
-		ensure_final_newline(doc->editor, total_num_lines);
-
-	/* copy *all* lines into **lines array */
-	for(i = 0; i < total_num_lines; i++)
-		lines[i] = sci_get_line(doc->editor->sci, i);
+void
+rmdupln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file)
+{
+	gchar *nf_end  = new_file;  /* points to last char of new_file */
+	gint  i        = 0;         /* iterator */
+	gint  j        = 0;         /* iterator */
+	gboolean *to_remove = NULL; /* flag to 'mark' which lines to remove */
+
 
 	/* allocate and set *to_remove to all FALSE
 	 * to_remove[i] represents whether lines[i] should be removed  */
-	to_remove = g_malloc(sizeof(gboolean) * total_num_lines);
-	for(i = 0; i < (total_num_lines); i++)
+	to_remove = g_malloc(sizeof(gboolean) * num_lines);
+	for(i = 0; i < (num_lines); i++)
 		to_remove[i] = FALSE;
 
 	/* find which **lines are duplicate, and mark them as duplicate */
-	for(i = 0; i < total_num_lines; i++)	/* loop through **lines */
+	for(i = 0; i < num_lines; i++)	/* loop through **lines */
+	{
 		/* make sure that the line is not already duplicate */
 		if(!to_remove[i])
+		{
 			/* find the rest of same lines */
-			for(j = (i+1); j < total_num_lines; j++)
+			for(j = (i+1); j < num_lines; j++)
+			{
 				if(!to_remove[j] && strcmp(lines[i], lines[j]) == 0)
 					to_remove[j] = TRUE;   /* line is duplicate, mark to remove */
+			}
+		}
+	}
 
 	/* copy **lines into 'new_file' if it is not FALSE(not duplicate) */
-	for(i = 0; i < total_num_lines; i++)
+	for(i = 0; i < num_lines; i++)
 		if(!to_remove[i])
 			nf_end   = g_stpcpy(nf_end, lines[i]);
 
-	/* set new document */
-	sci_set_text(doc->editor->sci, new_file);
-
 	/* free used memory */
-	for(i = 0; i < total_num_lines; i++)
-		g_free(lines[i]);
-	g_free(lines);
-	g_free(new_file);
 	g_free(to_remove);
 }
 
 
 /* Remove Unique Lines */
-void rmunqln(GeanyDocument *doc) {
-	gint total_num_chars;   /* number of characters in the document */
-	gint total_num_lines;   /* number of lines in the document */
-	gchar **lines;          /* array to hold all lines in the document */
-	gchar *new_file;        /* *final* string to replace current document */
-	gchar *nf_end;          /* points to end of new_file */
-	gint i;                 /* iterator */
-	gint j;                 /* iterator */
-	gboolean *to_remove;    /* to 'mark' which lines to remove */
-
-	total_num_chars = sci_get_length(doc->editor->sci);
-	total_num_lines = sci_get_line_count(doc->editor->sci);
-	lines           = g_malloc(sizeof(gchar *) * total_num_lines);
-	new_file        = g_malloc(sizeof(gchar) * (total_num_chars+1));
-	new_file[0]     = '\0';
-	nf_end          = new_file;
-
-
-	/* if file is not empty, ensure that the file ends with newline */
-	if(total_num_lines != 1)
-		ensure_final_newline(doc->editor, total_num_lines);
-
-	/* copy *all* lines into **lines array */
-	for(i = 0; i < total_num_lines; i++)
-		lines[i] = sci_get_line(doc->editor->sci, i);
+void
+rmunqln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file)
+{
+	gchar *nf_end = new_file;   /* points to last char of new_file */
+	gint i        = 0;          /* iterator */
+	gint j        = 0;          /* iterator */
+	gboolean *to_remove = NULL; /* to 'mark' which lines to remove */
 
 
 	/* allocate and set *to_remove to all TRUE
 	 * to_remove[i] represents whether lines[i] should be removed */
-	to_remove = g_malloc(sizeof(gboolean) * total_num_lines);
-	for(i = 0; i < total_num_lines; i++)
+	to_remove = g_malloc(sizeof(gboolean) * num_lines);
+	for(i = 0; i < num_lines; i++)
 		to_remove[i] = TRUE;
 
 	/* find all unique lines and set them to FALSE (not to be removed) */
-	for(i = 0; i < total_num_lines; i++)
+	for(i = 0; i < num_lines; i++)
 		/* make sure that the line is not already determined to be unique */
 		if(to_remove[i])
-			for(j = (i+1); j < total_num_lines; j++)
+			for(j = (i+1); j < num_lines; j++)
 				if(to_remove[j] && strcmp(lines[i], lines[j]) == 0)
 				{
 					to_remove[i] = FALSE;
 					to_remove[j] = FALSE;
 				}
 
 	/* copy **lines into 'new_file' if it is not FALSE(not duplicate) */
-	for(i = 0; i < total_num_lines; i++)
+	for(i = 0; i < num_lines; i++)
 		if(!to_remove[i])
 			nf_end = g_stpcpy(nf_end, lines[i]);
 
-	/* set new document */
-	sci_set_text(doc->editor->sci, new_file);
-
 	/* free used memory */
-	for(i = 0; i < total_num_lines; i++)
-		g_free(lines[i]);
-	g_free(lines);
-	g_free(new_file);
 	g_free(to_remove);
 }
 
 
 /* Remove Empty Lines */
-void rmemtyln(GeanyDocument *doc) {
-	gint  total_num_lines;    /* number of lines in the document */
-	gint  i;                  /* iterator */
-
-	total_num_lines = sci_get_line_count(doc->editor->sci);
-
-	sci_start_undo_action(doc->editor->sci);
+void
+rmemtyln(GeanyDocument *doc, gint line_num, gint end_line_num)
+{
 
-	for(i = 0; i < total_num_lines; i++)    /* loop through opened doc */
+	while(line_num <= end_line_num)    /* loop through lines */
 	{
+		/* check if the first posn of the line is also the end of line posn */
 		if(sci_get_position_from_line(doc->editor->sci, i) ==
 		   sci_get_line_end_position(doc->editor->sci, i))
 		{
 			scintilla_send_message(doc->editor->sci,
-								   SCI_DELETERANGE,
-								   sci_get_position_from_line(doc->editor->sci, i),
-								   sci_get_line_length(doc->editor->sci, i));
-			total_num_lines--;
-			i--;
+					   SCI_DELETERANGE,
+					   sci_get_position_from_line(doc->editor->sci, line_num),
+					   sci_get_line_length(doc->editor->sci, line_num));
+			line_num--;
+			end_line_num--;
 		}
 	}
-
-	sci_end_undo_action(doc->editor->sci);
 }
 
 
 /* Remove Whitespace Lines */
-void rmwhspln(GeanyDocument *doc) {
-	gint total_num_lines;  /* number of lines in the document */
-	gint indent;
-	gint i;                /* iterator */
-
-	total_num_lines = sci_get_line_count(doc->editor->sci);
-
-	sci_start_undo_action(doc->editor->sci);
+void
+rmwhspln(GeanyDocument *doc, gint line_num, gint end_line_num)
+{
+	gint indent;                       /* indent position */
 
-	for(i = 0; i < total_num_lines; i++)    /* loop through opened doc */
+	while(line_num <= end_line_num)    /* loop through lines */
 	{
 		indent = scintilla_send_message(doc->editor->sci,
 									SCI_GETLINEINDENTPOSITION,
 									i, 0);
 
+		/* check if the posn of indentation is also the end of line posn */
 		if(indent -
 		   sci_get_position_from_line(doc->editor->sci, i) ==
 		   sci_get_line_end_position(doc->editor->sci, i)-
 		   sci_get_position_from_line(doc->editor->sci, i))
 		{
 			scintilla_send_message(doc->editor->sci,
-								   SCI_DELETERANGE,
-								   sci_get_position_from_line(doc->editor->sci, i),
-								   sci_get_line_length(doc->editor->sci, i));
-			total_num_lines--;
-			i--;
+					   SCI_DELETERANGE,
+					   sci_get_position_from_line(doc->editor->sci, line_num),
+					   sci_get_line_length(doc->editor->sci, line_num));
+			line_num--;
+			end_line_num--;
 		}
 
 	}
-
-
-	sci_end_undo_action(doc->editor->sci);
 }
 
 


Modified: lineoperations/src/linefunctions.h
25 lines changed, 17 insertions(+), 8 deletions(-)
===================================================================
@@ -1,5 +1,6 @@
 /*
- *      linefunctions.h - Line operations, remove duplicate lines, empty lines, lines with only whitespace, sort lines.
+ *      linefunctions.h - Line operations, remove duplicate lines, empty lines,
+ *                        lines with only whitespace, sort lines.
  *
  *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.com>
  *
@@ -30,29 +31,37 @@
 
 
 /* Remove Duplicate Lines, sorted */
-void rmdupst(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
+void
+rmdupst(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
 
 
 /* Remove Duplicate Lines, ordered */
-void rmdupln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
+void
+rmdupln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
 
 
 /* Remove Unique Lines */
-void rmunqln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
+void
+rmunqln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
 
 
 /* Remove Empty Lines */
-void rmemtyln(GeanyDocument *doc, gint num_lines);
+void
+rmemtyln(GeanyDocument *doc, gint line_num, gint end_line_num);
 
 
 /* Remove Whitespace Lines */
-void rmwhspln(GeanyDocument *doc, gint num_lines);
+void
+rmwhspln(GeanyDocument *doc, gint line_num, gint end_line_num);
 
 
 /* Sort Lines Ascending */
-void sortlinesasc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
+void
+sortlnsasc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
+
 
 /* Sort Lines Descending */
-void sortlinesdesc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
+void
+sortlndesc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
 
 #endif


Modified: lineoperations/src/lineoperations.c
148 lines changed, 119 insertions(+), 29 deletions(-)
===================================================================
@@ -1,5 +1,6 @@
 /*
- *      lineoperations.c - Line operations, remove duplicate lines, empty lines, lines with only whitespace, sort lines.
+ *      lineoperations.c - Line operations, remove duplicate lines, empty lines,
+ *                         lines with only whitespace, sort lines.
  *
  *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.com>
  *
@@ -30,12 +31,74 @@ static GtkWidget *main_menu_item = NULL;
 
 
 
+/* represents lines that will have Operation applied to */
+struct lo_lines {
+	gboolean is_selection;
+	gint start_posn_line;
+	gint end_posn_line;
+};
+
+
+/* select lines in document based on lo_lines struct parameter */
+static void
+select_lines(GeanyDocument *doc, struct lo_lines sel)
+{
+	/* set the selection to beginning of first line */
+	sci_set_selection_start(doc->editor->sci,
+			sci_get_position_from_line(doc->editor->sci, sel.start_posn_line));
+
+	/* set the selection to end of last line */
+	sci_set_selection_end(doc->editor->sci,
+			sci_get_line_end_position(doc->editor->sci, sel.end_posn_line) +
+									 editor_get_eol_char_len(doc->editor));
+}
+
+
+/* get lo_lines struct based off of document */
+static struct lo_lines
+get_current_sel_lines(GeanyDocument *doc)
+{
+	struct lo_lines sel = { 0, 0 };
+	gint start_posn     = 0;        /* position of selection start */
+	gint end_posn       = 0;        /* position of selection end   */
+
+	/* check for selection */
+	if(sci_has_selection(doc->editor->sci))
+	{
+		/* get the start and end positions */
+		start_posn = sci_get_selection_start(doc->editor->sci);
+		end_posn   = sci_get_selection_end  (doc->editor->sci);
+
+		/* get the line number of those positions */
+		sel.start_posn_line = scintilla_send_message(doc->editor->sci,
+									SCI_LINEFROMPOSITION,
+									start_posn, 0);
+
+		sel.end_posn_line   = scintilla_send_message(doc->editor->sci,
+									SCI_LINEFROMPOSITION,
+									end_posn, 0);
+
+		sel.is_selection = TRUE;
+	}
+	else
+	{
+		/* if there is no selection, start at first line */
+		sel.start_posn_line = 0;
+		/* and end at last one */
+		sel.end_posn_line   = (sci_get_line_count(doc->editor->sci) - 1);
+
+		sel.is_selection = FALSE;
+	}
+
+	return sel;
+}
+
 
 /* altered from geany/src/editor.c, ensure new line at file end */
 static void
 ensure_final_newline(GeanyEditor *editor, gint max_lines)
 {
-	gint end_document       = sci_get_position_from_line(editor->sci, max_lines);
+	gint end_document      = sci_get_position_from_line(editor->sci, max_lines);
 	gboolean append_newline = end_document >
 					sci_get_position_from_line(editor->sci, max_lines - 1);
 
@@ -47,38 +110,57 @@ ensure_final_newline(GeanyEditor *editor, gint max_lines)
 }
 
 
-/* 
- * functions with indirect scintilla manipulation 
- * e.g. requires **lines array, *new_file...
+/*
+ * Menu action for functions with indirect scintilla manipulation
+ * e.g. functions requiring **lines array, *new_file...
 */
 static void
 action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata)
 {
-	void (*func)(GeanyDocument *, gchar **, gint, gchar *) = gdata;
-	GeanyDocument *doc = document_get_current();
-
-	gint  num_chars  = sci_get_length(doc->editor->sci);
-	gint  num_lines  = sci_get_line_count(doc->editor->sci);
-	gchar **lines    = g_malloc(sizeof(gchar *) * num_lines);
-	gchar *new_file  = g_malloc(sizeof(gchar)   * (num_chars+1));
-	gint i           = 0;
+	/* function pointer to gdata -- function to be used */
+	void (*func)(GeanyDocument * doc,
+					gchar **lines,
+					gint num_lines,
+					gchar *new_file) = gdata;
+
+	GeanyDocument *doc  = document_get_current();
+	struct lo_lines sel = get_current_sel_lines(doc);
+	gint  num_chars     = 0;
+	gint  num_lines     = (sel.end_posn_line - sel.start_posn_line) + 1;
+	gchar **lines       = g_malloc(sizeof(gchar *) * num_lines);
+	gint i              = 0;
+
+	/* get num_chars and **lines */
+	for(i = 0; i < num_lines; i++)
+	{
+		num_chars += (sci_get_line_length(doc->editor->sci,
+										(i + sel.start_posn_line)));
+		lines[i]   = sci_get_line(doc->editor->sci,
+										(i + sel.start_posn_line));
+	}
+
+	gchar *new_file  = g_malloc(sizeof(gchar) * (num_chars + 1));
 	new_file[0]      = '\0';
 
-	
-	/* copy *all* lines into **lines array */
-	for(i = 0; i < num_lines; i++)
-		lines[i] = sci_get_line(doc->editor->sci, i);
+	/* select lines to indicate to user what lines were altered */
+	select_lines(doc, sel);
 
 	sci_start_undo_action(doc->editor->sci);
 
 	/* if file is not empty, ensure that the file ends with newline */
-	if(num_lines != 1)
+	if((!sel.is_selection && num_lines != 1) || (sel.is_selection &&
+		sel.end_posn_line == (sci_get_line_count(doc->editor->sci) - 1)))
+	{
 		ensure_final_newline(doc->editor, num_lines);
+	}
 
 	if(doc) func(doc, lines, num_lines, new_file);
 
 	/* set new document */
-	sci_set_text(doc->editor->sci, new_file);
+	if(sci_has_selection(doc->editor->sci))
+		sci_replace_sel(doc->editor->sci, new_file);
+	else
+		sci_set_text(doc->editor->sci, new_file);
 
 	sci_end_undo_action(doc->editor->sci);
 
@@ -90,21 +172,25 @@ action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata)
 }
 
 
-/* 
- * functions with direct scintilla manipulation 
+
+/*
+ * Menu action for functions with direct scintilla manipulation
  * e.g. no need for **lines array, *new_file...
 */
 static void
 action_sci_manip_item(GtkMenuItem *menuitem, gpointer gdata)
 {
-	void (*func)(GeanyDocument *, gint) = gdata;
-	GeanyDocument *doc = document_get_current();
+	/* function pointer to gdata -- function to be used */
+	void (*func)(GeanyDocument *, gint, gint) = gdata;
+	GeanyDocument *doc  = document_get_current();
+	struct lo_lines sel = get_current_sel_lines(doc);
 
-	gint num_lines  = sci_get_line_count(doc->editor->sci);
+	/* select lines to indicate to user what lines were altered */
+	select_lines(doc, sel);
 
 	sci_start_undo_action(doc->editor->sci);
 
-	if(doc) func(doc, num_lines);
+	if(doc) func(doc, sel.start_posn_line, sel.end_posn_line);
 
 	sci_end_undo_action(doc->editor->sci);
 }
@@ -135,9 +221,9 @@ lo_init(GeanyPlugin *plugin, gpointer gdata)
 		  G_CALLBACK(action_sci_manip_item), (gpointer) rmwhspln },
 		{ NULL },
 		{ N_("Sort Lines _Ascending"),
-		  G_CALLBACK(action_indir_manip_item), (gpointer) sortlinesasc },
+		  G_CALLBACK(action_indir_manip_item), (gpointer) sortlnsasc },
 		{ N_("Sort Lines _Descending"),
-		  G_CALLBACK(action_indir_manip_item), (gpointer) sortlinesdesc }
+		  G_CALLBACK(action_indir_manip_item), (gpointer) sortlndesc }
 	};
 
 	main_menu_item = gtk_menu_item_new_with_mnemonic(_("_Line Operations"));
@@ -155,7 +241,10 @@ lo_init(GeanyPlugin *plugin, gpointer gdata)
 		else
 		{
 			item = gtk_menu_item_new_with_mnemonic(_(menu_items[i].label));
-			g_signal_connect(item, "activate", menu_items[i].cb_activate, menu_items[i].cb_data);
+			g_signal_connect(item,
+								"activate",
+								menu_items[i].cb_activate,
+								menu_items[i].cb_data);
 			ui_add_document_sensitive(item);
 		}
 
@@ -164,7 +253,8 @@ lo_init(GeanyPlugin *plugin, gpointer gdata)
 	}
 
 	gtk_menu_item_set_submenu(GTK_MENU_ITEM(main_menu_item), submenu);
-	gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), main_menu_item);
+	gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu),
+									main_menu_item);
 
 	return TRUE;
 }



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list