[gnome-builder] auto-indent: auto insert matching {}. do right thing on \n.



commit 171b10c6f76c9f02698c7c661331913afe36b7ca
Author: Christian Hergert <christian hergert me>
Date:   Sat Sep 20 19:00:39 2014 -0700

    auto-indent: auto insert matching {}. do right thing on \n.
    
    Start with
    
      {|}
    
    Upon return, be like:
    
      {
        |
      }

 src/editor/gb-source-auto-indenter-c.c |   59 ++++++++++++++++++++++++++++++++
 src/editor/gb-source-auto-indenter.c   |   10 +++++
 src/editor/gb-source-auto-indenter.h   |    5 +++
 src/editor/gb-source-view.c            |   16 ++++++++-
 4 files changed, 89 insertions(+), 1 deletions(-)
---
diff --git a/src/editor/gb-source-auto-indenter-c.c b/src/editor/gb-source-auto-indenter-c.c
index 2dde2bd..a27c8f4 100644
--- a/src/editor/gb-source-auto-indenter-c.c
+++ b/src/editor/gb-source-auto-indenter-c.c
@@ -904,6 +904,27 @@ maybe_align_parameters (GbSourceAutoIndenterC *c,
   RETURN (ret);
 }
 
+static gchar *
+maybe_add_brace (GbSourceAutoIndenterC *c,
+                 GtkTextIter           *begin,
+                 GtkTextIter           *end,
+                 gint                  *cursor_offset)
+{
+  GtkTextIter iter;
+
+  gtk_text_iter_assign (&iter, begin);
+
+  if (gtk_text_iter_backward_char (&iter) &&
+      (gtk_text_iter_get_char (&iter) == '{') &&
+      (gtk_text_iter_get_char (begin) != '}'))
+    {
+      *cursor_offset = -1;
+      return g_strdup ("}");
+    }
+
+  return NULL;
+}
+
 static gboolean
 gb_source_auto_indenter_c_is_trigger (GbSourceAutoIndenter *indenter,
                                       GdkEventKey          *event)
