[geany/geany-plugins] 922b31: lineoperations: add support for locale-aware sorting (#897)

Sylvan Mostert git-noreply at xxxxx
Sun Sep 8 08:39:44 UTC 2019


Branch:      refs/heads/master
Author:      Sylvan Mostert <smostertdev at users.noreply.github.com>
Committer:   Frank Lanitz <frank at frank.uvena.de>
Date:        Sun, 08 Sep 2019 08:39:44 UTC
Commit:      922b3173dfed9e701552cef987cb5912fae70953
             https://github.com/geany/geany-plugins/commit/922b3173dfed9e701552cef987cb5912fae70953

Log Message:
-----------
lineoperations: add support for locale-aware sorting  (#897)

* lineoperations: minor formatting changes

* lineoperations: add preferences

* lineoperations: split files into fns and prefs

Move free lo_info to prefs file.

* lineoperations: abstract string compare fns

Either use g_utf8_collate or strcmp based on user preference.

* lineoperations: add documentation for prefs

Add to changelog.

Bump version number.

Add comments to 'action_sci_manip_item' and 'action_indir_manip_item',
to try explain which to use for new line operations.

* lineoperations: match indentation

* lineoperations: update POTFILES with lo_fns and lo_prefs

* lineoperations: docs changes, use g_strcmp0


Modified Paths:
--------------
    lineoperations/ChangeLog
    lineoperations/README
    lineoperations/src/Makefile.am
    lineoperations/src/lineoperations.c
    lineoperations/src/lo_fns.c
    lineoperations/src/lo_fns.h
    lineoperations/src/lo_prefs.c
    lineoperations/src/lo_prefs.h
    po/POTFILES.in

Modified: lineoperations/ChangeLog
9 lines changed, 6 insertions(+), 3 deletions(-)
===================================================================
@@ -1,6 +1,9 @@
-2016-02-27  Sylvan Mostert  <smostert.dev at gmail.com>
-
- * added selection support
+2019-08-11  Sylvan Mostert  <smostert.dev at gmail.com>
 
+ * added preferences to compare strings using linguistically correct rules
+   for the current locale
+ * added help button link to documentation
 
+2016-02-27  Sylvan Mostert  <smostert.dev at gmail.com>
 
+ * added selection support


Modified: lineoperations/README
102 lines changed, 74 insertions(+), 28 deletions(-)
===================================================================
@@ -7,7 +7,7 @@ Line Operations
 About
 =====
 
-Line Operations is an assortment of simple line functions that can be 
+Line Operations is an assortment of simple line functions that can be
 applied to an open file, or selection.
 
 Features
@@ -26,23 +26,72 @@ Features
 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, or 
-selection. See descriptions below to see operations for each menu item.
+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 ("Tools" > "Line Operations"). Click on each menu item to apply
+the operation on whole file, or selection. See descriptions below to
+see operations for each menu item.
+
+Preferences
+-----------
+
+To enable preferences ("Tools" > "Plugin Manager"), check the checkbox to
+enable Line Operations, and with the item highlighted click "Preferences"
+on bottom of the "Plugin Manager" frame.
+
+**Use collation based string compare** - When this option is enabled it will
+compare strings using linguistically correct rules for the current locale
+(g_utf8_collate).
+
+When it is disabled it will compare strings based on numerical value of the
+characters (strcmp).
+
+This option is disabled by default.
+
+  Example: Sort order using **Use collation based string compare** enabled
+
+  ::
+
+    D U+0044 : LATIN CAPITAL LETTER D
+    d U+0064 : LATIN SMALL LETTER D
+    E U+0045 : LATIN CAPITAL LETTER E
+    e U+0065 : LATIN SMALL LETTER E
+    Ê U+00CA : LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    é U+00E9 : LATIN SMALL LETTER E WITH ACUTE
+    F U+0046 : LATIN CAPITAL LETTER F
+    f U+0066 : LATIN SMALL LETTER F
+
+  Note: all 'e' characters appear after any 'd' character and before any 'f'
+  character.
+
+  Example: Sort order **Use collation based string compare** disabled
+
+  ::
+
+    D U+0044 : LATIN CAPITAL LETTER D
+    E U+0045 : LATIN CAPITAL LETTER E
+    F U+0046 : LATIN CAPITAL LETTER F
+    d U+0064 : LATIN SMALL LETTER D
+    e U+0065 : LATIN SMALL LETTER E
+    f U+0066 : LATIN SMALL LETTER F
+    Ê U+00CA : LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+    é U+00E9 : LATIN SMALL LETTER E WITH ACUTE
+
+  Note: all the 'e' characters do not appear together.
+
 
 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 
+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
 -----
 
- * Line Operations will **not** make changes to a file until you save 
+ * Line Operations will **not** make changes to a file until you save
    the file.
 
 
@@ -52,9 +101,9 @@ Operation Details
 Remove Duplicate Lines
 ----------------------
 
-The first occurrence of each duplicate line will remain in the file. 
-The **Sorted** option will sort the file and remove duplicate lines 
-[fast on large files]. The **Ordered** option will keep the same order 
+The first occurrence of each duplicate line will remain in the file.
+The **Sorted** option will sort the file and remove duplicate lines
+[fast on large files]. The **Ordered** option will keep the same order
 of lines [slow on large files].
 
   Example: Suppose a file has the following lines. (#comments added for
@@ -77,7 +126,7 @@ of lines [slow on large files].
     Line 2
     Line 3
 
-  The **Remove Duplicate Lines, ordered** will change the file into 
+  The **Remove Duplicate Lines, ordered** will change the file into
   this:
 
   ::
@@ -93,7 +142,7 @@ Remove Unique Lines
 
 Removes all lines that appear only once.
 
-  Example: Suppose a file has the following lines. (#comments added for 
+  Example: Suppose a file has the following lines. (#comments added for
   clarity)
 
   ::
@@ -121,7 +170,7 @@ Keep Unique Lines
 
 Keep all lines that appear only once.
 
-  Example: Suppose a file has the following lines. (#comments added for 
+  Example: Suppose a file has the following lines. (#comments added for
   clarity)
 
   ::
@@ -144,10 +193,10 @@ Keep all lines that appear only once.
 Remove Empty Lines
 ------------------
 
-Removes all lines that only contain a newline character, and no other 
+Removes all lines that only contain a newline character, and no other
 characters.
 
-  Example: Suppose a file has the following lines. (#comments, and 
+  Example: Suppose a file has the following lines. (#comments, and
   \\n newline characters added for clarity)
 
   ::
@@ -225,7 +274,7 @@ The user can enter a number N. Every Nth line will be removed then.
 Sort Lines
 ----------
 
-Sorts lines ascending or descending based on ASCII values 
+Sorts lines ascending or descending based on ASCII values
 (lexicographic sort).
 
 
@@ -264,19 +313,16 @@ Sorts lines ascending or descending based on ASCII values
 License
 =======
 
-The Line Operations plugin is distributed 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. 
-A copy of this license can be found in the file COPYING included with 
+The Line Operations plugin is distributed 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.
+A copy of this license can be found in the file COPYING included with
 the source code of this program.
 
 Ideas, questions, patches and bug reports
 =========================================
 
-Please direct all questions, bug reports and patches to the plugin 
-author using the email address listed below or to the Geany mailing 
-list to get some help from other Geany users, or report them at 
+Please direct all questions, bug reports and patches to the plugin
+author using the email address listed below or to the Geany mailing
+list to get some help from other Geany users, or report them at
 https://github.com/geany/geany-plugins/issues.
-
-
-


Modified: lineoperations/src/Makefile.am
6 lines changed, 4 insertions(+), 2 deletions(-)
===================================================================
@@ -4,8 +4,10 @@ plugin = lineoperations
 geanyplugins_LTLIBRARIES = lineoperations.la
 
 lineoperations_la_SOURCES = \
-	linefunctions.h \
-	linefunctions.c \
+	lo_fns.h \
+	lo_fns.c \
+	lo_prefs.h \
+	lo_prefs.c \
 	lineoperations.c
 
 lineoperations_la_CPPFLAGS = $(AM_CPPFLAGS) -DG_LOG_DOMAIN=\"LineOperations\"


Modified: lineoperations/src/lineoperations.c
84 lines changed, 54 insertions(+), 30 deletions(-)
===================================================================
@@ -20,27 +20,31 @@
 */
 
 
-#include "config.h"
+#ifdef HAVE_CONFIG_H
+    #include "config.h" /* for the gettext domain */
+#endif
 
 #include <geanyplugin.h>
 #include "Scintilla.h"
-#include "linefunctions.h"
+#include "lo_fns.h"
+#include "lo_prefs.h"
 
 
 static GtkWidget *main_menu_item = NULL;
 
 
-
 /* represents a selection of lines that will have Operation applied to */
-struct lo_lines {
+struct lo_lines
+{
 	gboolean is_selection;
 	gint     start_line;
 	gint     end_line;
 };
 
 
 /* represents a menu item and key binding */
-struct lo_menu_item{
+struct lo_menu_item
+{
 	const gchar *label;
 	const gchar *kb_section_name;
 	GCallback cb_activate;
@@ -51,18 +55,18 @@ struct lo_menu_item{
 typedef void (*CB_USER_FUNCTION)(GtkMenuItem *menuitem, gpointer gdata);
 
 
-/* selects lines in document (based off of lo_lines struct parameter) */
+/* selects lines in document (based on lo_lines struct parameter) */
 static void
 select_lines(GeanyEditor *editor, struct lo_lines *sel)
 {
 	/* set the selection to beginning of first line */
 	sci_set_selection_start(editor->sci,
-			sci_get_position_from_line(editor->sci, sel->start_line));
+							sci_get_position_from_line(editor->sci, sel->start_line));
 
 	/* 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));
+						  sci_get_line_end_position(editor->sci, sel->end_line) +
+							  editor_get_eol_char_len(editor));
 }
 
 
@@ -74,7 +78,7 @@ get_current_sel_lines(ScintillaObject *sci, struct lo_lines *sel)
 	gint end_posn       = 0;        /* position of selection end   */
 
 	/* check for selection */
-	if(sci_has_selection(sci))
+	if (sci_has_selection(sci))
 	{
 		/* get the start and end *positions* */
 		start_posn = sci_get_selection_start(sci);
@@ -127,23 +131,23 @@ ensure_final_newline(GeanyEditor *editor, gint *num_lines, struct lo_lines *sel)
 static void
 user_indicate(GeanyEditor *editor, gint lines_affected, struct lo_lines *sel)
 {
-	if(lines_affected < 0)
+	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;
+		sel->end_line += lines_affected;
 
-		if(sel->is_selection)
+		if (sel->is_selection)
 			select_lines(editor, sel);
 	}
-	else if(lines_affected == 0)
+	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)
+		if (sel->is_selection)
 			select_lines(editor, sel);
 	}
 	else
@@ -152,7 +156,7 @@ user_indicate(GeanyEditor *editor, gint lines_affected, struct lo_lines *sel)
 					lines_affected);
 
 		/* select lines to indicate to user what lines were altered */
-		if(sel->is_selection)
+		if (sel->is_selection)
 			select_lines(editor, sel);
 	}
 }
@@ -161,6 +165,11 @@ user_indicate(GeanyEditor *editor, gint lines_affected, struct lo_lines *sel)
 /*
  * Menu action for functions with indirect scintilla manipulation
  * e.g. functions requiring **lines array, num_lines, *new_file
+ *
+ * Use 'action_sci_manip_item()' if possible, since direction
+ * manipulation of Scintilla doc is faster/better.
+ * Use this if the line operation cannot be easily done with
+ * scintilla functions.
 */
 static void
 action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata)
@@ -176,16 +185,15 @@ action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata)
 	gint   lines_affected = 0;
 
 	get_current_sel_lines(doc->editor->sci, &sel);
-	gint num_lines       = (sel.end_line - sel.start_line) + 1;
-
+	gint num_lines = (sel.end_line - sel.start_line) + 1;
 
 	/* if last line within selection ensure that the file ends with newline */
-	if((sel.end_line + 1) == sci_get_line_count(doc->editor->sci))
+	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++)
+	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)));
@@ -214,24 +222,26 @@ action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata)
 	sci_end_undo_action(doc->editor->sci);
 
 	/* free used memory */
