[gnome-builder/editor-layout] editor: add reformat command for editor tab.



commit 6aa4b4b09770339164046fa0f5535762552acafe
Author: Christian Hergert <christian hergert me>
Date:   Mon Dec 1 01:41:26 2014 -0800

    editor: add reformat command for editor tab.

 src/editor/gb-editor-document.h  |    1 +
 src/editor/gb-editor-frame.c     |   97 ++++++++++++++++++++++++++++++++++++++
 src/editor/gb-editor-frame.h     |    1 +
 src/editor/gb-editor-tab.c       |   11 ++++
 src/editor/gb-editor-tab.h       |    1 +
 src/editor/gb-editor-workspace.c |   14 ++++++
 6 files changed, 125 insertions(+), 0 deletions(-)
---
diff --git a/src/editor/gb-editor-document.h b/src/editor/gb-editor-document.h
index f0e556b..b7fd268 100644
--- a/src/editor/gb-editor-document.h
+++ b/src/editor/gb-editor-document.h
@@ -84,6 +84,7 @@ void                   gb_editor_document_save_async         (GbEditorDocument
 gboolean               gb_editor_document_save_finish        (GbEditorDocument       *document,
                                                               GAsyncResult           *result,
                                                               GError                **error);
+void                   gb_editor_document_reformat           (GbEditorDocument       *document);
 
 G_END_DECLS
 
diff --git a/src/editor/gb-editor-frame.c b/src/editor/gb-editor-frame.c
index 4b05ef9..833f24d 100644
--- a/src/editor/gb-editor-frame.c
+++ b/src/editor/gb-editor-frame.c
@@ -23,6 +23,7 @@
 #include "gb-editor-frame.h"
 #include "gb-editor-frame-private.h"
 #include "gb-log.h"
+#include "gb-source-formatter.h"
 #include "gb-string.h"
 #include "gb-widget.h"
 #include "gb-workbench.h"
@@ -267,6 +268,102 @@ gb_editor_frame_on_search_occurrences_notify (GbEditorFrame          *frame,
   gb_editor_frame_update_search_position_label (frame);
 }
 
+void
+gb_editor_frame_reformat (GbEditorFrame *frame)
+{
+  GbEditorFramePrivate *priv;
+  GbSourceFormatter *formatter;
+  GtkSourceLanguage *language;
+  GtkTextBuffer *buffer;
+  GtkTextIter begin;
+  GtkTextIter end;
+  GtkTextIter iter;
+  GtkTextMark *insert;
+  gboolean fragment = TRUE;
+  GError *error = NULL;
+  gchar *input = NULL;
+  gchar *output = NULL;
+  guint line_number;
+  guint char_offset;
+
+  ENTRY;
+
+  /*
+   * TODO: Do this asynchronously, add tab state, propagate errors.
+   */
+
+  g_return_if_fail (GB_IS_EDITOR_FRAME (frame));
+
+  priv = frame->priv;
+
+  buffer = GTK_TEXT_BUFFER (priv->document);
+
+  gtk_text_buffer_get_selection_bounds (buffer, &begin, &end);
+
+  if (gtk_text_iter_compare (&begin, &end) == 0)
+    {
+      gtk_text_buffer_get_bounds (buffer, &begin, &end);
+      fragment = FALSE;
+    }
+
+  input = gtk_text_buffer_get_text (buffer, &begin, &end, TRUE);
+
+  insert = gtk_text_buffer_get_insert (buffer);
+  gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
+  char_offset = gtk_text_iter_get_line_offset (&iter);
+  line_number = gtk_text_iter_get_line (&iter);
+
+  language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (buffer));
+  formatter = gb_source_formatter_new_from_language (language);
+
+  if (!gb_source_formatter_format (formatter, input, fragment, NULL, &output,
+                                   &error))
+    {
+      g_warning ("%s", error->message);
+      g_clear_error (&error);
+      GOTO (cleanup);
+    }
+
+  gtk_text_buffer_begin_user_action (buffer);
+
+  /* TODO: Keep the cursor on same CXCursor from Clang instead of the
+   *       same character offset within the buffer. We probably want
+   *       to defer this to the formatter API since it will be language
+   *       specific.
+   */
+
+  gtk_text_buffer_delete (buffer, &begin, &end);
+  gtk_text_buffer_insert (buffer, &begin, output, -1);
+
+  if (line_number >= gtk_text_buffer_get_line_count (buffer))
+    {
+      gtk_text_buffer_get_bounds (buffer, &begin, &iter);
+      goto select_range;
+    }
+
+  gtk_text_buffer_get_iter_at_line (buffer, &iter, line_number);
+  gtk_text_iter_forward_to_line_end (&iter);
+
+  if (gtk_text_iter_get_line (&iter) != line_number)
+    gtk_text_iter_backward_char (&iter);
+  else if (gtk_text_iter_get_line_offset (&iter) > char_offset)
+    gtk_text_buffer_get_iter_at_line_offset (buffer, &iter, line_number, char_offset);
+
+select_range:
+  gtk_text_buffer_select_range (buffer, &iter, &iter);
+  gtk_text_buffer_end_user_action (buffer);
+
+  gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->source_view), &iter,
+                                0.25, TRUE, 0.5, 0.5);
+
+cleanup:
+  g_free (input);
+  g_free (output);
+  g_clear_object (&formatter);
+
+  EXIT;
+}
+
 /**
  * gb_editor_frame_on_cursor_moved:
  *
diff --git a/src/editor/gb-editor-frame.h b/src/editor/gb-editor-frame.h
index 2c006ba..03722f3 100644
--- a/src/editor/gb-editor-frame.h
+++ b/src/editor/gb-editor-frame.h
@@ -59,6 +59,7 @@ void              gb_editor_frame_set_document (GbEditorFrame    *frame,
                                                 GbEditorDocument *document);
 void              gb_editor_frame_find         (GbEditorFrame    *frame,
                                                 const gchar      *search_text);
+void              gb_editor_frame_reformat     (GbEditorFrame    *frame);
 
 G_END_DECLS
 
diff --git a/src/editor/gb-editor-tab.c b/src/editor/gb-editor-tab.c
index 8b7c25e..91229cc 100644
--- a/src/editor/gb-editor-tab.c
+++ b/src/editor/gb-editor-tab.c
@@ -504,6 +504,17 @@ gb_editor_tab_find (GbEditorTab *tab)
   gb_editor_frame_find (frame, NULL);
 }
 
+void
+gb_editor_tab_reformat (GbEditorTab *tab)
+{
+  GbEditorFrame *frame;
+
+  g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+  frame = gb_editor_tab_get_last_frame (tab);
+  gb_editor_frame_reformat (frame);
+}
+
 static void
 gb_editor_tab_constructed (GObject *object)
 {
diff --git a/src/editor/gb-editor-tab.h b/src/editor/gb-editor-tab.h
index f35627f..bd769f9 100644
--- a/src/editor/gb-editor-tab.h
+++ b/src/editor/gb-editor-tab.h
@@ -61,6 +61,7 @@ void         gb_editor_tab_scroll_up      (GbEditorTab *tab);
 void         gb_editor_tab_scroll_down    (GbEditorTab *tab);
 void         gb_editor_tab_toggle_split   (GbEditorTab *tab);
 void         gb_editor_tab_find           (GbEditorTab *tab);
+void         gb_editor_tab_reformat       (GbEditorTab *tab);
 void         gb_editor_tab_scroll_to_line (GbEditorTab *tab,
                                            guint        line,
                                            guint        line_offset);
diff --git a/src/editor/gb-editor-workspace.c b/src/editor/gb-editor-workspace.c
index e1b07e3..c40a90e 100644
--- a/src/editor/gb-editor-workspace.c
+++ b/src/editor/gb-editor-workspace.c
@@ -128,6 +128,19 @@ find_tab (GSimpleAction *action,
 }
 
 static void
+reformat_tab (GSimpleAction *action,
+              GVariant      *parameter,
+              gpointer       user_data)
+{
+  GbEditorWorkspace *workspace = user_data;
+  GbTab *tab;
+
+  tab = gb_tab_grid_get_active (workspace->priv->tab_grid);
+  if (GB_IS_EDITOR_TAB (tab))
+    gb_editor_tab_reformat (GB_EDITOR_TAB (tab));
+}
+
+static void
 close_tab (GSimpleAction *action,
            GVariant      *parameter,
            gpointer       user_data)
@@ -284,6 +297,7 @@ gb_editor_workspace_init (GbEditorWorkspace *workspace)
       { "scroll-down", scroll_down_tab },
       { "toggle-split", toggle_split_tab },
       { "find", find_tab },
+      { "reformat", reformat_tab },
     };
 
   workspace->priv = gb_editor_workspace_get_instance_private (workspace);


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