[geany/geany-plugins] c563b2: Merge pull request #378 from smostertdev/lineoperations_v2

Frank Lanitz git-noreply at xxxxx
Tue Jan 3 21:45:58 UTC 2017


Branch:      refs/heads/master
Author:      Frank Lanitz <frank at frank.uvena.de>
Committer:   GitHub <noreply at github.com>
Date:        Tue, 03 Jan 2017 21:45:58 UTC
Commit:      c563b20ceeac9d91d2fa77b1783262317b4b49ef
             https://github.com/geany/geany-plugins/commit/c563b20ceeac9d91d2fa77b1783262317b4b49ef

Log Message:
-----------
Merge pull request #378 from smostertdev/lineoperations_v2

lineoperations: added selection support


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

Modified: lineoperations/ChangeLog
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,6 @@
+2016-02-27  Sylvan Mostert  <smostert.dev at gmail.com>
+
+ * added selection support
+
+
+


Modified: lineoperations/README
14 lines changed, 11 insertions(+), 3 deletions(-)
===================================================================
@@ -8,7 +8,7 @@ About
 =====
 
 Line Operations is an assortment of simple line functions that can be 
-applied to an open file.
+applied to an open file, or selection.
 
 Features
 ========
@@ -26,8 +26,16 @@ Usage
 
 After the plugins has been installed successfully, load the plugin via 
 Geany's plugin manager and a new menu item in the Tools menu will 
-appear. Click on each menu item to apply the operation on whole file. 
-See descriptions below to see operations for each menu item.
+appear. Click on each menu item to apply the operation on whole file, or 
+selection. See descriptions below to see operations for each menu item.
+
+Selection
+---------
+
+If a selection is made in the file, the line operation will be applied to the 
+lines within the selection. The beginning of the selection will expand to the 
+beginning of its line, and the end of the selection will expand to the end of 
+its line. If the end of the selection is on col 0, that line will be included.
 
 Notes
 -----


Modified: lineoperations/src/linefunctions.c
336 lines changed, 136 insertions(+), 200 deletions(-)
===================================================================
@@ -1,5 +1,6 @@
 /*
- *      linefunctions.c - Line operations, remove duplicate lines, empty lines, lines with only whitespace, sort lines.
+ *      linefunctions.c - Line operations, remove duplicate lines, empty lines,
+ *                        lines with only whitespace, sort lines.
  *
  *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.com>
  *
@@ -22,302 +23,237 @@
 #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)
+static gint
+compare_asc(const void * a, const void * b)
 {
 	return strcmp(*(const gchar **) a, *(const gchar **) b);
 }
 
 
 /* comparison function to be used in qsort */
-static gint compare_desc(const void * a, const void * b)
+static gint
+compare_desc(const void * a, const void * b)
 {
 	return strcmp(*(const gchar **) b, *(const gchar **) a);
 }
 
 
 /* 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);
+gint
+rmdupst(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 */
+	gint  changed  = 0;            /* number of lines removed */
 
 	/* 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]);
+			changed++;     /* number of lines kept */
+			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);
+	/* return the number of lines deleted */
+	return -(num_lines - changed);
 }
 
 
 /* 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);
+gint
+rmdupln(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 */
+	gint  changed  = 0;         /* number of lines removed */
+
 
 	/* 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 */
+					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++)
+	/* copy **lines into 'new_file' if it is not FALSE (not duplicate) */
+	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);
+		{
+			changed++;     /* number of lines kept */
+			nf_end = g_stpcpy(nf_end, lines[i]);
+		}
 
 	/* 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);
+
+	/* return the number of lines deleted */
+	return -(num_lines - changed);
 }
 
 
 /* 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);
+gint
+rmunqln(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 */
+	gint  changed = 0;          /* number of lines removed */
 
 
 	/* 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])
+		{
+			changed++;     /* number of lines kept */
 			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);
