[gnome-builder/wip/uajain/word-completion: 1/2] Improve on how to replay results



commit cf687884c7dcb7203ffc8720f12a51331ecd282c
Author: Umang Jain <mailumangjain gmail com>
Date:   Thu Aug 31 05:16:59 2017 +0530

    Improve on how to replay results
    
    Relative offsets can change while proposals can be replayed in 2 cases:
    (1) User requests for opposite direction while the string prefix is same
    (2) Completion requested on a different line (different from where initial
        proposals matches were created).

 libide/sourceview/ide-completion-results.c      |   38 +++++++
 libide/sourceview/ide-completion-results.h      |    2 +
 libide/sourceview/ide-word-completion-results.c |  124 ++++++++++++++++++++++-
 libide/sourceview/ide-word-completion-results.h |    3 +-
 4 files changed, 161 insertions(+), 6 deletions(-)
---
diff --git a/libide/sourceview/ide-completion-results.c b/libide/sourceview/ide-completion-results.c
index 89948e1..9197710 100644
--- a/libide/sourceview/ide-completion-results.c
+++ b/libide/sourceview/ide-completion-results.c
@@ -53,6 +53,14 @@ typedef struct
    */
   GPtrArray *results;
   /*
+   * insert_offset and end_offset helps to determine new relative offsets
+   * in case we can replay the results but in an another location. Hence,
+   * recompute new offsets and sort. See ide_word_completion_results_compare
+   * for details.
+   */
+  gint insert_offset;
+  gint end_offset;
+  /*
    * query is the filtering string that was used to create the
    * initial set of results. All future queries must have this
    * word as a prefix to be reusable.
@@ -362,6 +370,8 @@ ide_completion_results_present (IdeCompletionResults        *self,
                                 GtkSourceCompletionContext  *context)
 {
   IdeCompletionResultsPrivate *priv = ide_completion_results_get_instance_private (self);
+  GtkTextIter insert_iter;
+  GtkTextIter end_iter;
 
   g_return_if_fail (IDE_IS_COMPLETION_RESULTS (self));
   g_return_if_fail (GTK_SOURCE_IS_COMPLETION_PROVIDER (provider));
@@ -369,6 +379,14 @@ ide_completion_results_present (IdeCompletionResults        *self,
   g_return_if_fail (priv->query != NULL);
   g_return_if_fail (priv->replay != NULL);
 
+  /* Maybe find some "if logic" block to detect that we are doing word-completion */
+  gtk_source_completion_context_get_iter (context, &insert_iter);
+  gtk_text_buffer_get_end_iter (gtk_text_iter_get_buffer (&insert_iter),
+                                &end_iter);
+
+  priv->insert_offset = gtk_text_iter_get_offset (&insert_iter);
+  priv->end_offset = gtk_text_iter_get_offset (&end_iter);
+
   if (priv->needs_refilter)
     {
       ide_completion_results_refilter (self);
@@ -462,3 +480,23 @@ ide_completion_results_get_size (IdeCompletionResults *self)
 
   return priv->results != NULL ? priv->results->len : 0;
 }
