[nautilus] files-view: change "New Folder /w Selection" to offer a name



commit ca0e00b6b3c48a61f0ad091e6ae16d4f4e3e39fb
Author: Neil Herald <neil herald gmail com>
Date:   Sun Apr 3 13:28:11 2016 +0100

    files-view: change "New Folder /w Selection" to offer a name
    
    New Folder with Selection currently doesn't offer a folder name. It
    would be better if it suggested a folder name based on the files that
    are selected.
    
    With this change, it now looks for a common filename prefix of the
    selected files, and pre-populates the folder name entry with that. If no
    common prefix is found that is greater than 3 characters long, the
    folder name entry will be left blank.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=747907

 eel/eel-string.c                                   |  126 +++++
 eel/eel-string.h                                   |   18 +
 src/nautilus-file-utilities.c                      |   54 ++
 src/nautilus-file-utilities.h                      |   22 +
 src/nautilus-files-view.c                          |   13 +
 test/Makefile.am                                   |   15 +
 test/test-eel-string-get-common-prefix.c           |  188 +++++++
 test/test-eel-string-rtrim-punctuation.c           |  121 +++++
 ...est-file-utilities-get-common-filename-prefix.c |  534 ++++++++++++++++++++
 9 files changed, 1091 insertions(+), 0 deletions(-)
---
diff --git a/eel/eel-string.c b/eel/eel-string.c
index 28c7e50..e0f849c 100644
--- a/eel/eel-string.c
+++ b/eel/eel-string.c
@@ -208,6 +208,132 @@ eel_str_replace_substring (const char *string,
        return result;
 }
 