+
+	/* return the number of lines deleted */
+	return -(num_lines - changed);
 }
 
 
 /* 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);
+gint
+rmemtyln(ScintillaObject *sci, gint line_num, gint end_line_num)
+{
+	gint  changed = 0;     /* number of lines removed */
 
-	for(i = 0; i < total_num_lines; i++)    /* loop through opened doc */
+	while(line_num <= end_line_num)    /* loop through lines */
 	{
-		if(sci_get_position_from_line(doc->editor->sci, i) ==
-		   sci_get_line_end_position(doc->editor->sci, i))
+		/* check if the first posn of the line is also the end of line posn */
+		if(sci_get_position_from_line(sci, line_num) ==
+		   sci_get_line_end_position (sci, line_num))
 		{
-			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--;
+			scintilla_send_message(sci,
+					   SCI_DELETERANGE,
+					   sci_get_position_from_line(sci, line_num),
+					   sci_get_line_length(sci, line_num));
+
+			line_num--;
+			end_line_num--;
+			changed++;
 		}
+		line_num++;
 	}
 
-	sci_end_undo_action(doc->editor->sci);
+	/* return the number of lines deleted */
+	return -changed;
 }
 
 
 /* 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);
+gint
+rmwhspln(ScintillaObject *sci, gint line_num, gint end_line_num)
+{
+	gint indent;                       /* indent position */
+	gint changed = 0;                  /* number of lines removed */
 
-	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,
+		indent = scintilla_send_message(sci,
 									SCI_GETLINEINDENTPOSITION,
-									i, 0);
+									line_num, 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))
+		   sci_get_position_from_line(sci, line_num) ==
+		   sci_get_line_end_position (sci, line_num) -
+		   sci_get_position_from_line(sci, line_num))
 		{
-			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--;
+			scintilla_send_message(sci,
+					   SCI_DELETERANGE,
+					   sci_get_position_from_line(sci, line_num),
+					   sci_get_line_length(sci, line_num));
+
+			line_num--;
+			end_line_num--;
+			changed++;
 		}
+		line_num++;
 
 	}
 
-
-	sci_end_undo_action(doc->editor->sci);
+	/* return the number of lines deleted */
+	return -changed;
 }
 
 
