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