+
+gint
+ide_completion_results_get_insert_offset (IdeCompletionResults *self)
+{
+  IdeCompletionResultsPrivate *priv = ide_completion_results_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_COMPLETION_RESULTS (self), 0);
+
+  return priv->insert_offset;
+}
+
+gint
+ide_completion_results_get_end_offset (IdeCompletionResults *self)
+{
+  IdeCompletionResultsPrivate *priv = ide_completion_results_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_COMPLETION_RESULTS (self), 0);
+
+  return priv->end_offset;
+}
diff --git a/libide/sourceview/ide-completion-results.h b/libide/sourceview/ide-completion-results.h
index 749ba51..d848a8a 100644
--- a/libide/sourceview/ide-completion-results.h
+++ b/libide/sourceview/ide-completion-results.h
@@ -59,6 +59,8 @@ void                  ide_completion_results_present          (IdeCompletionResu
 gboolean              ide_completion_results_replay           (IdeCompletionResults        *self,
                                                                const gchar                 *query);
 guint                 ide_completion_results_get_size         (IdeCompletionResults        *self);
+gint                 ide_completion_results_get_insert_offset (IdeCompletionResults        *self);
+gint                 ide_completion_results_get_end_offset    (IdeCompletionResults        *self);
 
 G_END_DECLS
 
diff --git a/libide/sourceview/ide-word-completion-results.c b/libide/sourceview/ide-word-completion-results.c
index f728182..74297bf 100644
--- a/libide/sourceview/ide-word-completion-results.c
+++ b/libide/sourceview/ide-word-completion-results.c
@@ -24,25 +24,85 @@
 struct _IdeWordCompletionResults
 {
   IdeCompletionResults parent_instance;
+
+  gint                 sort_direction;
 };
 
 G_DEFINE_TYPE (IdeWordCompletionResults,
                ide_word_completion_results,
                IDE_TYPE_COMPLETION_RESULTS)
 
+enum
+{
+  PROP_0,
+  PROP_SORT_DIRECTION,
+  N_PROPERTIES
+};
+
+static GParamSpec *properties[N_PROPERTIES];
+
 static gint
 ide_word_completion_results_compare (IdeCompletionResults *results,
                                      IdeCompletionItem    *left,
                                      IdeCompletionItem    *right)
 {
+  IdeWordCompletionResults *self = IDE_WORD_COMPLETION_RESULTS (results);
   IdeWordCompletionItem *p1 = (IdeWordCompletionItem *) left;
   IdeWordCompletionItem *p2 = (IdeWordCompletionItem *) right;
+  gint offset_p1 = ide_word_completion_item_get_offset (p1);
+  gint offset_p2 = ide_word_completion_item_get_offset (p2);
+  gint rel_offset_p1= 0;
+  gint rel_offset_p2 = 0;
+  gint insert_offset = 0;
+  gint end_offset = 0;
+
+  insert_offset = ide_completion_results_get_insert_offset (results);
+  end_offset = ide_completion_results_get_end_offset (results);
+
+  g_assert (self->sort_direction != 0);
+  g_assert (insert_offset != 0);
+  g_assert (end_offset != 0);
+
+  if (self->sort_direction == 1)
+    {
+      rel_offset_p1 = offset_p1 - insert_offset;
 
-  if (ide_word_completion_item_get_offset (p1) <
-      ide_word_completion_item_get_offset (p2))
-    return -1;
+      /* Scan must had wrapped so relative offset < 0 possible */
+      if (rel_offset_p1 < 0)
+        rel_offset_p1 = end_offset - insert_offset + offset_p1;
+        g_assert (rel_offset_p1 >= 0);
+
+      rel_offset_p2 =  offset_p2 - insert_offset;
+
+      if (rel_offset_p2 < 0)
+        rel_offset_p2 = end_offset - insert_offset +  offset_p2;
+        g_assert (rel_offset_p2 >= 0);
+
+      if (rel_offset_p1 < rel_offset_p2)
+        return -1;
+      else
+        return 1;
+    }
   else
-    return 1;
+    {
+      rel_offset_p1 = insert_offset - offset_p1;
+
+      /* Scan must had wrapped so relative offset < 0 possible */
+      if (rel_offset_p1 < 0)
+        rel_offset_p1 = end_offset - offset_p1 + insert_offset;
+      g_assert (rel_offset_p1 >= 0);
+
+      rel_offset_p2 = insert_offset - offset_p2;
+
+      if (rel_offset_p2 < 0)
+        rel_offset_p2 = end_offset - offset_p2 + insert_offset;
+      g_assert (rel_offset_p2 >= 0);
+
+      if (rel_offset_p1 > rel_offset_p2)
+        return 1;
+      else
+        return -1;
+    }
 }
 
 static void
@@ -51,17 +111,71 @@ ide_word_completion_results_init (IdeWordCompletionResults *self)
 }
 
 static void
+ide_word_completion_results_get_property (GObject    *object,
+                                          guint       prop_id,
+                                          GValue     *value,
+                                          GParamSpec *pspec)
+{
+  IdeWordCompletionResults *self = IDE_WORD_COMPLETION_RESULTS (object);
+
+  switch (prop_id)
+    {
+    case PROP_SORT_DIRECTION:
+      g_value_set_int (value, self->sort_direction);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+ide_word_completion_results_set_property (GObject      *object,
+                                          guint         prop_id,
+                                          const GValue *value,
+                                          GParamSpec   *pspec)
+{
+  IdeWordCompletionResults *self = IDE_WORD_COMPLETION_RESULTS (object);
+
+  switch (prop_id)
+    {
+    case PROP_SORT_DIRECTION:
+      self->sort_direction = g_value_get_int (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
 ide_word_completion_results_class_init (IdeWordCompletionResultsClass *klass)
 {
   IdeCompletionResultsClass *results_class = IDE_COMPLETION_RESULTS_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
+  object_class->get_property = ide_word_completion_results_get_property;
+  object_class->set_property = ide_word_completion_results_set_property;
   results_class->compare = ide_word_completion_results_compare;
+
+  properties [PROP_SORT_DIRECTION] =
+    g_param_spec_int ("sort-direction",
+                      "Sort direction",
+                      "Determines whether to sort with ascending or descending value of offset",
+                      -1,
+                       1,
+                       0,
+                      (G_PARAM_READWRITE | G_PARAM_CONSTRUCT |  G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPERTIES, properties);
 }
 
 IdeWordCompletionResults *
-ide_word_completion_results_new (const gchar *query)
+ide_word_completion_results_new (const gchar *query,
+                                 gint         sort_direction)
 {
   return g_object_new (IDE_TYPE_WORD_COMPLETION_RESULTS,
                        "query", query,
+                       "sort-direction", sort_direction,
                        NULL);
 }
diff --git a/libide/sourceview/ide-word-completion-results.h b/libide/sourceview/ide-word-completion-results.h
index 8b02463..21623fc 100644
--- a/libide/sourceview/ide-word-completion-results.h
+++ b/libide/sourceview/ide-word-completion-results.h
@@ -29,7 +29,8 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeWordCompletionResults, ide_word_completion_results, IDE, WORD_COMPLETION_RESULTS, 
IdeCompletionResults)
 
-IdeWordCompletionResults* ide_word_completion_results_new (const gchar *query);
+IdeWordCompletionResults* ide_word_completion_results_new (const gchar *query,
+                                                           gint         sort_direction);
 
 G_END_DECLS
 


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