-	for(i = 0; i < num_lines; i++)
+	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...
+ *
+ * Use this if the line operation can be directly done with
+ * scintilla functions.
 */
 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();
+	GeanyDocument *doc = document_get_current();
 	g_return_if_fail(doc != NULL);
 
 	struct lo_lines sel;
@@ -286,14 +296,17 @@ static void lo_keybinding_callback(guint key_id)
 }
 
 
+/* Initialization */
 static gboolean
-lo_init(GeanyPlugin *plugin, gpointer gdata)
+lo_init(GeanyPlugin *plugin, G_GNUC_UNUSED gpointer gdata)
 {
 	GeanyData *geany_data = plugin->geany_data;
 	GeanyKeyGroup *key_group;
 	GtkWidget *submenu;
 	guint i;
 
+	lo_init_prefs(plugin);
+
 	main_menu_item = gtk_menu_item_new_with_mnemonic(_("_Line Operations"));
 	gtk_widget_show(main_menu_item);
 
@@ -310,9 +323,9 @@ lo_init(GeanyPlugin *plugin, gpointer gdata)
 		{
 			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);
+							"activate",
+							menu_items[i].cb_activate,
+							menu_items[i].cb_data);
 			ui_add_document_sensitive(item);
 		}
 
@@ -341,10 +354,19 @@ lo_init(GeanyPlugin *plugin, gpointer gdata)
 }
 
 
