[gtksourceview] Add a sort line method to the buffer
- From: Paolo Borelli <pborelli src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview] Add a sort line method to the buffer
- Date: Sat, 16 May 2015 14:00:05 +0000 (UTC)
commit ef3d335e2608c26c0e02ab97244df510bfdf1952
Author: Paolo Borelli <pborelli gnome org>
Date: Fri May 15 23:37:06 2015 +0200
Add a sort line method to the buffer
docs/reference/gtksourceview-3.0-sections.txt | 2 +
gtksourceview/gtksourcebuffer.c | 178 +++++++++++++++++++++++++
gtksourceview/gtksourcebuffer.h | 24 ++++
tests/test-buffer.c | 46 +++++++
4 files changed, 250 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gtksourceview-3.0-sections.txt b/docs/reference/gtksourceview-3.0-sections.txt
index 87c335b..8d52945 100644
--- a/docs/reference/gtksourceview-3.0-sections.txt
+++ b/docs/reference/gtksourceview-3.0-sections.txt
@@ -6,6 +6,7 @@
GtkSourceBuffer
GtkSourceBracketMatchType
GtkSourceChangeCaseType
+GtkSourceSortFlags
gtk_source_buffer_new
gtk_source_buffer_new_with_language
<SUBSECTION Syntax Highlighting>
@@ -44,6 +45,7 @@ gtk_source_buffer_remove_source_marks
<SUBSECTION Other>
gtk_source_buffer_change_case
gtk_source_buffer_join_lines
+gtk_source_buffer_sort_lines
gtk_source_buffer_set_implicit_trailing_newline
gtk_source_buffer_get_implicit_trailing_newline
<SUBSECTION Standard>
diff --git a/gtksourceview/gtksourcebuffer.c b/gtksourceview/gtksourcebuffer.c
index b97a06d..c0ffa45 100644
--- a/gtksourceview/gtksourcebuffer.c
+++ b/gtksourceview/gtksourcebuffer.c
@@ -31,6 +31,7 @@
#include "gtksourcebuffer-private.h"
#include <string.h>
+#include <stdlib.h>
#include <gtk/gtk.h>
#include "gtksourcelanguage.h"
@@ -2709,6 +2710,183 @@ gtk_source_buffer_join_lines (GtkSourceBuffer *buffer,
gtk_text_buffer_delete_mark (text_buffer, end_mark);
}
+static gchar *
+get_line_slice (GtkTextBuffer *buf,
+ gint line)
+{
+ GtkTextIter start, end;
+
+ gtk_text_buffer_get_iter_at_line (buf, &start, line);
+ end = start;
+
+ if (!gtk_text_iter_ends_line (&start))
+ {
+ gtk_text_iter_forward_to_line_end (&end);
+ }
+
+ return gtk_text_buffer_get_slice (buf, &start, &end, TRUE);
+}
+
+typedef struct {
+ gchar *line; /* the original text to re-insert */
+ gchar *key; /* the key to use for the comparison */
+} SortLine;
+
+static gint
+compare_line (gconstpointer aptr,
+ gconstpointer bptr)
+{
+ const SortLine *a = aptr;
+ const SortLine *b = bptr;
+
+ return g_strcmp0 (a->key, b->key);
+}
+
+static gint
+compare_line_reversed (gconstpointer aptr,
+ gconstpointer bptr)
+{
+ const SortLine *a = aptr;
+ const SortLine *b = bptr;
+
+ return g_strcmp0 (b->key, a->key);
+}
+
+/**
+ * gtk_source_buffer_sort_lines:
+ * @buffer: a #GtkSourceBuffer.
+ * @start: a #GtkTextIter.
+ * @end: a #GtkTextIter.
+ * @flags: #GtkSourceSortFlags specifying how the sort should behave
+ * @column: sort considering the text starting at the given column
+ *
+ * Sort the lines of text between the specified iterators.
+ *
+ * Since: 3.18
+ */
+void
+gtk_source_buffer_sort_lines (GtkSourceBuffer *buffer,
+ GtkTextIter *start,
+ GtkTextIter *end,
+ GtkSourceSortFlags flags,
+ gint column)
+{
+ GtkTextBuffer *text_buffer;
+ gint start_line;
+ gint end_line;
+ gint num_lines;
+ SortLine *lines;
+ gchar *last_line = NULL;
+ gint i;
+
+ g_return_if_fail (GTK_SOURCE_IS_BUFFER (buffer));
+ g_return_if_fail (start != NULL);
+ g_return_if_fail (end != NULL);
+
+ text_buffer = GTK_TEXT_BUFFER (buffer);
+
+ gtk_text_iter_order (start, end);
+
+ start_line = gtk_text_iter_get_line (start);
+ end_line = gtk_text_iter_get_line (end);
+
+ /* if we are at line start our last line is the previus one.
+ * Otherwise the last line is the current one but we try to
+ * move the iter after the line terminator */
+ if (gtk_text_iter_get_line_offset (end) == 0)
+ {
+ end_line = MAX (start_line, end_line - 1);
+ }
+ else
+ {
+ gtk_text_iter_forward_line (end);
+ }
+
+ num_lines = end_line - start_line + 1;
+ lines = g_new0 (SortLine, num_lines);
+
+ for (i = 0; i < num_lines; i++)
+ {
+ gchar *line;
+ gboolean free_line = FALSE;
+ glong length;
+
+ lines[i].line = get_line_slice (text_buffer, start_line + i);
+
+ if ((flags & GTK_SOURCE_SORT_FLAGS_CASE_SENSITIVE) != 0)
+ {
+ line = lines[i].line;
+ }
+ else
+ {
+ line = g_utf8_casefold (lines[i].line, -1);
+ free_line = TRUE;
+ }
+
+ length = g_utf8_strlen (line, -1);
+
+ if (length < column)
+ {
+ lines[i].key = NULL;
+ }
+ else if (column > 0)
+ {
+ gchar *substring;
+
+ substring = g_utf8_offset_to_pointer (line, column);
+ lines[i].key = g_utf8_collate_key (substring, -1);
+ }
+ else
+ {
+ lines[i].key = g_utf8_collate_key (line, -1);
+ }
+
+ if (free_line)
+ {
+ g_free (line);
+ }
+ }
+
+ if ((flags & GTK_SOURCE_SORT_FLAGS_REVERSE_ORDER) != 0)
+ {
+ qsort (lines, num_lines, sizeof (SortLine), compare_line_reversed);
+ }
+ else
+ {
+ qsort (lines, num_lines, sizeof (SortLine), compare_line);
+ }
+
+ _gtk_source_buffer_save_and_clear_selection (buffer);
+ gtk_text_buffer_begin_user_action (text_buffer);
+
+ gtk_text_buffer_delete (text_buffer, start, end);
+
+ for (i = 0; i < num_lines; i++)
+ {
+ if ((flags & GTK_SOURCE_SORT_FLAGS_REMOVE_DUPLICATES) != 0 &&
+ g_strcmp0 (last_line, lines[i].line) == 0)
+ {
+ continue;
+ }
+
+ gtk_text_buffer_insert (text_buffer, start, lines[i].line, -1);
+ gtk_text_buffer_insert (text_buffer, start, "\n", -1);
+
+ last_line = lines[i].line;
+ }
+
+ gtk_text_buffer_end_user_action (text_buffer);
+ _gtk_source_buffer_restore_selection (buffer);
+
+ for (i = 0; i < num_lines; i++)
+ {
+ g_free (lines[i].line);
+ g_free (lines[i].key);
+ }
+
+ g_free (lines);
+}
+
/**
* gtk_source_buffer_set_undo_manager:
* @buffer: a #GtkSourceBuffer.
diff --git a/gtksourceview/gtksourcebuffer.h b/gtksourceview/gtksourcebuffer.h
index 2f5830b..373b304 100644
--- a/gtksourceview/gtksourcebuffer.h
+++ b/gtksourceview/gtksourcebuffer.h
@@ -74,6 +74,24 @@ typedef enum
GTK_SOURCE_CHANGE_CASE_TITLE
} GtkSourceChangeCaseType;
+/**
+ * GtkSourceSortFlags:
+ * @GTK_SOURCE_SORT_FLAGS_NONE: no flags specified
+ * @GTK_SOURCE_SORT_FLAGS_CASE_SENSITIVE: case sensitive sort
+ * @GTK_SOURCE_SORT_FLAGS_REVERSE_ORDER: sort in reverse order
+ * @GTK_SOURCE_SORT_FLAGS_REMOVE_DUPLICATES: remove duplicates
+ *
+ * Since: 3.18
+ */
+typedef enum
+{
+ GTK_SOURCE_SORT_FLAGS_NONE = 0,
+ GTK_SOURCE_SORT_FLAGS_CASE_SENSITIVE = 1 << 0,
+ GTK_SOURCE_SORT_FLAGS_REVERSE_ORDER = 1 << 1,
+ GTK_SOURCE_SORT_FLAGS_REMOVE_DUPLICATES = 1 << 2,
+} GtkSourceSortFlags;
+
+
struct _GtkSourceBuffer
{
GtkTextBuffer parent_instance;
@@ -197,6 +215,12 @@ void gtk_source_buffer_join_lines
(GtkSourceBuffer *buffer,
GtkTextIter
*start,
GtkTextIter *end);
+void gtk_source_buffer_sort_lines (GtkSourceBuffer
*buffer,
+ GtkTextIter
*start,
+ GtkTextIter *end,
+ GtkSourceSortFlags flags,
+ gint
column);
+
GtkSourceUndoManager *gtk_source_buffer_get_undo_manager (GtkSourceBuffer
*buffer);
void gtk_source_buffer_set_undo_manager (GtkSourceBuffer
*buffer,
diff --git a/tests/test-buffer.c b/tests/test-buffer.c
index dae0ae2..fdab630 100644
--- a/tests/test-buffer.c
+++ b/tests/test-buffer.c
@@ -221,6 +221,51 @@ test_join_lines (void)
g_object_unref (buffer);
}
+static void
+do_test_sort_lines (GtkSourceBuffer *buffer,
+ const gchar *text,
+ const gchar *expected,
+ gint start_offset,
+ gint end_offset,
+ GtkSourceSortFlags flags,
+ gint column)
+{
+ GtkTextIter start;
+ GtkTextIter end;
+ gchar *changed;
+
+ gtk_text_buffer_set_text (GTK_TEXT_BUFFER (buffer), text, -1);
+
+ gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &start, start_offset);
+ gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (buffer), &end, end_offset);
+
+ gtk_source_buffer_sort_lines (buffer, &start, &end, flags, column);
+
+ gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), &start, &end);
+ changed = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (buffer), &start, &end, TRUE);
+
+ g_assert_cmpstr (changed, ==, expected);
+
+ g_free (changed);
+}
+
+static void
+test_sort_lines (void)
+{
+ GtkSourceBuffer *buffer;
+
+ buffer = gtk_source_buffer_new (NULL);
+
+ do_test_sort_lines (buffer, "aaa\nbbb\n", "aaa\nbbb\n", 0, -1, 0, 0);
+ do_test_sort_lines (buffer, "bbb\naaa\n", "aaa\nbbb\n", 0, -1, 0, 0);
+ do_test_sort_lines (buffer, "aaa\nbbb\n", "bbb\naaa\n", 0, -1, GTK_SOURCE_SORT_FLAGS_REVERSE_ORDER,
0);
+ do_test_sort_lines (buffer, "aaa\nbbb\naaa\n", "aaa\nbbb\n", 0, -1,
GTK_SOURCE_SORT_FLAGS_REMOVE_DUPLICATES, 0);
+ do_test_sort_lines (buffer, "bbb\naaa\nCCC\n", "CCC\naaa\nbbb\n", 0, -1,
GTK_SOURCE_SORT_FLAGS_CASE_SENSITIVE, 0);
+ do_test_sort_lines (buffer, "aaabbb\nbbbaaa\n", "bbbaaa\naaabbb\n", 0, -1, 0, 3);
+
+ g_object_unref (buffer);
+}
+
int
main (int argc, char** argv)
{
@@ -232,6 +277,7 @@ main (int argc, char** argv)
g_test_add_func ("/Buffer/get-context-classes", test_get_context_classes);
g_test_add_func ("/Buffer/change-case", test_change_case);
g_test_add_func ("/Buffer/join-lines", test_join_lines);
+ g_test_add_func ("/Buffer/sort-lines", test_sort_lines);
return g_test_run();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]