@@ -911,6 +932,7 @@ gb_source_auto_indenter_c_is_trigger (GbSourceAutoIndenter *indenter,
   switch (event->keyval) {
   case GDK_KEY_KP_Enter:
   case GDK_KEY_Return:
+  case GDK_KEY_braceleft:
   case GDK_KEY_braceright:
   case GDK_KEY_colon:
   case GDK_KEY_numbersign:
@@ -929,6 +951,7 @@ gb_source_auto_indenter_c_format (GbSourceAutoIndenter *indenter,
                                   GtkTextBuffer        *buffer,
                                   GtkTextIter          *begin,
                                   GtkTextIter          *end,
+                                  gint                 *cursor_offset,
                                   GdkEventKey          *event)
 {
   GbSourceAutoIndenterC *c = (GbSourceAutoIndenterC *)indenter;
@@ -943,11 +966,47 @@ gb_source_auto_indenter_c_format (GbSourceAutoIndenter *indenter,
     gtk_text_iter_assign (&begin_copy, begin);
     ret = gb_source_auto_indenter_c_indent (c, view, buffer, begin);
     gtk_text_iter_assign (begin, &begin_copy);
+
+    /*
+     * If we are inserting a newline right before a closing brace (for example
+     * after {<cursor>}, we need to indent and then maybe unindent the }.
+     */
+    if (gtk_text_iter_get_char (begin) == '}')
+      {
+        GtkTextIter iter;
+        GString *str;
+        gchar *tmp = ret;
+        guint offset;
+
+        str = g_string_new (NULL);
+
+        gtk_text_iter_assign (&iter, begin);
+        gtk_text_iter_backward_char (&iter);
+        gtk_text_iter_backward_char (&iter);
+        offset = gtk_text_iter_get_line_offset (&iter);
+        build_indent (c, offset, &iter, str);
+        g_string_prepend (str, "\n");
+        g_string_prepend (str, ret);
+
+        *cursor_offset = -(str->len - strlen (ret));
+
+        ret = g_string_free (str, FALSE);
+        g_free (tmp);
+      }
+
+    break;
+
+  case GDK_KEY_braceleft:
+    /*
+     * If we are starting a new scope, maybe add a match closing brace.
+     */
+    ret = maybe_add_brace (c, begin, end, cursor_offset);
     break;
 
   case GDK_KEY_braceright:
     /*
      * Probably need to unindent this line.
+     * TODO: Maybe overwrite character.
      */
     ret = maybe_unindent_brace (c, begin, end);
     break;
diff --git a/src/editor/gb-source-auto-indenter.c b/src/editor/gb-source-auto-indenter.c
index 58ace44..e8d63ec 100644
--- a/src/editor/gb-source-auto-indenter.c
+++ b/src/editor/gb-source-auto-indenter.c
@@ -71,8 +71,11 @@ gb_source_auto_indenter_format (GbSourceAutoIndenter *indenter,
                                 GtkTextBuffer        *buffer,
                                 GtkTextIter          *begin,
                                 GtkTextIter          *end,
+                                gint                 *cursor_offset,
                                 GdkEventKey          *event)
 {
+  gint dummy;
+
   g_return_val_if_fail (GB_IS_SOURCE_AUTO_INDENTER (indenter), NULL);
   g_return_val_if_fail (GTK_IS_TEXT_VIEW (view), NULL);
   g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
@@ -80,11 +83,17 @@ gb_source_auto_indenter_format (GbSourceAutoIndenter *indenter,
   g_return_val_if_fail (end, NULL);
   g_return_val_if_fail (event, NULL);
 
+  if (cursor_offset)
+    *cursor_offset = 0;
+  else
+    cursor_offset = &dummy;
+
   return GB_SOURCE_AUTO_INDENTER_GET_CLASS (indenter)->format (indenter,
                                                                view,
                                                                buffer,
                                                                begin,
                                                                end,
+                                                               cursor_offset,
                                                                event);
 }
 
@@ -94,6 +103,7 @@ gb_source_auto_indenter_real_format (GbSourceAutoIndenter *indenter,
                                      GtkTextBuffer        *buffer,
                                      GtkTextIter          *begin,
                                      GtkTextIter          *end,
+                                     gint                 *cursor_offset,
                                      GdkEventKey          *event)
 {
   return NULL;
diff --git a/src/editor/gb-source-auto-indenter.h b/src/editor/gb-source-auto-indenter.h
index 7d4bebd..d1de838 100644
--- a/src/editor/gb-source-auto-indenter.h
+++ b/src/editor/gb-source-auto-indenter.h
@@ -48,6 +48,9 @@ struct _GbSourceAutoIndenterClass
 {
   GObjectClass parent_class;
 
+  /*
+   * TODO: Remove "query".
+   */
   gchar *(*query) (GbSourceAutoIndenter *indenter,
                    GtkTextView          *view,
                    GtkTextBuffer        *buffer,
@@ -58,6 +61,7 @@ struct _GbSourceAutoIndenterClass
                     GtkTextBuffer        *buffer,
                     GtkTextIter          *begin,
                     GtkTextIter          *end,
+                    gint                 *cursor_offset,
                     GdkEventKey          *trigger);
 
   gboolean (*is_trigger) (GbSourceAutoIndenter *indenter,
@@ -78,6 +82,7 @@ gchar    *gb_source_auto_indenter_format     (GbSourceAutoIndenter *indenter,
                                               GtkTextBuffer        *buffer,
                                               GtkTextIter          *begin,
                                               GtkTextIter          *end,
+                                              gint                 *cursor_offset,
                                               GdkEventKey          *event);
 
 G_END_DECLS
diff --git a/src/editor/gb-source-view.c b/src/editor/gb-source-view.c
index a6176c3..12e8d4a 100644
--- a/src/editor/gb-source-view.c
+++ b/src/editor/gb-source-view.c
@@ -986,6 +986,7 @@ gb_source_view_key_press_event (GtkWidget   *widget,
       GtkTextIter begin;
       GtkTextIter end;
       gchar *indent;
+      gint cursor_offset = 0;
 
       /*
        * Insert into the buffer so the auto-indenter can see it. If
@@ -1007,16 +1008,29 @@ gb_source_view_key_press_event (GtkWidget   *widget,
       indent = gb_source_auto_indenter_format (priv->auto_indenter,
                                                GTK_TEXT_VIEW (view),
                                                priv->buffer, &begin, &end,
-                                               event);
+                                               &cursor_offset, event);
 
       if (indent)
         {
+          /*
+           * Insert the indention text.
+           */
           gtk_text_buffer_begin_user_action (priv->buffer);
           if (!gtk_text_iter_equal (&begin, &end))
             gtk_text_buffer_delete (priv->buffer, &begin, &end);
           gtk_text_buffer_insert (priv->buffer, &begin, indent, -1);
           g_free (indent);
           gtk_text_buffer_end_user_action (priv->buffer);
+
+          /*
+           * Place the cursor, as it could be somewhere within our indent text.
+           */
+          gtk_text_buffer_get_iter_at_mark (priv->buffer, &begin, insert);
+          if (cursor_offset > 0)
+            gtk_text_iter_forward_chars (&begin, cursor_offset);
+          else if (cursor_offset < 0)
+            gtk_text_iter_backward_chars (&begin, ABS (cursor_offset));
+          gtk_text_buffer_select_range (priv->buffer, &begin, &begin);
         }
 
       return TRUE;


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