+/* Show help */
+static void
+lo_help (G_GNUC_UNUSED GeanyPlugin *plugin, G_GNUC_UNUSED gpointer pdata)
+{
+	utils_open_browser("https://plugins.geany.org/lineoperations.html");
+}
+
+
 static void
 lo_cleanup(GeanyPlugin *plugin, gpointer pdata)
 {
-	if(main_menu_item) gtk_widget_destroy(main_menu_item);
+	gtk_widget_destroy(main_menu_item);
+	lo_free_info();
 }
 
 
@@ -355,11 +377,13 @@ void geany_load_module(GeanyPlugin *plugin)
 
 	plugin->info->name        = _("Line Operations");
 	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->version     = "0.3";
 	plugin->info->author      = "Sylvan Mostert <smostert.dev at gmail.com>";
 
 	plugin->funcs->init       = lo_init;
 	plugin->funcs->cleanup    = lo_cleanup;
+	plugin->funcs->configure  = lo_configure;
+	plugin->funcs->help       = lo_help;
 
 	GEANY_PLUGIN_REGISTER(plugin, 225);
 }


Modified: lineoperations/src/lo_fns.c
137 lines changed, 79 insertions(+), 58 deletions(-)
===================================================================
@@ -1,6 +1,6 @@
 /*
- *      linefunctions.c - Line operations, remove duplicate lines, empty lines,
- *                        lines with only whitespace, sort lines.
+ *      lo_fns.c - Line operations, remove duplicate lines, empty lines,
+ *                 lines with only whitespace, sort lines.
  *
  *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.com>
  *
@@ -20,22 +20,40 @@
 */
 
 
