[gnome-builder] sourceview: propagate snippet content to parent



commit 85ff37503b18d65a7778b3df083f93baa7e55ecf
Author: Simone Piccardi <simone piccardi gmail com>
Date:   Mon Jan 21 17:17:10 2019 +0100

    sourceview: propagate snippet content to parent
    
    When editing a nested snippet, the run-length of the parent can get out
    of sync. This copies the edited sub-snippet content into the parent's
    containing chunk so that editing can continue with proper run lengths.
    
    Signed-off-by: Christian Hergert <chergert redhat com>

 src/libide/sourceview/ide-snippet.c     | 66 +++++++++++++++++++++++++++++++++
 src/libide/sourceview/ide-snippet.h     |  7 ++++
 src/libide/sourceview/ide-source-view.c | 14 +++++--
 3 files changed, 84 insertions(+), 3 deletions(-)
---
diff --git a/src/libide/sourceview/ide-snippet.c b/src/libide/sourceview/ide-snippet.c
index 12e010d68..6a2152640 100644
--- a/src/libide/sourceview/ide-snippet.c
+++ b/src/libide/sourceview/ide-snippet.c
@@ -1307,6 +1307,72 @@ ide_snippet_init (IdeSnippet *self)
   self->runs = g_array_new (FALSE, FALSE, sizeof (gint));
 }
 
+/**
+ * ide_snippet_get_full_text:
+ * @self: a #IdeSnippet
+ *
+ * Gets the contents of the snippet as currently edited by the user.
+ *
+ * Returns: (transfer full): a newly allocated string containing the full
+ *   contents of all the snippet chunks.
+ *
+ * Since: 3.32
+ */
+gchar *
+ide_snippet_get_full_text (IdeSnippet *self)
+{
+  GtkTextIter begin;
+  GtkTextIter end;
+
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
+
+  if (self->mark_begin == NULL || self->mark_end == NULL)
+    return NULL;
+
+  gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin);
+  gtk_text_buffer_get_iter_at_mark (self->buffer, &end, self->mark_end);
+
+  return gtk_text_iter_get_slice (&begin, &end);
+}
+
+/**
+ * ide_snippet_replace_current_chunk_text:
+ * @self: a #IdeSnippet
+ * @new_text: the text to use as the replacement
+ *
+ * This replaces the current chunk (if any) to contain the contents of
+ * @new_text.
+ *
+ * This function is primarily useful to the #IdeSourceView as it updates
+ * content as the user types.
+ *
+ * Since: 3.32
+ */
+void
+ide_snippet_replace_current_chunk_text (IdeSnippet  *self,
+                                        const gchar *new_text)
+{
+  IdeSnippetChunk *chunk;
+  gint utf8_len;
+
+  g_return_if_fail (IDE_IS_SNIPPET (self));
+  g_return_if_fail (self->chunks != NULL);
+
+  if (self->current_chunk < 0 || self->current_chunk >= self->chunks->len)
+    return;
+
+  chunk = g_ptr_array_index (self->chunks, self->current_chunk);
+
+  ide_snippet_chunk_set_text (chunk, new_text);
+  ide_snippet_chunk_set_text_set (chunk, TRUE);
+
+  g_assert (self->current_chunk >= 0);
+  g_assert (self->current_chunk < self->runs->len);
+
+  utf8_len = g_utf8_strlen (new_text, -1);
+  g_array_index (self->runs, gint, self->current_chunk) = utf8_len;
+}
+
 /**
  * ide_snippet_dump:
  * @self: a #IdeSnippet
diff --git a/src/libide/sourceview/ide-snippet.h b/src/libide/sourceview/ide-snippet.h
index d3f9dda9f..92eb66a9d 100644
--- a/src/libide/sourceview/ide-snippet.h
+++ b/src/libide/sourceview/ide-snippet.h
@@ -74,4 +74,11 @@ void               ide_snippet_get_chunk_range (IdeSnippet      *self,
 IDE_AVAILABLE_IN_3_32
 IdeSnippetContext *ide_snippet_get_context     (IdeSnippet      *self);
 
+IDE_AVAILABLE_IN_3_32
+gchar             *ide_snippet_get_full_text   (IdeSnippet      *self);
+
+IDE_AVAILABLE_IN_3_32
+void               ide_snippet_replace_current_chunk_text (IdeSnippet      *self,
+                                                           const gchar     *new_text);
+
 G_END_DECLS
diff --git a/src/libide/sourceview/ide-source-view.c b/src/libide/sourceview/ide-source-view.c
index 82e8eb347..f41639859 100644
--- a/src/libide/sourceview/ide-source-view.c
+++ b/src/libide/sourceview/ide-source-view.c
@@ -6878,13 +6878,21 @@ ide_source_view_pop_snippet (IdeSourceView *self)
 
   if ((snippet = g_queue_pop_head (priv->snippets)))
     {
+      g_autofree gchar *new_text = NULL;
+
+      new_text = ide_snippet_get_full_text (snippet);
+
       ide_snippet_finish (snippet);
       g_signal_emit (self, signals [POP_SNIPPET], 0, snippet);
       g_object_unref (snippet);
-    }
 
-  if ((snippet = g_queue_peek_head (priv->snippets)))
-    ide_snippet_unpause (snippet);
+      if ((snippet = g_queue_peek_head (priv->snippets)))
+        {
+          ide_snippet_replace_current_chunk_text (snippet, new_text);
+          ide_snippet_unpause (snippet);
+          ide_snippet_move_next (snippet);
+        }
+    }
 
   ide_source_view_invalidate_window (self);
 }


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