-/* Sort Lines Ascending and Descending */
-void sortlines(GeanyDocument *doc, gboolean asc) {
-	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 */
-	gint  i;                /* iterator */
+/* Sort Lines Ascending */
+gint
+sortlnsasc(gchar **lines, gint num_lines, gchar *new_file)
+{
+	gchar *nf_end = new_file;          /* points to last char of new_file */
+	gint i;
+
+	qsort(lines, num_lines, sizeof(gchar *), compare_asc);
+
+	/* join **lines into one string (new_file) */
+	for(i = 0; i < num_lines; i++)
+		nf_end = g_stpcpy(nf_end, lines[i]);
 
-	total_num_lines = sci_get_line_count(doc->editor->sci);
-	lines           = g_malloc(sizeof(gchar *) * (total_num_lines+1));
+	return num_lines;
+}
 
-	/* 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);
+/* Sort Lines Descending */
+gint
+sortlndesc(gchar **lines, gint num_lines, gchar *new_file)
+{
+	gchar *nf_end = new_file;          /* points to last char of new_file */
+	gint i;
 
-	/* sort **lines array */
-	if(asc)
-		qsort(lines, total_num_lines, sizeof(gchar *), compare_asc);
-	else
-		qsort(lines, total_num_lines, sizeof(gchar *), compare_desc);
+	qsort(lines, num_lines, sizeof(gchar *), compare_desc);
 
 	/* join **lines into one string (new_file) */
-	lines[total_num_lines] = NULL;
-	new_file = g_strjoinv("", lines);
-
-	/* set new document */
-	sci_set_text(doc->editor->sci, new_file);
+	for(i = 0; i < num_lines; i++)
+		nf_end = g_stpcpy(nf_end, lines[i]);
 
-	/* free used memory */
-	for(i = 0; i < total_num_lines; i++)
-		g_free(lines[i]);
-	g_free(lines);
-	g_free(new_file);
+	return num_lines;
 }


Modified: lineoperations/src/linefunctions.h
28 lines changed, 20 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,26 +31,37 @@
 
 
 /* Remove Duplicate Lines, sorted */
-void rmdupst(GeanyDocument *doc);
+gint
+rmdupst(gchar **lines, gint num_lines, gchar *new_file);
 
 
 /* Remove Duplicate Lines, ordered */
-void rmdupln(GeanyDocument *doc);
+gint
+rmdupln(gchar **lines, gint num_lines, gchar *new_file);
 
 
 /* Remove Unique Lines */
-void rmunqln(GeanyDocument *doc);
+gint
+rmunqln(gchar **lines, gint num_lines, gchar *new_file);
 
 
 /* Remove Empty Lines */
-void rmemtyln(GeanyDocument *doc);
+gint
+rmemtyln(ScintillaObject *sci, gint line_num, gint end_line_num);
 
 
 /* Remove Whitespace Lines */
-void rmwhspln(GeanyDocument *doc);
+gint
+rmwhspln(ScintillaObject *sci, gint line_num, gint end_line_num);
 
 
-/* Sort Lines Ascending and Descending */
-void sortlines(GeanyDocument *doc, gboolean asc);
+/* Sort Lines Ascending */
+gint
+sortlnsasc(gchar **lines, gint num_lines, gchar *new_file);
+
+
+/* Sort Lines Descending */
+gint
+sortlndesc(gchar **lines, gint num_lines, gchar *new_file);
 
 #endif


Modified: lineoperations/src/lineoperations.c
237 lines changed, 214 insertions(+), 23 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>
  *
@@ -29,26 +30,212 @@
 static GtkWidget *main_menu_item = NULL;
 
 
-/* call custom func */
+
+/* represents a selection of lines that will have Operation applied to */
+struct lo_lines {
+	gboolean is_selection;
+	gint     start_line;
+	gint     end_line;
+};
+
+
+/* selects lines in document (based off of lo_lines struct parameter) */
 static void
-action_func_item(GtkMenuItem *menuitem, gpointer gdata)
+select_lines(GeanyEditor *editor, struct lo_lines sel)
 {
-	void (*func)(GeanyDocument *) = gdata;
-	GeanyDocument *doc = NULL;
-	doc = document_get_current();
+	/* set the selection to beginning of first line */
+	sci_set_selection_start(editor->sci,
+			sci_get_position_from_line(editor->sci, sel.start_line));
 
-	if(doc) func(doc);
+	/* set the selection to end of last line */
+	sci_set_selection_end(editor->sci,
+			sci_get_line_end_position(editor->sci, sel.end_line) +
+									 editor_get_eol_char_len(editor));
 }
 
 
-/* Sort Lines */
+/* get lo_lines struct based off of document */
+static struct lo_lines
+get_current_sel_lines(ScintillaObject *sci)
+{
+	struct lo_lines sel = { FALSE, 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(sci))
+	{
+		/* get the start and end *positions* */
+		start_posn = sci_get_selection_start(sci);
+		end_posn   = sci_get_selection_end  (sci);
+
+		/* get the *line number* of those positions */
+		sel.start_line = scintilla_send_message(sci,
+									SCI_LINEFROMPOSITION,
+									start_posn, 0);
+
+		sel.end_line   = scintilla_send_message(sci,
+									SCI_LINEFROMPOSITION,
+									end_posn, 0);
+
+		sel.is_selection = TRUE;
+	}
+	else
+	{
+		/* if there is no selection, start at first line */
+		sel.start_line = 0;
+		/* and end at last one */
+		sel.end_line   = (sci_get_line_count(sci) - 1);
+
+		sel.is_selection = FALSE;
+	}
+
+	return sel;
+}
+
+
+/* altered from geany/src/editor.c, ensure new line at file end */
 static void
-action_sort_item(GtkMenuItem *menuitem, gpointer gdata)
+ensure_final_newline(GeanyEditor *editor, gint *num_lines, struct lo_lines *sel)
 {
-	GeanyDocument *doc = NULL;
-	doc = document_get_current();
+	gint end_document   = sci_get_position_from_line(editor->sci, (*num_lines));
+	gboolean append_newline = end_document >
+					sci_get_position_from_line(editor->sci, ((*num_lines) - 1));
+
+	if (append_newline)
+	{
+		const gchar *eol = editor_get_eol_char(editor);
+		sci_insert_text(editor->sci, end_document, eol);
+
+		/* re-adjust the selection */
+		(*num_lines)++;
+		(*sel).end_line++;
+	}
+}
+
+
+/* set statusbar with message and select altered lines */
+static void
+user_indicate(GeanyEditor *editor, gint lines_affected, struct lo_lines sel)
+{
+	if(lines_affected < 0)
+	{
+		ui_set_statusbar(FALSE, _("Operation successful! %d lines removed."),
+					-lines_affected);
+
+		/* select lines to indicate to user what lines were altered */
+		sel.end_line   += lines_affected;
+
+		if(sel.is_selection)
+			select_lines(editor, sel);
+	}
+	else if(lines_affected == 0)
+	{
+		ui_set_statusbar(FALSE, _("Operation successful! No lines removed."));
+
+		/* select lines to indicate to user what lines were altered */
+		if(sel.is_selection)
+			select_lines(editor, sel);
+	}
+	else
+	{
+		ui_set_statusbar(FALSE, _("Operation successful! %d lines affected."),
+					lines_affected);
+
+		/* select lines to indicate to user what lines were altered */
+		if(sel.is_selection)
+			select_lines(editor, sel);
+	}
+}
+
+
+/*
+ * Menu action for functions with indirect scintilla manipulation
+ * e.g. functions requiring **lines array, num_lines, *new_file
+*/
+static void
+action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata)
+{
+	/* function pointer to function to be used */
+	gint (*func)(gchar **lines, gint num_lines, gchar *new_file) = gdata;
+	GeanyDocument *doc    = document_get_current();
+
+	struct lo_lines sel   = get_current_sel_lines(doc->editor->sci);
+	gint   num_lines      = (sel.end_line - sel.start_line) + 1;
+
+	gint   num_chars      = 0;
+	gint   i              = 0;
+	gint   lines_affected = 0;
+
+
+	/* if last line within selection ensure that the file ends with newline */
+	if((sel.end_line + 1) == sci_get_line_count(doc->editor->sci))
+		ensure_final_newline(doc->editor, &num_lines, &sel);
+
+	/* get num_chars and **lines */
+	gchar **lines        = g_malloc(sizeof(gchar *) * num_lines);
+	for(i = 0; i < num_lines; i++)
+	{
+		num_chars += (sci_get_line_length(doc->editor->sci,
+										(i + sel.start_line)));
+
+		lines[i]   = sci_get_line(doc->editor->sci,
+										(i + sel.start_line));
+	}
+
+	gchar *new_file  = g_malloc(sizeof(gchar) * (num_chars + 1));
+	new_file[0]      = '\0';
+
+	/* select lines that will be replaced with array */
+	select_lines(doc->editor, sel);
+
+	sci_start_undo_action(doc->editor->sci);
+
+
+	if(doc)
+		lines_affected = func(lines, num_lines, new_file);
+
+
+	/* set new document */
+	sci_replace_sel(doc->editor->sci, new_file);
+
+	/* select affected lines and set statusbar message */
+	user_indicate(doc->editor, lines_affected, sel);
+
+	sci_end_undo_action(doc->editor->sci);
+
+	/* free used memory */
+	for(i = 0; i < num_lines; i++)
+		g_free(lines[i]);
+	g_free(lines);
+	g_free(new_file);
+}
+
+
+
+/*
+ * 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)
+{
+	/* function pointer to gdata -- function to be used */
+	gint (*func)(ScintillaObject *, gint, gint) = gdata;
+	GeanyDocument *doc  = document_get_current();
+	struct lo_lines sel = get_current_sel_lines(doc->editor->sci);
+	gint lines_affected = 0;
+
+
+	sci_start_undo_action(doc->editor->sci);
+
+	if(doc)
+		lines_affected = func(doc->editor->sci, sel.start_line, sel.end_line);
+
+	/* put message in ui_statusbar, and highlight lines that were affected */
+	user_indicate(doc->editor, lines_affected, sel);
 