-#include "linefunctions.h"
+#include "lo_fns.h"
+#include "lo_prefs.h"
+
+
+/* Get sort function based on user preferences */
+lo_strcmpfns
+getcmpfns(void)
+{
+	if(lo_info->use_collation_compare)
+	{
+		return g_utf8_collate;
+	}
+	else
+	{
+		return g_strcmp0;
+	}
+}
 
 
 /* comparison function to be used in qsort */
 static gint
-compare_asc(const void * a, const void * b)
+compare_asc(const void *a, const void *b)
 {
-	return strcmp(*(const gchar **) a, *(const gchar **) b);
+	lo_strcmpfns lo_strcmp = getcmpfns();
+	return lo_strcmp(*(const gchar **)a, *(const gchar **)b);
 }
 
 
 /* comparison function to be used in qsort */
 static gint
-compare_desc(const void * a, const void * b)
+compare_desc(const void *a, const void *b)
 {
-	return strcmp(*(const gchar **) b, *(const gchar **) a);
+	lo_strcmpfns lo_strcmp = getcmpfns();
+	return lo_strcmp(*(const gchar **)b, *(const gchar **)a);
 }
 
 
@@ -47,14 +65,15 @@ rmdupst(gchar **lines, gint num_lines, gchar *new_file)
 	gchar *lineptr = (gchar *)" "; /* temporary line pointer */
 	gint  i        = 0;            /* iterator */
 	gint  changed  = 0;            /* number of lines removed */