+char *
+eel_str_rtrim_punctuation (char *str)
+{
+       int num_punctuation_chars;
+       int str_len;
+       int num_chars_left;
+       char *current_char_pos;
+       gunichar current_char;
+
+       num_punctuation_chars = 0;
+       str_len = g_utf8_strlen (str, -1);
+       current_char_pos = g_utf8_offset_to_pointer (str, str_len);
+
+       while (num_punctuation_chars <= str_len) {
+               current_char_pos = g_utf8_prev_char (current_char_pos);
+               current_char = g_utf8_get_char (current_char_pos);
+
+               if (!g_unichar_ispunct (current_char) && !g_unichar_isspace (current_char))
+                       break;
+
+               ++num_punctuation_chars;
+       }
+
+       if (num_punctuation_chars == 0)
+               return g_strdup (str);
+
+       num_chars_left = str_len - num_punctuation_chars;
+
+       return g_utf8_substring (str, 0, num_chars_left);
+}
+
+/**
+ * get_common_prefix_length:
+ * @str_a: first string
+ * @str_b: second string
+ * @min_required_len: the minimum number of characters required in the prefix
+ *
+ * Returns: the size of the common prefix of two strings, in characters.
+ * If there's no common prefix, or the common prefix is smaller than
+ * min_required_len, this will return -1
+ */
+static int
+get_common_prefix_length (char *str_a,
+                         char *str_b,
+                         int   min_required_len)
+{
+       int a_len;
+       int b_len;
+       int intersection_len;
+       int matching_chars;
+       char *a;
+       char *b;
+
+       a_len = g_utf8_strlen (str_a, -1);
+       b_len = g_utf8_strlen (str_b, -1);
+
+       intersection_len = MIN (a_len, b_len);
+       if (intersection_len < min_required_len)
+               return -1;
+
+       matching_chars = 0;
+       a = str_a;
+       b = str_b;
+       while (matching_chars < intersection_len) {
+               if (g_utf8_get_char (a) != g_utf8_get_char (b))
+                       break;
+
+               ++matching_chars;
+
+               a = g_utf8_next_char (a);
+               b = g_utf8_next_char (b);
+       }
+
+       if (matching_chars < min_required_len)
+               return -1;
+
+       return matching_chars;
+}
+
+char *
+eel_str_get_common_prefix (GList *strs, int min_required_len)
+{
+       GList *l;
+       char *common_part;
+       char *name;
+       char *truncated;
+       int matching_chars;
+
+       if (strs == NULL)
+               return NULL;
+
+       common_part = NULL;
+       for (l = strs; l != NULL; l = l->next) {
+
+               name = l->data;
+               if (name == NULL) {
+                       g_free (common_part);
+                       return NULL;
+               }
+
+               if (l->prev == NULL) {
+                       common_part = g_strdup (name);
+                       continue;
+               }
+
+               matching_chars = get_common_prefix_length (common_part, name, min_required_len);
+
+               if (matching_chars == -1) {
+                       g_free (common_part);
+                       return NULL;
+               }
+
+               truncated = g_utf8_substring (common_part, 0, matching_chars);
+               g_free (common_part);
+               common_part = truncated;
+       }
+
+       matching_chars = g_utf8_strlen (common_part, -1);
+       if (matching_chars < min_required_len) {
+               g_free (common_part);
+               return NULL;
+       }
+
+       return common_part;
+}
+
 /**************** Custom printf ***********/
 
 typedef struct {
diff --git a/eel/eel-string.h b/eel/eel-string.h
index 202eec2..98cca7e 100644
--- a/eel/eel-string.h
+++ b/eel/eel-string.h
@@ -57,6 +57,24 @@ char *   eel_str_strip_substring_and_after (const char    *str,
 char *   eel_str_replace_substring         (const char    *str,
                                            const char    *substring,
                                            const char    *replacement);
+/**
+ * eel_str_rtrim_punctuation:
+ * @str: string
+ *
+ * Returns: a copy of str with trailing punctuation characters removed
+ */
+char *   eel_str_rtrim_punctuation         (char *str);
+
+
+/**
+ * eel_str_get_common_prefix:
+ * @str: set of strings
+ * @min_required_len: the minimum number of characters required in the prefix
+ *
+ * Returns: the common prefix for a set of strings, or NULL if there isn't a
+ * common prefix of length min_required_len
+ */
+char *   eel_str_get_common_prefix         (GList *strs, int min_required_len);
 
 typedef char * eel_ref_str;
 
diff --git a/src/nautilus-file-utilities.c b/src/nautilus-file-utilities.c
index 40b37df..14929aa 100644
--- a/src/nautilus-file-utilities.c
+++ b/src/nautilus-file-utilities.c
@@ -1149,6 +1149,60 @@ nautilus_file_selection_equal (GList *selection_a,
        return selection_matches;
 }
 
+char *
+nautilus_get_common_filename_prefix (GList *file_list,
+                                     int    min_required_len)
+{
+        GList *l;
+        GList *strs = NULL;
+        char *name;
+        char *result;
+
+        if (file_list == NULL)
+                return NULL;
+
+        for (l = file_list; l != NULL; l = l->next) {
+                g_return_val_if_fail (NAUTILUS_IS_FILE (l->data), NULL);
+
+                name = nautilus_file_get_display_name (l->data);
+                strs = g_list_append (strs, name);
+        }
+
+        result = nautilus_get_common_filename_prefix_from_filenames (strs, min_required_len);
+        g_list_free_full (strs, g_free);
+
+        return result;
+}
+
+char *
+nautilus_get_common_filename_prefix_from_filenames (GList *filenames,
+                                                    int    min_required_len)
+{
+        char *common_prefix;
+        char *truncated;
+        int common_prefix_len;
+
+        common_prefix = eel_str_get_common_prefix (filenames, min_required_len);
+
+        if (common_prefix == NULL)
+                return NULL;
+
+        truncated = eel_filename_strip_extension (common_prefix);
+        g_free (common_prefix);
+        common_prefix = truncated;
+
+        truncated = eel_str_rtrim_punctuation (common_prefix);
+        g_free (common_prefix);
+
+        common_prefix_len = g_utf8_strlen (truncated, -1);
+        if (common_prefix_len < min_required_len) {
+                g_free (truncated);
+                return NULL;
+        }
+
+        return truncated;
+}
+
 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
 
 void
diff --git a/src/nautilus-file-utilities.h b/src/nautilus-file-utilities.h
index ee5f624..6d46df5 100644
--- a/src/nautilus-file-utilities.h
+++ b/src/nautilus-file-utilities.h
@@ -95,6 +95,28 @@ gboolean should_handle_content_types (const char * const *content_type);
 
 gboolean nautilus_file_selection_equal (GList *selection_a, GList *selection_b);
 
+/**
+ * nautilus_get_common_filename_prefix:
+ * @file_list: set of files (NautilusFile *)
+ * @min_required_len: the minimum number of characters required in the prefix
+ *
+ * Returns: the common filename prefix for a set of files, or NULL if
+ * there isn't a common prefix of length min_required_len
+ */
+char * nautilus_get_common_filename_prefix (GList *file_list,
+                                            int    min_required_len);
+
+/**
+ * nautilus_get_common_filename_prefix_from_filenames:
+ * @filename_list: set of file names (char *)
+ * @min_required_len: the minimum number of characters required in the prefix
+ *
+ * Returns: the common filename prefix for a set of filenames, or NULL if
+ * there isn't a common prefix of length min_required_len
+ */
+char * nautilus_get_common_filename_prefix_from_filenames (GList *filename_list,
+                                                           int    min_required_len);
+
 void nautilus_ensure_extension_points (void);
 void nautilus_ensure_extension_builtins (void);
 
diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c
index 3c9a8ea..ac84b73 100644
--- a/src/nautilus-files-view.c
+++ b/src/nautilus-files-view.c
@@ -126,6 +126,9 @@
 /* Delay to show the Loading... floating bar */
 #define FLOATING_BAR_LOADING_DELAY 200 /* ms */
 
+#define MIN_COMMON_FILENAME_PREFIX_LENGTH 4
+
+
 enum {
         ADD_FILE,
         BEGIN_FILE_CHANGES,
@@ -2094,6 +2097,8 @@ nautilus_files_view_new_folder_dialog_new (NautilusFilesView *view,
         FileNameWidgetData *widget_data;
         GtkWidget *label_file_name;
         GtkBuilder *builder;
+        GList *selection;
+        char *common_prefix;
 
         builder = gtk_builder_new_from_resource ("/org/gnome/nautilus/ui/nautilus-create-folder-dialog.ui");
         label_file_name = GTK_WIDGET (gtk_builder_get_object (builder, "name_label"));
@@ -2122,6 +2127,13 @@ nautilus_files_view_new_folder_dialog_new (NautilusFilesView *view,
                                           G_CALLBACK (create_folder_dialog_on_response),
                                           NULL);
 
+        selection = nautilus_view_get_selection (NAUTILUS_VIEW (view));
+        common_prefix = nautilus_get_common_filename_prefix (selection, MIN_COMMON_FILENAME_PREFIX_LENGTH);
+        if (common_prefix != NULL) {
+                gtk_entry_set_text (GTK_ENTRY (widget_data->name_entry), common_prefix);
+                g_free (common_prefix);
+        }
+
         gtk_builder_connect_signals (builder, widget_data);
         gtk_button_set_label (GTK_BUTTON (widget_data->activate_button),
                               _("Create"));
@@ -2132,6 +2144,7 @@ nautilus_files_view_new_folder_dialog_new (NautilusFilesView *view,
         /* Update the ok button status */
         file_name_widget_entry_on_changed (widget_data);
 
+        nautilus_file_list_free (selection);
         g_object_unref (builder);
 }
 
diff --git a/test/Makefile.am b/test/Makefile.am
index 9f0bcf0..5591d60 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -19,6 +19,9 @@ noinst_PROGRAMS =\
        test-nautilus-search-engine \
        test-nautilus-directory-async \
        test-nautilus-copy \
+       test-file-utilities-get-common-filename-prefix \
+       test-eel-string-rtrim-punctuation \
+       test-eel-string-get-common-prefix \
        $(NULL)
 
 test_nautilus_copy_SOURCES = test-copy.c test.c
@@ -27,6 +30,18 @@ test_nautilus_search_engine_SOURCES = test-nautilus-search-engine.c
 
 test_nautilus_directory_async_SOURCES = test-nautilus-directory-async.c
 
+test_file_utilities_get_common_filename_prefix_SOURCES = test-file-utilities-get-common-filename-prefix.c
+
+test_eel_string_rtrim_punctuation_SOURCES = test-eel-string-rtrim-punctuation.c
+
+test_eel_string_get_common_prefix_SOURCES = test-eel-string-get-common-prefix.c
+
+
+TESTS = test-file-utilities-get-common-filename-prefix \
+       test-eel-string-rtrim-punctuation \
+       test-eel-string-get-common-prefix \
+       $(NULL)
+
 EXTRA_DIST = \
        test.h \
        $(NULL)
diff --git a/test/test-eel-string-get-common-prefix.c b/test/test-eel-string-get-common-prefix.c
new file mode 100644
index 0000000..140b0be
--- /dev/null
+++ b/test/test-eel-string-get-common-prefix.c
@@ -0,0 +1,188 @@
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include "eel/eel-string.h"
+
+
+static void
+free_list_and_result (GList *list, char *result)
+{
+        g_list_free (list);
+        g_free (result);
+}
+
+static void
+test_has_large_enough_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "foo-1.txt");
+        list = g_list_append (list, "foo-1.tar");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_cmpstr ("foo-1.t", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_common_prefix_that_equals_the_min_required_length ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "food");
+        list = g_list_append (list, "foody");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_cmpstr ("food", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_common_prefix_that_equals_the_min_required_length2 ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "foody");
+        list = g_list_append (list, "food");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_cmpstr ("food", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_many_strings_with_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "some text that matches abcde");
+        list = g_list_append (list, "some text that matches abc22");
+        list = g_list_append (list, "some text that 11");
+        list = g_list_append (list, "some text that matches---");
+        list = g_list_append (list, "some text that matches £$$");
+        list = g_list_append (list, "some text that matches.txt");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_cmpstr ("some text that ", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_strings_with_unicode_characters_that_have_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "ƹƱƱƬ");
+        list = g_list_append (list, "ƹƱƱƬƧƥƧ");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_cmpstr ("ƹƱƱƬ", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_no_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "fyod");
+        list = g_list_append (list, "completely different string");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_common_prefix_but_smaller_than_min_required_length ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "fyod");
+        list = g_list_append (list, "fyoa");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_first_character_differs ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "tyodaa");
+        list = g_list_append (list, "fyodaa");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_strings_with_unicode_characters_that_dont_have_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "ƹƱƱƬ");
+        list = g_list_append (list, "ƹƱƢƱƬƧƥƧ");
+
+        actual = eel_str_get_common_prefix (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+
+static void
+setup_test_suite ()
+{
+        g_test_add_func ("/get-common-prefix/1.0",
+                         test_has_large_enough_common_prefix);
+        g_test_add_func ("/get-common-prefix/1.1",
+                         test_has_common_prefix_that_equals_the_min_required_length);
+        g_test_add_func ("/get-common-prefix/1.2",
+                         test_has_common_prefix_that_equals_the_min_required_length2);
+        g_test_add_func ("/get-common-prefix/1.3",
+                         test_many_strings_with_common_prefix);
+        g_test_add_func ("/get-common-prefix/1.4",
+                         test_strings_with_unicode_characters_that_have_common_prefix);
+
+        g_test_add_func ("/get-common-prefix/2.0",
+                         test_no_common_prefix);
+        g_test_add_func ("/get-common-prefix/2.1",
+                         test_has_common_prefix_but_smaller_than_min_required_length);
+        g_test_add_func ("/get-common-prefix/2.2",
+                         test_first_character_differs);
+        g_test_add_func ("/get-common-prefix/2.3",
+                         test_strings_with_unicode_characters_that_dont_have_common_prefix);
+}
+
+int
+main (int argc, char *argv[])
+{
+        g_test_init (&argc, &argv, NULL);
+        g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=747907";);
+        g_test_set_nonfatal_assertions ();
+
+        setup_test_suite ();
+
+        return g_test_run ();
+}
diff --git a/test/test-eel-string-rtrim-punctuation.c b/test/test-eel-string-rtrim-punctuation.c
new file mode 100644
index 0000000..3dc1f94
--- /dev/null
+++ b/test/test-eel-string-rtrim-punctuation.c
@@ -0,0 +1,121 @@
+#include <glib.h>
+
+#include "eel/eel-string.h"
+
+
+static void
+test_single_punctuation_character_removed ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Yossarian-");
+        g_assert_cmpstr ("Yossarian", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_tailing_space_is_removed ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Yossarian ");
+        g_assert_cmpstr ("Yossarian", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_multiple_punctuation_characters_removed ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Yossarian-$$!£");
+        g_assert_cmpstr ("Yossarian", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_multiple_punctuation_characters_removed_try_all_punctuation_characters ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Yossarian-`¬!\"£$%^&*()_+-= {}[]:@~;'#<>?,./\\");
+        g_assert_cmpstr ("Yossarian", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_punctuation_characters_removed_when_punctuation_in_middle_of_string ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Yoss,,arian-$$!£");
+        g_assert_cmpstr ("Yoss,,arian", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_punctuation_characters_removed_when_prefix_is_single_character ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Y-$$  !£");
+        g_assert_cmpstr ("Y", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_punctuation_characters_removed_when_unicode_characters_are_used ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Y✺ǨǨǨ-$$  !£");
+        g_assert_cmpstr ("Y✺ǨǨǨ", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_when_no_trailing_punctuation ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("Yoss,,arian");
+        g_assert_cmpstr ("Yoss,,arian", ==, actual);
+        g_free (actual);
+}
+
+static void
+test_when_single_character_and_no_trailing_punctuation ()
+{
+        char *actual;
+        actual = eel_str_rtrim_punctuation ("t");
+        g_assert_cmpstr ("t", ==, actual);
+        g_free (actual);
+}
+
+static void
+setup_test_suite ()
+{
+        g_test_add_func ("/rtrim-punctuation/1.0",
+                         test_single_punctuation_character_removed);
+        g_test_add_func ("/rtrim-punctuation/1.1",
+                         test_tailing_space_is_removed);
+        g_test_add_func ("/rtrim-punctuation/1.2",
+                         test_multiple_punctuation_characters_removed);
+        g_test_add_func ("/rtrim-punctuation/1.3",
+                         test_multiple_punctuation_characters_removed_try_all_punctuation_characters);
+        g_test_add_func ("/rtrim-punctuation/1.4",
+                         test_punctuation_characters_removed_when_punctuation_in_middle_of_string);
+        g_test_add_func ("/rtrim-punctuation/1.5",
+                         test_punctuation_characters_removed_when_prefix_is_single_character);
+        g_test_add_func ("/rtrim-punctuation/1.6",
+                         test_punctuation_characters_removed_when_unicode_characters_are_used);
+
+        g_test_add_func ("/rtrim-punctuation/2.0",
+                         test_when_no_trailing_punctuation);
+        g_test_add_func ("/rtrim-punctuation/2.1",
+                         test_when_single_character_and_no_trailing_punctuation);
+}
+
+int
+main (int argc, char *argv[])
+{
+        g_test_init (&argc, &argv, NULL);
+        g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=747907";);
+        g_test_set_nonfatal_assertions ();
+
+        setup_test_suite ();
+
+        return g_test_run ();
+}
diff --git a/test/test-file-utilities-get-common-filename-prefix.c 
b/test/test-file-utilities-get-common-filename-prefix.c
new file mode 100644
index 0000000..2eaaa9c
--- /dev/null
+++ b/test/test-file-utilities-get-common-filename-prefix.c
@@ -0,0 +1,534 @@
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include "src/nautilus-file-utilities.h"
+
+
+static void
+free_list_and_result (GList *list, char *result)
+{
+        g_list_free (list);
+        g_free (result);
+}
+
+static void
+test_has_large_enough_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "test");
+        list = g_list_append (list, "tests");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("test", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_large_enough_common_prefix_with_spaces_in_middle ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "Cpt J Yossarian r1");
+        list = g_list_append (list, "Cpt J Yossarian a1");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("Cpt J Yossarian", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_large_enough_common_prefix_with_punctuation_in_middle ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "Cpt-J_Yossarian r1");
+        list = g_list_append (list, "Cpt-J_Yossarian a1");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("Cpt-J_Yossarian", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_large_enough_common_prefix_with_punctuation_in_middle_and_extension ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "Cpt-J, Yossarian.xml");
+        list = g_list_append (list, "Cpt-J, Yossarian.xsl");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("Cpt-J, Yossarian", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_doesnt_have_large_enough_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "foo");
+        list = g_list_append (list, "foob");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_doesnt_have_large_enough_common_prefix_completely_different_strings ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "this string really");
+        list = g_list_append (list, "isn't the same as the other");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_doesnt_have_large_enough_common_prefix_first_character_differs ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "foo");
+        list = g_list_append (list, "roo");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_doesnt_have_large_enough_common_prefix_first_character_differs_longer_string ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "fools");
+        list = g_list_append (list, "rools");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_large_enough_common_prefix_until_punctuation_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "tes$%^");
+        list = g_list_append (list, "tes$%something");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_large_enough_common_prefix_until_extension_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "tes.txt");
+        list = g_list_append (list, "tes.tar");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_has_large_enough_common_prefix_until_extension_and_punctuation_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "tux$&&&.txt");
+        list = g_list_append (list, "tux$&&&.tar");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_extension_is_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nau tilus.c");
+        list = g_list_append (list, "nau tilus.cpp");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nau tilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_punctuation_is_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nautilus((&&£");
+        list = g_list_append (list, "nautilus((&&xyz");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nautilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_whitespace_is_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nautilus ");
+        list = g_list_append (list, "nautilus two");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nautilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_punctuation_and_whitespace_are_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nautilus! £ $\"TTR");
+        list = g_list_append (list, "nautilus! £ $\"");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nautilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_whitespace_and_punctuation_are_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nautilus !£ $\"TTR");
+        list = g_list_append (list, "nautilus !£ $\"");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nautilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_puctuation_and_extension_are_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nautilus!£$%^&*()_+-={}[];':@#~<>?,./\".tar");
+        list = g_list_append (list, "nautilus!£$%^&*()_+-={}[];':@#~<>?,./\".tat");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nautilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_puctuation_extension_and_whitespace_are_removed ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "nautilus!£$%^&* ()_+-={}[ ];':@#~<>?,./\".tar");
+        list = g_list_append (list, "nautilus!£$%^&* ()_+-={}[ ];':@#~<>?,./\".tat");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("nautilus", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_unicode_on_outside ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "ӶtestӶ234");
+        list = g_list_append (list, "ӶtestӶ1");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("ӶtestӶ", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_unicode_on_inside ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "QQӶtestӶabb234");
+        list = g_list_append (list, "QQӶtestӶabb1");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("QQӶtestӶabb", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_unicode_whole_string ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "ǣȸʸͻͻΎΘΛ");
+        list = g_list_append (list, "ǣȸʸͻͻΎΘ");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("ǣȸʸͻͻΎΘ", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_unicode_extension ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "test.ǣȸʸͻͻΎΘΛ");
+        list = g_list_append (list, "test.ǣȸʸͻͻΎΘ");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("test", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_unicode_with_punctuation ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "ǣȸʸ- ͻͻΎΘ$%%^");
+        list = g_list_append (list, "ǣȸʸ- ͻͻΎΘ$%%&");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("ǣȸʸ- ͻͻΎΘ", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_many_strings ()
+{
+        GList *list = NULL;
+        char *actual;
+        char *filename;
+
+        for (int i = 0; i < 500; ++i) {
+                filename = g_strdup_printf ("we are no longer the knights who say nii%d", i);
+                list = g_list_append (list, filename);
+        }
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_cmpstr ("we are no longer the knights who say nii", ==, actual);
+
+        g_free (actual);
+        g_list_free_full (list, g_free);
+}
+
+static void
+test_many_strings_last_differs ()
+{
+        GList *list = NULL;
+        char *actual;
+        char *filename;
+
+        for (int i = 0; i < 500; ++i) {
+                filename = g_strdup_printf ("we are no longer the knights who say nii%d", i);
+
+                if (i == 499) {
+                        filename[2] = 'X';
+                }
+
+                list = g_list_append (list, filename);
+        }
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        g_free (actual);
+        g_list_free_full (list, g_free);
+}
+
+static void
+test_many_strings_first_differs ()
+{
+        GList *list = NULL;
+        char *actual;
+        char *filename;
+
+        for (int i = 0; i < 500; ++i) {
+                filename = g_strdup_printf ("we are no longer the knights who say nii%d", i);
+
+                if (i == 0) {
+                        filename[2] = 'X';
+                }
+
+                list = g_list_append (list, filename);
+        }
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 4);
+        g_assert_null (actual);
+
+        g_free (actual);
+        g_list_free_full (list, g_free);
+}
+
+static void
+test_smaller_min_length_and_does_have_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "CA");
+        list = g_list_append (list, "CB");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 1);
+        g_assert_cmpstr ("C", ==, actual);
+
+        free_list_and_result (list, actual);
+}
+
+static void
+test_smaller_min_length_and_doesnt_have_common_prefix ()
+{
+        GList *list = NULL;
+        char *actual;
+
+        list = g_list_append (list, "CA");
+        list = g_list_append (list, "BB");
+
+        actual = nautilus_get_common_filename_prefix_from_filenames (list, 1);
+        g_assert_null (actual);
+
+        free_list_and_result (list, actual);
+}
+
+
+static void
+setup_test_suite ()
+{
+        g_test_add_func ("/get-common-filename-prefix/1.0",
+                         test_has_large_enough_common_prefix);
+        g_test_add_func ("/get-common-filename-prefix/1.1",
+                         test_has_large_enough_common_prefix_with_spaces_in_middle);
+        g_test_add_func ("/get-common-filename-prefix/1.2",
+                         test_has_large_enough_common_prefix_with_punctuation_in_middle);
+        g_test_add_func ("/get-common-filename-prefix/1.3",
+                         test_has_large_enough_common_prefix_with_punctuation_in_middle_and_extension);
+
+        g_test_add_func ("/get-common-filename-prefix/2.0",
+                         test_doesnt_have_large_enough_common_prefix);
+        g_test_add_func ("/get-common-filename-prefix/2.1",
+                         test_doesnt_have_large_enough_common_prefix_completely_different_strings);
+        g_test_add_func ("/get-common-filename-prefix/2.2",
+                         test_doesnt_have_large_enough_common_prefix_first_character_differs);
+        g_test_add_func ("/get-common-filename-prefix/2.3",
+                         test_doesnt_have_large_enough_common_prefix_first_character_differs_longer_string);
+
+        g_test_add_func ("/get-common-filename-prefix/3.0",
+                         test_has_large_enough_common_prefix_until_punctuation_removed);
+        g_test_add_func ("/get-common-filename-prefix/3.1",
+                         test_has_large_enough_common_prefix_until_extension_removed);
+        g_test_add_func ("/get-common-filename-prefix/3.2",
+                         test_has_large_enough_common_prefix_until_extension_and_punctuation_removed);
+
+        g_test_add_func ("/get-common-filename-prefix/4.0",
+                         test_extension_is_removed);
+        g_test_add_func ("/get-common-filename-prefix/4.1",
+                         test_punctuation_is_removed);
+        g_test_add_func ("/get-common-filename-prefix/4.2",
+                         test_whitespace_is_removed);
+        g_test_add_func ("/get-common-filename-prefix/4.3",
+                         test_punctuation_and_whitespace_are_removed);
+        g_test_add_func ("/get-common-filename-prefix/4.4",
+                         test_whitespace_and_punctuation_are_removed);
+        g_test_add_func ("/get-common-filename-prefix/4.5",
+                         test_puctuation_and_extension_are_removed);
+        g_test_add_func ("/get-common-filename-prefix/4.6",
+                         test_puctuation_extension_and_whitespace_are_removed);
+
+        g_test_add_func ("/get-common-filename-prefix/5.0",
+                         test_unicode_on_inside);
+        g_test_add_func ("/get-common-filename-prefix/5.1",
+                         test_unicode_on_outside);
+        g_test_add_func ("/get-common-filename-prefix/5.2",
+                         test_unicode_whole_string);
+        g_test_add_func ("/get-common-filename-prefix/5.3",
+                         test_unicode_extension);
+        g_test_add_func ("/get-common-filename-prefix/5.4",
+                         test_unicode_with_punctuation);
+
+        g_test_add_func ("/get-common-filename-prefix/6.0",
+                         test_many_strings);
+        g_test_add_func ("/get-common-filename-prefix/6.1",
+                         test_many_strings_last_differs);
+        g_test_add_func ("/get-common-filename-prefix/6.2",
+                         test_many_strings_first_differs);
+
+        g_test_add_func ("/get-common-filename-prefix/7.0",
+                         test_smaller_min_length_and_does_have_common_prefix);
+        g_test_add_func ("/get-common-filename-prefix/7.1",
+                         test_smaller_min_length_and_doesnt_have_common_prefix);
+}
+
+int
+main (int argc, char *argv[])
+{
+        g_test_init (&argc, &argv, NULL);
+        g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=747907";);
+        g_test_set_nonfatal_assertions ();
+
+        setup_test_suite ();
+
+        return g_test_run ();
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]