Branch: refs/heads/master Author: Sylvan Mostert smostert.dev@gmail.com Committer: Sylvan Mostert smostert.dev@gmail.com Date: Fri, 09 Sep 2016 05:45:32 UTC Commit: f0fa9e8c150b36ae6b1be241299ad70266cf5367 https://github.com/geany/geany-plugins/commit/f0fa9e8c150b36ae6b1be241299ad7...
Log Message: ----------- lineoperations: added selection support
If there is a selection, the Operation will be applied to the lines in the selection, and if there is no selection, the Operation will be applied to the whole file.
Adjusted `rmemtyln` and `rmwhspln` to accept first line and end line for selection.
Modified Paths: -------------- lineoperations/src/linefunctions.c lineoperations/src/linefunctions.h lineoperations/src/lineoperations.c
Modified: lineoperations/src/linefunctions.c 219 lines changed, 62 insertions(+), 157 deletions(-) =================================================================== @@ -22,21 +22,6 @@ #include "linefunctions.h"
-/* altered from geany/src/editor.c, ensure new line at file end */ -static void ensure_final_newline(GeanyEditor *editor, gint max_lines) -{ - gint end_document = sci_get_position_from_line(editor->sci, max_lines); - gboolean append_newline = end_document > - sci_get_position_from_line(editor->sci, max_lines - 1); - - if (append_newline) - { - const gchar *eol = editor_get_eol_char(editor); - sci_insert_text(editor->sci, end_document, eol); - } -} - - /* comparison function to be used in qsort */ static gint compare_asc(const void * a, const void * b) { @@ -52,235 +37,155 @@ static gint compare_desc(const void * a, const void * b)
/* Remove Duplicate Lines, sorted */ -void rmdupst(GeanyDocument *doc) { - gint total_num_chars; /* number of characters in the document */ - gint total_num_lines; /* number of lines in the document */ - gchar **lines; /* array to hold all lines in the document */ - gchar *new_file; /* *final* string to replace current document */ - gchar *nf_end; /* points to end of new_file */ - gchar *lineptr; /* temporary line pointer */ - gint i; /* iterator */ - - total_num_chars = sci_get_length(doc->editor->sci); - total_num_lines = sci_get_line_count(doc->editor->sci); - lines = g_malloc(sizeof(gchar *) * total_num_lines); - new_file = g_malloc(sizeof(gchar) * (total_num_chars+1)); - new_file[0] = '\0'; - nf_end = new_file; - lineptr = (gchar *)""; - - - /* if file is not empty, ensure that the file ends with newline */ - if(total_num_lines != 1) - ensure_final_newline(doc->editor, total_num_lines); - - /* copy *all* lines into **lines array */ - for(i = 0; i < total_num_lines; i++) - lines[i] = sci_get_line(doc->editor->sci, i); +void +rmdupst(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file) +{ + gchar *nf_end = new_file; /* points to last char of new_file */ + gchar *lineptr = (gchar *)""; /* temporary line pointer */ + gint i = 0; /* iterator */
/* sort **lines ascending */ - qsort(lines, total_num_lines, sizeof(gchar *), compare_asc); + qsort(lines, num_lines, sizeof(gchar *), compare_asc);
/* loop through **lines, join first occurances into one str (new_file) */ - for(i = 0; i < total_num_lines; i++) + for(i = 0; i < num_lines; i++) + { if(strcmp(lines[i], lineptr) != 0) { lineptr = lines[i]; nf_end = g_stpcpy(nf_end, lines[i]); } - - /* set new document */ - sci_set_text(doc->editor->sci, new_file); - - /* free used memory */ - for(i = 0; i < total_num_lines; i++) - g_free(lines[i]); - g_free(lines); - g_free(new_file); + } }
/* Remove Duplicate Lines, ordered */ -void rmdupln(GeanyDocument *doc) { - gint total_num_chars; /* number of characters in the document */ - gint total_num_lines; /* number of lines in the document */ - gchar **lines; /* array to hold all lines in the document */ - gchar *new_file; /* *final* string to replace current document */ - gchar *nf_end; /* points to end of new_file */ - gint i; /* iterator */ - gint j; /* iterator */ - gboolean *to_remove; /* flag to 'mark' which lines to remove */ - - total_num_chars = sci_get_length(doc->editor->sci); - total_num_lines = sci_get_line_count(doc->editor->sci); - lines = g_malloc(sizeof(gchar *) * total_num_lines); - new_file = g_malloc(sizeof(gchar) * (total_num_chars+1)); - new_file[0] = '\0'; - nf_end = new_file; - - - /* if file is not empty, ensure that the file ends with newline */ - if(total_num_lines != 1) - ensure_final_newline(doc->editor, total_num_lines); - - /* copy *all* lines into **lines array */ - for(i = 0; i < total_num_lines; i++) - lines[i] = sci_get_line(doc->editor->sci, i); +void +rmdupln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file) +{ + gchar *nf_end = new_file; /* points to last char of new_file */ + gint i = 0; /* iterator */ + gint j = 0; /* iterator */ + gboolean *to_remove = NULL; /* flag to 'mark' which lines to remove */ +
/* allocate and set *to_remove to all FALSE * to_remove[i] represents whether lines[i] should be removed */ - to_remove = g_malloc(sizeof(gboolean) * total_num_lines); - for(i = 0; i < (total_num_lines); i++) + to_remove = g_malloc(sizeof(gboolean) * num_lines); + for(i = 0; i < (num_lines); i++) to_remove[i] = FALSE;
/* find which **lines are duplicate, and mark them as duplicate */ - for(i = 0; i < total_num_lines; i++) /* loop through **lines */ + for(i = 0; i < num_lines; i++) /* loop through **lines */ + { /* make sure that the line is not already duplicate */ if(!to_remove[i]) + { /* find the rest of same lines */ - for(j = (i+1); j < total_num_lines; j++) + for(j = (i+1); j < num_lines; j++) + { if(!to_remove[j] && strcmp(lines[i], lines[j]) == 0) to_remove[j] = TRUE; /* line is duplicate, mark to remove */ + } + } + }
/* copy **lines into 'new_file' if it is not FALSE(not duplicate) */ - for(i = 0; i < total_num_lines; i++) + for(i = 0; i < num_lines; i++) if(!to_remove[i]) nf_end = g_stpcpy(nf_end, lines[i]);
- /* set new document */ - sci_set_text(doc->editor->sci, new_file); - /* free used memory */ - for(i = 0; i < total_num_lines; i++) - g_free(lines[i]); - g_free(lines); - g_free(new_file); g_free(to_remove); }
/* Remove Unique Lines */ -void rmunqln(GeanyDocument *doc) { - gint total_num_chars; /* number of characters in the document */ - gint total_num_lines; /* number of lines in the document */ - gchar **lines; /* array to hold all lines in the document */ - gchar *new_file; /* *final* string to replace current document */ - gchar *nf_end; /* points to end of new_file */ - gint i; /* iterator */ - gint j; /* iterator */ - gboolean *to_remove; /* to 'mark' which lines to remove */ - - total_num_chars = sci_get_length(doc->editor->sci); - total_num_lines = sci_get_line_count(doc->editor->sci); - lines = g_malloc(sizeof(gchar *) * total_num_lines); - new_file = g_malloc(sizeof(gchar) * (total_num_chars+1)); - new_file[0] = '\0'; - nf_end = new_file; - - - /* if file is not empty, ensure that the file ends with newline */ - if(total_num_lines != 1) - ensure_final_newline(doc->editor, total_num_lines); - - /* copy *all* lines into **lines array */ - for(i = 0; i < total_num_lines; i++) - lines[i] = sci_get_line(doc->editor->sci, i); +void +rmunqln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file) +{ + gchar *nf_end = new_file; /* points to last char of new_file */ + gint i = 0; /* iterator */ + gint j = 0; /* iterator */ + gboolean *to_remove = NULL; /* to 'mark' which lines to remove */
/* allocate and set *to_remove to all TRUE * to_remove[i] represents whether lines[i] should be removed */ - to_remove = g_malloc(sizeof(gboolean) * total_num_lines); - for(i = 0; i < total_num_lines; i++) + to_remove = g_malloc(sizeof(gboolean) * num_lines); + for(i = 0; i < num_lines; i++) to_remove[i] = TRUE;
/* find all unique lines and set them to FALSE (not to be removed) */ - for(i = 0; i < total_num_lines; i++) + for(i = 0; i < num_lines; i++) /* make sure that the line is not already determined to be unique */ if(to_remove[i]) - for(j = (i+1); j < total_num_lines; j++) + for(j = (i+1); j < num_lines; j++) if(to_remove[j] && strcmp(lines[i], lines[j]) == 0) { to_remove[i] = FALSE; to_remove[j] = FALSE; }
/* copy **lines into 'new_file' if it is not FALSE(not duplicate) */ - for(i = 0; i < total_num_lines; i++) + for(i = 0; i < num_lines; i++) if(!to_remove[i]) nf_end = g_stpcpy(nf_end, lines[i]);
- /* set new document */ - sci_set_text(doc->editor->sci, new_file); - /* free used memory */ - for(i = 0; i < total_num_lines; i++) - g_free(lines[i]); - g_free(lines); - g_free(new_file); g_free(to_remove); }
/* Remove Empty Lines */ -void rmemtyln(GeanyDocument *doc) { - gint total_num_lines; /* number of lines in the document */ - gint i; /* iterator */ - - total_num_lines = sci_get_line_count(doc->editor->sci); - - sci_start_undo_action(doc->editor->sci); +void +rmemtyln(GeanyDocument *doc, gint line_num, gint end_line_num) +{
- for(i = 0; i < total_num_lines; i++) /* loop through opened doc */ + while(line_num <= end_line_num) /* loop through lines */ { + /* check if the first posn of the line is also the end of line posn */ if(sci_get_position_from_line(doc->editor->sci, i) == sci_get_line_end_position(doc->editor->sci, i)) { scintilla_send_message(doc->editor->sci, - SCI_DELETERANGE, - sci_get_position_from_line(doc->editor->sci, i), - sci_get_line_length(doc->editor->sci, i)); - total_num_lines--; - i--; + SCI_DELETERANGE, + sci_get_position_from_line(doc->editor->sci, line_num), + sci_get_line_length(doc->editor->sci, line_num)); + line_num--; + end_line_num--; } } - - sci_end_undo_action(doc->editor->sci); }
/* Remove Whitespace Lines */ -void rmwhspln(GeanyDocument *doc) { - gint total_num_lines; /* number of lines in the document */ - gint indent; - gint i; /* iterator */ - - total_num_lines = sci_get_line_count(doc->editor->sci); - - sci_start_undo_action(doc->editor->sci); +void +rmwhspln(GeanyDocument *doc, gint line_num, gint end_line_num) +{ + gint indent; /* indent position */
- for(i = 0; i < total_num_lines; i++) /* loop through opened doc */ + while(line_num <= end_line_num) /* loop through lines */ { indent = scintilla_send_message(doc->editor->sci, SCI_GETLINEINDENTPOSITION, i, 0);
+ /* check if the posn of indentation is also the end of line posn */ if(indent - sci_get_position_from_line(doc->editor->sci, i) == sci_get_line_end_position(doc->editor->sci, i)- sci_get_position_from_line(doc->editor->sci, i)) { scintilla_send_message(doc->editor->sci, - SCI_DELETERANGE, - sci_get_position_from_line(doc->editor->sci, i), - sci_get_line_length(doc->editor->sci, i)); - total_num_lines--; - i--; + SCI_DELETERANGE, + sci_get_position_from_line(doc->editor->sci, line_num), + sci_get_line_length(doc->editor->sci, line_num)); + line_num--; + end_line_num--; }
} - - - sci_end_undo_action(doc->editor->sci); }
Modified: lineoperations/src/linefunctions.h 25 lines changed, 17 insertions(+), 8 deletions(-) =================================================================== @@ -1,5 +1,6 @@ /* - * linefunctions.h - Line operations, remove duplicate lines, empty lines, lines with only whitespace, sort lines. + * linefunctions.h - Line operations, remove duplicate lines, empty lines, + * lines with only whitespace, sort lines. * * Copyright 2015 Sylvan Mostert smostert.dev@gmail.com * @@ -30,29 +31,37 @@
/* Remove Duplicate Lines, sorted */ -void rmdupst(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file); +void +rmdupst(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
/* Remove Duplicate Lines, ordered */ -void rmdupln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file); +void +rmdupln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
/* Remove Unique Lines */ -void rmunqln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file); +void +rmunqln(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
/* Remove Empty Lines */ -void rmemtyln(GeanyDocument *doc, gint num_lines); +void +rmemtyln(GeanyDocument *doc, gint line_num, gint end_line_num);
/* Remove Whitespace Lines */ -void rmwhspln(GeanyDocument *doc, gint num_lines); +void +rmwhspln(GeanyDocument *doc, gint line_num, gint end_line_num);
/* Sort Lines Ascending */ -void sortlinesasc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file); +void +sortlnsasc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file); +
/* Sort Lines Descending */ -void sortlinesdesc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file); +void +sortlndesc(GeanyDocument *doc, gchar **lines, gint num_lines, gchar *new_file);
#endif
Modified: lineoperations/src/lineoperations.c 148 lines changed, 119 insertions(+), 29 deletions(-) =================================================================== @@ -1,5 +1,6 @@ /* - * lineoperations.c - Line operations, remove duplicate lines, empty lines, lines with only whitespace, sort lines. + * lineoperations.c - Line operations, remove duplicate lines, empty lines, + * lines with only whitespace, sort lines. * * Copyright 2015 Sylvan Mostert smostert.dev@gmail.com * @@ -30,12 +31,74 @@ static GtkWidget *main_menu_item = NULL;
+/* represents lines that will have Operation applied to */ +struct lo_lines { + gboolean is_selection; + gint start_posn_line; + gint end_posn_line; +}; + + +/* select lines in document based on lo_lines struct parameter */ +static void +select_lines(GeanyDocument *doc, struct lo_lines sel) +{ + /* set the selection to beginning of first line */ + sci_set_selection_start(doc->editor->sci, + sci_get_position_from_line(doc->editor->sci, sel.start_posn_line)); + + /* set the selection to end of last line */ + sci_set_selection_end(doc->editor->sci, + sci_get_line_end_position(doc->editor->sci, sel.end_posn_line) + + editor_get_eol_char_len(doc->editor)); +} + + +/* get lo_lines struct based off of document */ +static struct lo_lines +get_current_sel_lines(GeanyDocument *doc) +{ + struct lo_lines sel = { 0, 0 }; + gint start_posn = 0; /* position of selection start */ + gint end_posn = 0; /* position of selection end */ + + /* check for selection */ + if(sci_has_selection(doc->editor->sci)) + { + /* get the start and end positions */ + start_posn = sci_get_selection_start(doc->editor->sci); + end_posn = sci_get_selection_end (doc->editor->sci); + + /* get the line number of those positions */ + sel.start_posn_line = scintilla_send_message(doc->editor->sci, + SCI_LINEFROMPOSITION, + start_posn, 0); + + sel.end_posn_line = scintilla_send_message(doc->editor->sci, + SCI_LINEFROMPOSITION, + end_posn, 0); + + sel.is_selection = TRUE; + } + else + { + /* if there is no selection, start at first line */ + sel.start_posn_line = 0; + /* and end at last one */ + sel.end_posn_line = (sci_get_line_count(doc->editor->sci) - 1); + + sel.is_selection = FALSE; + } + + return sel; +} +
/* altered from geany/src/editor.c, ensure new line at file end */ static void ensure_final_newline(GeanyEditor *editor, gint max_lines) { - gint end_document = sci_get_position_from_line(editor->sci, max_lines); + gint end_document = sci_get_position_from_line(editor->sci, max_lines); gboolean append_newline = end_document > sci_get_position_from_line(editor->sci, max_lines - 1);
@@ -47,38 +110,57 @@ ensure_final_newline(GeanyEditor *editor, gint max_lines) }
-/* - * functions with indirect scintilla manipulation - * e.g. requires **lines array, *new_file... +/* + * Menu action for functions with indirect scintilla manipulation + * e.g. functions requiring **lines array, *new_file... */ static void action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata) { - void (*func)(GeanyDocument *, gchar **, gint, gchar *) = gdata; - GeanyDocument *doc = document_get_current(); - - gint num_chars = sci_get_length(doc->editor->sci); - gint num_lines = sci_get_line_count(doc->editor->sci); - gchar **lines = g_malloc(sizeof(gchar *) * num_lines); - gchar *new_file = g_malloc(sizeof(gchar) * (num_chars+1)); - gint i = 0; + /* function pointer to gdata -- function to be used */ + void (*func)(GeanyDocument * doc, + gchar **lines, + gint num_lines, + gchar *new_file) = gdata; + + GeanyDocument *doc = document_get_current(); + struct lo_lines sel = get_current_sel_lines(doc); + gint num_chars = 0; + gint num_lines = (sel.end_posn_line - sel.start_posn_line) + 1; + gchar **lines = g_malloc(sizeof(gchar *) * num_lines); + gint i = 0; + + /* get num_chars and **lines */ + for(i = 0; i < num_lines; i++) + { + num_chars += (sci_get_line_length(doc->editor->sci, + (i + sel.start_posn_line))); + lines[i] = sci_get_line(doc->editor->sci, + (i + sel.start_posn_line)); + } + + gchar *new_file = g_malloc(sizeof(gchar) * (num_chars + 1)); new_file[0] = '\0';
- - /* copy *all* lines into **lines array */ - for(i = 0; i < num_lines; i++) - lines[i] = sci_get_line(doc->editor->sci, i); + /* select lines to indicate to user what lines were altered */ + select_lines(doc, sel);
sci_start_undo_action(doc->editor->sci);
/* if file is not empty, ensure that the file ends with newline */ - if(num_lines != 1) + if((!sel.is_selection && num_lines != 1) || (sel.is_selection && + sel.end_posn_line == (sci_get_line_count(doc->editor->sci) - 1))) + { ensure_final_newline(doc->editor, num_lines); + }
if(doc) func(doc, lines, num_lines, new_file);
/* set new document */ - sci_set_text(doc->editor->sci, new_file); + if(sci_has_selection(doc->editor->sci)) + sci_replace_sel(doc->editor->sci, new_file); + else + sci_set_text(doc->editor->sci, new_file);
sci_end_undo_action(doc->editor->sci);
@@ -90,21 +172,25 @@ action_indir_manip_item(GtkMenuItem *menuitem, gpointer gdata) }
-/* - * functions with direct scintilla manipulation + +/* + * Menu action for functions with direct scintilla manipulation * e.g. no need for **lines array, *new_file... */ static void action_sci_manip_item(GtkMenuItem *menuitem, gpointer gdata) { - void (*func)(GeanyDocument *, gint) = gdata; - GeanyDocument *doc = document_get_current(); + /* function pointer to gdata -- function to be used */ + void (*func)(GeanyDocument *, gint, gint) = gdata; + GeanyDocument *doc = document_get_current(); + struct lo_lines sel = get_current_sel_lines(doc);
- gint num_lines = sci_get_line_count(doc->editor->sci); + /* select lines to indicate to user what lines were altered */ + select_lines(doc, sel);
sci_start_undo_action(doc->editor->sci);
- if(doc) func(doc, num_lines); + if(doc) func(doc, sel.start_posn_line, sel.end_posn_line);
sci_end_undo_action(doc->editor->sci); } @@ -135,9 +221,9 @@ lo_init(GeanyPlugin *plugin, gpointer gdata) G_CALLBACK(action_sci_manip_item), (gpointer) rmwhspln }, { NULL }, { N_("Sort Lines _Ascending"), - G_CALLBACK(action_indir_manip_item), (gpointer) sortlinesasc }, + G_CALLBACK(action_indir_manip_item), (gpointer) sortlnsasc }, { N_("Sort Lines _Descending"), - G_CALLBACK(action_indir_manip_item), (gpointer) sortlinesdesc } + G_CALLBACK(action_indir_manip_item), (gpointer) sortlndesc } };
main_menu_item = gtk_menu_item_new_with_mnemonic(_("_Line Operations")); @@ -155,7 +241,10 @@ lo_init(GeanyPlugin *plugin, gpointer gdata) else { item = gtk_menu_item_new_with_mnemonic(_(menu_items[i].label)); - g_signal_connect(item, "activate", menu_items[i].cb_activate, menu_items[i].cb_data); + g_signal_connect(item, + "activate", + menu_items[i].cb_activate, + menu_items[i].cb_data); ui_add_document_sensitive(item); }
@@ -164,7 +253,8 @@ lo_init(GeanyPlugin *plugin, gpointer gdata) }
gtk_menu_item_set_submenu(GTK_MENU_ITEM(main_menu_item), submenu); - gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), main_menu_item); + gtk_container_add(GTK_CONTAINER(geany->main_widgets->tools_menu), + main_menu_item);
return TRUE; }
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org