+	lo_strcmpfns lo_strcmp = getcmpfns();
 
 	/* sort **lines ascending */
 	qsort(lines, num_lines, sizeof(gchar *), compare_asc);
 
 	/* loop through **lines, join first occurances into one str (new_file) */
-	for(i = 0; i < num_lines; i++)
+	for (i = 0; i < num_lines; i++)
 	{
-		if(strcmp(lines[i], lineptr) != 0)
+		if (lo_strcmp(lines[i], lineptr) != 0)
 		{
 			changed++;     /* number of lines kept */
 			lineptr = lines[i];
@@ -76,32 +95,33 @@ rmdupln(gchar **lines, gint num_lines, gchar *new_file)
 	gint  j        = 0;         /* iterator */
 	gboolean *to_remove = NULL; /* flag to 'mark' which lines to remove */
 	gint  changed  = 0;         /* number of lines removed */
+	lo_strcmpfns lo_strcmp = getcmpfns();
 
 
 	/* allocate and set *to_remove to all FALSE
 	 * to_remove[i] represents whether lines[i] should be removed  */
 	to_remove = g_malloc(sizeof(gboolean) * num_lines);
-	for(i = 0; i < (num_lines); i++)
+	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 < 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])
+		if (!to_remove[i])
 		{
 			/* find the rest of same lines */
-			for(j = (i+1); j < num_lines; j++)
+			for (j = (i + 1); j < num_lines; j++)
 			{
-				if(!to_remove[j] && strcmp(lines[i], lines[j]) == 0)
+				if (!to_remove[j] && lo_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 < num_lines; i++)
-		if(!to_remove[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]);
@@ -124,28 +144,29 @@ rmunqln(gchar **lines, gint num_lines, gchar *new_file)
 	gint  j       = 0;          /* iterator */
 	gboolean *to_remove = NULL; /* to 'mark' which lines to remove */
 	gint  changed = 0;          /* number of lines removed */
+	lo_strcmpfns lo_strcmp = getcmpfns();
 
 
 	/* allocate and set *to_remove to all TRUE
 	 * to_remove[i] represents whether lines[i] should be removed */
 	to_remove = g_malloc(sizeof(gboolean) * num_lines);
-	for(i = 0; i < num_lines; i++)
+	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 < 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 < num_lines; j++)
-				if(to_remove[j] && strcmp(lines[i], lines[j]) == 0)
+		if (to_remove[i])
+			for (j = (i + 1); j < num_lines; j++)
+				if (to_remove[j] && lo_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 < num_lines; i++)
-		if(!to_remove[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]);
@@ -168,28 +189,29 @@ kpunqln(gchar **lines, gint num_lines, gchar *new_file)
 	gint  j       = 0;          /* iterator */
 	gboolean *to_remove = NULL; /* to 'mark' which lines to remove */
 	gint  changed = 0;          /* number of lines removed */
+	lo_strcmpfns lo_strcmp = getcmpfns();
 
 
 	/* allocate and set *to_remove to all FALSE
 	 * to_remove[i] represents whether lines[i] should be removed */
 	to_remove = g_malloc(sizeof(gboolean) * num_lines);
-	for(i = 0; i < num_lines; i++)
+	for (i = 0; i < num_lines; i++)
 		to_remove[i] = FALSE;
-	
+
 	/* find all non unique lines and set them to TRUE (to be removed) */
-	for(i = 0; i < num_lines; i++)
+	for (i = 0; i < num_lines; i++)
 		/* make sure that the line is not already determined to be non unique */
-		if(!to_remove[i])
-			for(j = (i+1); j < num_lines; j++)
-				if(!to_remove[j] && strcmp(lines[i], lines[j]) == 0)
+		if (!to_remove[i])
+			for (j = (i + 1); j < num_lines; j++)
+				if (!to_remove[j] && lo_strcmp(lines[i], lines[j]) == 0)
 				{
 					to_remove[i] = TRUE;
 					to_remove[j] = TRUE;
 				}
-	
+
 	/* copy **lines into 'new_file' if it is not FALSE(not duplicate) */
-	for(i = 0; i < num_lines; i++)
-		if(!to_remove[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]);
@@ -207,18 +229,18 @@ kpunqln(gchar **lines, gint num_lines, gchar *new_file)
 gint
 rmemtyln(ScintillaObject *sci, gint line_num, gint end_line_num)
 {
-	gint  changed = 0;     /* number of lines removed */
+	gint changed = 0;     /* number of lines removed */
 
-	while(line_num <= end_line_num)    /* loop through lines */
+	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(sci, line_num) ==
-		   sci_get_line_end_position (sci, line_num))
+		if (sci_get_position_from_line(sci, line_num) ==
+			sci_get_line_end_position (sci, line_num))
 		{
 			scintilla_send_message(sci,
-					   SCI_DELETERANGE,
-					   sci_get_position_from_line(sci, line_num),
-					   sci_get_line_length(sci, line_num));
+								   SCI_DELETERANGE,
+								   sci_get_position_from_line(sci, line_num),
+								   sci_get_line_length(sci, line_num));
 
 			line_num--;
 			end_line_num--;
@@ -239,29 +261,28 @@ rmwhspln(ScintillaObject *sci, gint line_num, gint end_line_num)
 	gint indent;                       /* indent position */
 	gint changed = 0;                  /* number of lines removed */
 
-	while(line_num <= end_line_num)    /* loop through lines */
+	while (line_num <= end_line_num)    /* loop through lines */
 	{
 		indent = scintilla_send_message(sci,
-									SCI_GETLINEINDENTPOSITION,
-									line_num, 0);
+										SCI_GETLINEINDENTPOSITION,
+										line_num, 0);
 
 		/* check if the posn of indentation is also the end of line posn */
-		if(indent -
-		   sci_get_position_from_line(sci, line_num) ==
-		   sci_get_line_end_position (sci, line_num) -
-		   sci_get_position_from_line(sci, line_num))
+		if (indent -
+				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(sci,
-					   SCI_DELETERANGE,
-					   sci_get_position_from_line(sci, line_num),
-					   sci_get_line_length(sci, line_num));
+								   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++;
-
 	}
 
 	/* return the number of lines deleted */
@@ -279,7 +300,7 @@ sortlnsasc(gchar **lines, gint num_lines, gchar *new_file)
 	qsort(lines, num_lines, sizeof(gchar *), compare_asc);
 
 	/* join **lines into one string (new_file) */
-	for(i = 0; i < num_lines; i++)
+	for (i = 0; i < num_lines; i++)
 		nf_end = g_stpcpy(nf_end, lines[i]);
 
 	return num_lines;
@@ -296,7 +317,7 @@ sortlndesc(gchar **lines, gint num_lines, gchar *new_file)
 	qsort(lines, num_lines, sizeof(gchar *), compare_desc);
 
 	/* join **lines into one string (new_file) */
-	for(i = 0; i < num_lines; i++)
+	for (i = 0; i < num_lines; i++)
 		nf_end = g_stpcpy(nf_end, lines[i]);
 
 	return num_lines;
@@ -313,24 +334,24 @@ rmnthln(ScintillaObject *sci, gint line_num, gint end_line_num)
 	gint changed = 0;     /* number of lines removed */
 
 	ok = dialogs_show_input_numeric(_("Remove every Nth line"),
-		_("Value of N"), &n, 1, 1000, 1);
+									_("Value of N"), &n, 1, 1000, 1);
 	if (ok == FALSE)
 	{
 		return 0;
 	}
 
 	count = n;
