diff --git a/lineoperations/ChangeLog b/lineoperations/ChangeLog index 69974ecd9..656b10004 100644 --- a/lineoperations/ChangeLog +++ b/lineoperations/ChangeLog @@ -1,6 +1,9 @@ -2016-02-27 Sylvan Mostert - - * added selection support +2019-08-11 Sylvan Mostert + * added preferences to compare strings using linguistically correct rules + for the current locale + * added help button link to documentation +2016-02-27 Sylvan Mostert + * added selection support diff --git a/lineoperations/README b/lineoperations/README index 5695121fb..bacceab85 100644 --- a/lineoperations/README +++ b/lineoperations/README @@ -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. - - - diff --git a/lineoperations/src/Makefile.am b/lineoperations/src/Makefile.am index 322659a7a..027285e7a 100644 --- a/lineoperations/src/Makefile.am +++ b/lineoperations/src/Makefile.am @@ -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\" diff --git a/lineoperations/src/lineoperations.c b/lineoperations/src/lineoperations.c index bdd7f7f39..2a8fa66f3 100644 --- a/lineoperations/src/lineoperations.c +++ b/lineoperations/src/lineoperations.c @@ -20,19 +20,22 @@ */ -#include "config.h" +#ifdef HAVE_CONFIG_H + #include "config.h" /* for the gettext domain */ +#endif #include #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; @@ -40,7 +43,8 @@ struct lo_lines { /* 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 "; 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); } diff --git a/lineoperations/src/linefunctions.c b/lineoperations/src/lo_fns.c similarity index 72% rename from lineoperations/src/linefunctions.c rename to lineoperations/src/lo_fns.c index 76443554c..91fe55893 100644 --- a/lineoperations/src/linefunctions.c +++ b/lineoperations/src/lo_fns.c @@ -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 * @@ -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--; diff --git a/lineoperations/src/linefunctions.h b/lineoperations/src/lo_fns.h similarity index 85% rename from lineoperations/src/linefunctions.h rename to lineoperations/src/lo_fns.h index 4079b08dc..7d176919c 100644 --- a/lineoperations/src/linefunctions.h +++ b/lineoperations/src/lo_fns.h @@ -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 * @@ -21,8 +21,8 @@ -#ifndef LINEFUNCTIONS_H -#define LINEFUNCTIONS_H +#ifndef LO_FNS_H +#define LO_FNS_H #include #include "Scintilla.h" @@ -30,6 +30,13 @@ #include +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); diff --git a/lineoperations/src/lo_prefs.c b/lineoperations/src/lo_prefs.c new file mode 100644 index 000000000..b3df60870 --- /dev/null +++ b/lineoperations/src/lo_prefs.c @@ -0,0 +1,127 @@ +/* + * lo_prefs.c - Line operations, remove duplicate lines, empty lines, + * lines with only whitespace, sort lines. + * + * Copyright 2015 Sylvan Mostert + * + * 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 diff --git a/lineoperations/src/lo_prefs.h b/lineoperations/src/lo_prefs.h new file mode 100644 index 000000000..74ee1a6fb --- /dev/null +++ b/lineoperations/src/lo_prefs.h @@ -0,0 +1,59 @@ +/* + * lo_prefs.h - Line operations, remove duplicate lines, empty lines, + * lines with only whitespace, sort lines. + * + * Copyright 2015 Sylvan Mostert + * + * 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 +#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 diff --git a/po/POTFILES.in b/po/POTFILES.in index 0b0347792..e52bdba60 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -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