-	if(doc) sortlines(doc, GPOINTER_TO_INT(gdata));
+	sci_end_undo_action(doc->editor->sci);
 }
 
 
@@ -65,21 +252,21 @@ lo_init(GeanyPlugin *plugin, gpointer gdata)
 		gpointer cb_data;
 	} menu_items[] = {
 		{ N_("Remove Duplicate Lines, _Sorted"),
-		  G_CALLBACK(action_func_item), (gpointer) rmdupst },
+		  G_CALLBACK(action_indir_manip_item), (gpointer) rmdupst },
 		{ N_("Remove Duplicate Lines, _Ordered"),
-		  G_CALLBACK(action_func_item), (gpointer) rmdupln },
+		  G_CALLBACK(action_indir_manip_item), (gpointer) rmdupln },
 		{ N_("Remove _Unique Lines"),
-		  G_CALLBACK(action_func_item), (gpointer) rmunqln },
+		  G_CALLBACK(action_indir_manip_item), (gpointer) rmunqln },
 		{ NULL },
 		{ N_("Remove _Empty Lines"),
-		  G_CALLBACK(action_func_item), (gpointer) rmemtyln },
+		  G_CALLBACK(action_sci_manip_item), (gpointer) rmemtyln },
 		{ N_("Remove _Whitespace Lines"),
-		  G_CALLBACK(action_func_item), (gpointer) rmwhspln },
+		  G_CALLBACK(action_sci_manip_item), (gpointer) rmwhspln },
 		{ NULL },
 		{ N_("Sort Lines _Ascending"),
-		  G_CALLBACK(action_sort_item), GINT_TO_POINTER(1) },
+		  G_CALLBACK(action_indir_manip_item), (gpointer) sortlnsasc },
 		{ N_("Sort Lines _Descending"),
-		  G_CALLBACK(action_sort_item), GINT_TO_POINTER(0) }
+		  G_CALLBACK(action_indir_manip_item), (gpointer) sortlndesc }
 	};
 
 	main_menu_item = gtk_menu_item_new_with_mnemonic(_("_Line Operations"));
@@ -97,7 +284,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);
 		}
 
@@ -106,7 +296,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;
 }
@@ -125,8 +316,8 @@ void geany_load_module(GeanyPlugin *plugin)
 	main_locale_init(LOCALEDIR, GETTEXT_PACKAGE);
 
 	plugin->info->name        = _("Line Operations");
-	plugin->info->description = _("Line Operations provides a handful of functions that can be applied to a document such as, removing duplicate lines, removing empty lines, removing lines with only whitespace, and sorting lines.");
-	plugin->info->version     = "0.1";
+	plugin->info->description = _("Line Operations provides a handful of functions that can be applied to a document or selection such as, removing duplicate lines, removing empty lines, removing lines with only whitespace, and sorting lines.");
+	plugin->info->version     = "0.2";
 	plugin->info->author      = "Sylvan Mostert <smostert.dev at gmail.com>";
 
 	plugin->funcs->init       = lo_init;



--------------
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