-	while(line_num <= end_line_num)    /* loop through lines */
+	while (line_num <= end_line_num)    /* loop through lines */
 	{
 		count--;
 
 		/* check if this is the nth line. */
-		if(count == 0)
+		if (count == 0)
 		{
 			scintilla_send_message(sci,
-					   SCI_DELETERANGE,
-					   sci_get_position_from_line(sci, line_num),
-					   sci_get_line_length(sci, line_num));
+								   SCI_DELETERANGE,
+								   sci_get_position_from_line(sci, line_num),
+								   sci_get_line_length(sci, line_num));
 
 			line_num--;
 			end_line_num--;


Modified: lineoperations/src/lo_fns.h
15 lines changed, 11 insertions(+), 4 deletions(-)
===================================================================
@@ -1,6 +1,6 @@
 /*
- *      linefunctions.h - Line operations, remove duplicate lines, empty lines,
- *                        lines with only whitespace, sort lines.
+ *      lo_fns.h - Line operations, remove duplicate lines, empty lines,
+ *                 lines with only whitespace, sort lines.
  *
  *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.com>
  *
@@ -21,15 +21,22 @@
 
 
 
-#ifndef LINEFUNCTIONS_H
-#define LINEFUNCTIONS_H
+#ifndef LO_FNS_H
+#define LO_FNS_H
 
 #include <geanyplugin.h>
 #include "Scintilla.h"
 #include <stdlib.h>      /* qsort */
 #include <string.h>
 
 
+typedef gint (*lo_strcmpfns)(const gchar *str1, const gchar *str2);
+
+/* Get sort function based on user preferences */
+lo_strcmpfns
+getcmpfns(void);
+
+
 /* Remove Duplicate Lines, sorted */
 gint
 rmdupst(gchar **lines, gint num_lines, gchar *new_file);


Modified: lineoperations/src/lo_prefs.c
127 lines changed, 127 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,127 @@
+/*
+ *      lo_prefs.c - Line operations, remove duplicate lines, empty lines,
+ *                 lines with only whitespace, sort lines.
+ *
+ *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.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.
+*/
+
+#include "lo_prefs.h"
+
+
+static struct
+{
+	GtkWidget *collation_cb;
+} config_widgets;
+
+
+LineOpsInfo *lo_info = NULL;
+
+
+/* handle button presses in the preferences dialog box */
+void
+lo_configure_response_cb(GtkDialog *dialog, gint response, gpointer user_data)
+{
+	if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY)
+	{
+		GKeyFile *config = g_key_file_new();
+		gchar *config_dir = g_path_get_dirname(lo_info->config_file);
+		gchar *data;
+
+		/* Grabbing options that has been set */
+		lo_info->use_collation_compare =
+			gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_widgets.collation_cb));
+
+		/* Write preference to file */
+		g_key_file_load_from_file(config, lo_info->config_file, G_KEY_FILE_NONE, NULL);
+
+		g_key_file_set_boolean(config, "general", "use_collation_compare",
+			lo_info->use_collation_compare);
+
+		if (!g_file_test(config_dir, G_FILE_TEST_IS_DIR)
+			&& utils_mkdir(config_dir, TRUE) != 0)
+		{
+			dialogs_show_msgbox(GTK_MESSAGE_ERROR,
+				_("Plugin configuration directory could not be created."));
+		}
+		else
+		{
+			/* write config to file */
+			data = g_key_file_to_data(config, NULL, NULL);
+			utils_write_file(lo_info->config_file, data);
+			g_free(data);
+		}
+
+		g_free(config_dir);
+		g_key_file_free(config);
+	}
+}
+
+
+/* Configure the preferences GUI and callbacks */
+GtkWidget *
+lo_configure(G_GNUC_UNUSED GeanyPlugin *plugin, GtkDialog *dialog, G_GNUC_UNUSED gpointer pdata)
+{
+	GtkWidget *vbox;
+
+	vbox = gtk_vbox_new(FALSE, 0);
+
+	config_widgets.collation_cb = gtk_check_button_new_with_label(
+		_("Use collation based string compare"));
+
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(config_widgets.collation_cb),
+		lo_info->use_collation_compare);
+
+	gtk_box_pack_start(GTK_BOX(vbox), config_widgets.collation_cb, FALSE, FALSE, 2);
+
+
+	gtk_widget_show_all(vbox);
+	g_signal_connect(dialog, "response", G_CALLBACK(lo_configure_response_cb), NULL);
+
+	return vbox;
+}
+
+
+/* Initialize preferences */
+void
+lo_init_prefs(GeanyPlugin *plugin)
+{
+	GeanyData *geany_data = plugin->geany_data;
+	GKeyFile *config = g_key_file_new();
+
+	/* load preferences from file into lo_info */
+	lo_info = g_new0(LineOpsInfo, 1);
+	lo_info->config_file = g_strconcat(geany->app->configdir,
+		G_DIR_SEPARATOR_S, "plugins", G_DIR_SEPARATOR_S,
+		"lineoperations", G_DIR_SEPARATOR_S, "general.conf", NULL);
+
+	g_key_file_load_from_file(config, lo_info->config_file, G_KEY_FILE_NONE, NULL);
+
+	lo_info->use_collation_compare = utils_get_setting_boolean(config,
+		"general", "use_collation_compare", FALSE);
+
+	printf("VALUE: %d\n", lo_info->use_collation_compare);
+
+	g_key_file_free(config);
+}
+
+
+/* Free config */
+void
+lo_free_info() {
+	g_free(lo_info->config_file);
+	g_free(lo_info);
+}
\ No newline at end of file


Modified: lineoperations/src/lo_prefs.h
59 lines changed, 59 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,59 @@
+/*
+ *      lo_prefs.h - Line operations, remove duplicate lines, empty lines,
+ *                   lines with only whitespace, sort lines.
+ *
+ *      Copyright 2015 Sylvan Mostert <smostert.dev at gmail.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.
+*/
+
+#ifndef LO_PREFS_H
+#define LO_PREFS_H
+
+#include <geanyplugin.h>
+#include "lo_prefs.h"
+
+
+typedef struct
+{
+	/* general settings */
+	gchar *config_file;
+	gboolean use_collation_compare;
+} LineOpsInfo;
+
+
+extern LineOpsInfo *lo_info;
+
+
+/* handle button presses in the preferences dialog box */
+void
+lo_configure_response_cb(GtkDialog *dialog, gint response, gpointer user_data);
+
+
+/* Configure the preferences GUI and callbacks */
+GtkWidget *
+lo_configure(G_GNUC_UNUSED GeanyPlugin *plugin, GtkDialog *dialog, G_GNUC_UNUSED gpointer pdata);
+
+
+/* Initialize preferences */
+void
+lo_init_prefs(GeanyPlugin *plugin);
+
+
+/* Free config */
+void
+lo_free_info();
+
+#endif
\ No newline at end of file


Modified: po/POTFILES.in
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -220,7 +220,8 @@ keyrecord/src/keyrecord.c
 
 # LineOperations
 lineoperations/src/lineoperations.c
-lineoperations/src/linefunctions.c
+lineoperations/src/lo_fns.c
+lineoperations/src/lo_prefs.c
 
 # lipsum
 lipsum/src/lipsum.c



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