[gnome-builder/editor-layout] trim: trim whitespace upon saving for changed or added lines.



commit d7bbab7e67e3a3976306238a1a06aa3b7009750d
Author: Christian Hergert <christian hergert me>
Date:   Sun Nov 30 22:21:45 2014 -0800

    trim: trim whitespace upon saving for changed or added lines.

 ...rg.gnome.builder.editor.language.gschema.xml.in |    3 +
 src/editor/gb-editor-document.c                    |  118 +++++++++++++++++++-
 src/editor/gb-editor-document.h                    |    3 +
 src/editor/gb-editor-settings-widget.c             |    5 +
 src/editor/gb-source-view.c                        |    2 +
 src/resources/ui/gb-editor-settings-widget.ui      |   41 ++++++--
 6 files changed, 163 insertions(+), 9 deletions(-)
---
diff --git a/data/org.gnome.builder.editor.language.gschema.xml.in 
b/data/org.gnome.builder.editor.language.gschema.xml.in
index 73aa6a8..389abf2 100644
--- a/data/org.gnome.builder.editor.language.gschema.xml.in
+++ b/data/org.gnome.builder.editor.language.gschema.xml.in
@@ -32,5 +32,8 @@
       <range min="1" max="120"/>
       <default>8</default>
     </key>
+    <key name="trim-trailing-whitespace" type="b">
+      <default>true</default>
+    </key>
   </schema>
 </schemalist>
diff --git a/src/editor/gb-editor-document.c b/src/editor/gb-editor-document.c
index f548345..e3c3032 100644
--- a/src/editor/gb-editor-document.c
+++ b/src/editor/gb-editor-document.c
@@ -30,6 +30,8 @@ struct _GbEditorDocumentPrivate
   GtkSourceFile         *file;
   GbSourceChangeMonitor *change_monitor;
   GbSourceCodeAssistant *code_assistant;
+
+  guint trim_trailing_whitespace : 1;
 };
 
 enum {
@@ -37,6 +39,7 @@ enum {
   PROP_CHANGE_MONITOR,
   PROP_FILE,
   PROP_STYLE_SCHEME_NAME,
+  PROP_TRIM_TRAILING_WHITESPACE,
   LAST_PROP
 };
 
@@ -47,7 +50,7 @@ enum {
 
 G_DEFINE_TYPE_WITH_PRIVATE (GbEditorDocument, gb_editor_document, GTK_SOURCE_TYPE_BUFFER)
 
-static  GParamSpec *gParamSpecs [LAST_PROP];
+static GParamSpec *gParamSpecs [LAST_PROP];
 static guint gSignals [LAST_SIGNAL];
 
 GbEditorDocument *
@@ -56,6 +59,28 @@ gb_editor_document_new (void)
   return g_object_new (GB_TYPE_EDITOR_DOCUMENT, NULL);
 }
 
+gboolean
+gb_editor_document_get_trim_trailing_whitespace (GbEditorDocument *document)
+{
+  g_return_val_if_fail (GB_IS_EDITOR_DOCUMENT (document), FALSE);
+
+  return document->priv->trim_trailing_whitespace;
+}
+
+void
+gb_editor_document_set_trim_trailing_whitespace (GbEditorDocument *document,
+                                                 gboolean          trim_trailing_whitespace)
+{
+  g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+  if (trim_trailing_whitespace != document->priv->trim_trailing_whitespace)
+    {
+      document->priv->trim_trailing_whitespace = trim_trailing_whitespace;
+      g_object_notify_by_pspec (G_OBJECT (document),
+                                gParamSpecs [PROP_TRIM_TRAILING_WHITESPACE]);
+    }
+}
+
 GbSourceChangeMonitor *
 gb_editor_document_get_change_monitor (GbEditorDocument *document)
 {
@@ -331,6 +356,74 @@ gb_editor_document_code_assistant_changed (GbEditorDocument      *document,
   g_array_unref (ar);
 }
 
+static gboolean
+gb_editor_document_should_trim_line (GbEditorDocument *document,
+                                     guint             line)
+{
+  GbSourceChangeFlags flags;
+
+  g_return_val_if_fail (GB_IS_EDITOR_DOCUMENT (document), FALSE);
+
+  flags = gb_source_change_monitor_get_line (document->priv->change_monitor,
+                                             line);
+
+  return !!flags;
+}
+
+static gboolean
+text_iter_is_space (const GtkTextIter *iter)
+{
+  return g_unichar_isspace (gtk_text_iter_get_char (iter));
+}
+
+static void
+gb_editor_document_trim (GbEditorDocument *document)
+{
+  GtkTextBuffer *buffer;
+  GtkTextIter iter;
+  gint line;
+
+  ENTRY;
+
+  g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
+
+  buffer = GTK_TEXT_BUFFER (document);
+
+  gtk_text_buffer_get_end_iter (buffer, &iter);
+
+  for (line = gtk_text_iter_get_line (&iter); line >= 0; line--)
+    {
+      if (gb_editor_document_should_trim_line (document, line))
+        {
+          gtk_text_buffer_get_iter_at_line (buffer, &iter, line);
+
+          if (gtk_text_iter_forward_to_line_end (&iter) &&
+              text_iter_is_space (&iter))
+            {
+              GtkTextIter begin = iter;
+
+              while (text_iter_is_space (&begin))
+                {
+                  if (gtk_text_iter_starts_line (&begin))
+                    break;
+
+                  if (!gtk_text_iter_backward_char (&begin))
+                    break;
+                }
+
+              if (!text_iter_is_space (&begin) &&
+                  !gtk_text_iter_ends_line (&begin))
+                gtk_text_iter_forward_char (&begin);
+
+              if (!gtk_text_iter_equal (&begin, &iter))
+                gtk_text_buffer_delete (buffer, &begin, &iter);
+            }
+        }
+    }
+
+  EXIT;
+}
+
 static void
 gb_editor_document_guess_language (GbEditorDocument *document)
 {
@@ -426,6 +519,9 @@ gb_editor_document_save_async (GbEditorDocument      *document,
   g_return_if_fail (GB_IS_EDITOR_DOCUMENT (document));
   g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
 
+  if (document->priv->trim_trailing_whitespace)
+    gb_editor_document_trim (document);
+
   task = g_task_new (document, cancellable, callback, user_data);
 
   saver = gtk_source_file_saver_new (GTK_SOURCE_BUFFER (document),
@@ -578,6 +674,11 @@ gb_editor_document_get_property (GObject    *object,
       g_value_set_object (value, gb_editor_document_get_file (self));
       break;
 
+    case PROP_TRIM_TRAILING_WHITESPACE:
+      g_value_set_boolean (value,
+                           gb_editor_document_get_trim_trailing_whitespace (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
     }
@@ -602,6 +703,11 @@ gb_editor_document_set_property (GObject      *object,
                                                 g_value_get_string (value));
       break;
 
+    case PROP_TRIM_TRAILING_WHITESPACE:
+      gb_editor_document_set_trim_trailing_whitespace (self,
+                                                       g_value_get_boolean (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -648,6 +754,15 @@ gb_editor_document_class_init (GbEditorDocumentClass *klass)
   g_object_class_install_property (object_class, PROP_STYLE_SCHEME_NAME,
                                    gParamSpecs [PROP_STYLE_SCHEME_NAME]);
 
+  gParamSpecs [PROP_TRIM_TRAILING_WHITESPACE] =
+    g_param_spec_boolean ("trim-trailing-whitespace",
+                         _("Trim Trailing Whitespace"),
+                         _("If whitespace should be trimmed before saving."),
+                         TRUE,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (object_class, PROP_TRIM_TRAILING_WHITESPACE,
+                                   gParamSpecs [PROP_TRIM_TRAILING_WHITESPACE]);
+
   gSignals[CURSOR_MOVED] =
     g_signal_new ("cursor-moved",
                   G_OBJECT_CLASS_TYPE (object_class),
@@ -665,6 +780,7 @@ gb_editor_document_init (GbEditorDocument *document)
 {
   document->priv = gb_editor_document_get_instance_private (document);
 
+  document->priv->trim_trailing_whitespace = TRUE;
   document->priv->file = gtk_source_file_new ();
   document->priv->change_monitor = gb_source_change_monitor_new (GTK_TEXT_BUFFER (document));
   document->priv->code_assistant = gb_source_code_assistant_new (GTK_TEXT_BUFFER (document));
diff --git a/src/editor/gb-editor-document.h b/src/editor/gb-editor-document.h
index 4c1ae15..f0e556b 100644
--- a/src/editor/gb-editor-document.h
+++ b/src/editor/gb-editor-document.h
@@ -60,6 +60,9 @@ void                   gb_editor_document_set_file           (GbEditorDocument
                                                               GtkSourceFile          *file);
 GbSourceChangeMonitor *gb_editor_document_get_change_monitor (GbEditorDocument       *document);
 GbSourceCodeAssistant *gb_editor_document_get_code_assistant (GbEditorDocument       *document);
+gboolean               gb_editor_document_get_trim_trailing_whitespace (GbEditorDocument *document);
+void                   gb_editor_document_set_trim_trailing_whitespace (GbEditorDocument *document,
+                                                                        gboolean          
trim_trailing_whitespace);
 void                   gb_editor_document_load_async         (GbEditorDocument       *document,
                                                               GFile                  *file,
                                                               GCancellable           *cancellable,
diff --git a/src/editor/gb-editor-settings-widget.c b/src/editor/gb-editor-settings-widget.c
index f3c5824..31a8d0d 100644
--- a/src/editor/gb-editor-settings-widget.c
+++ b/src/editor/gb-editor-settings-widget.c
@@ -35,6 +35,7 @@ struct _GbEditorSettingsWidgetPrivate
   GtkCheckButton *smart_home_end;
   GtkSpinButton  *right_margin_position;
   GtkSpinButton  *tab_width;
+  GtkCheckButton *trim_trailing_whitespace;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GbEditorSettingsWidget, gb_editor_settings_widget,
@@ -111,6 +112,9 @@ gb_editor_settings_widget_set_language (GbEditorSettingsWidget *widget,
       g_settings_bind (priv->settings, "tab-width",
                        priv->tab_width, "value",
                        G_SETTINGS_BIND_DEFAULT);
+      g_settings_bind (priv->settings, "trim-trailing-whitespace",
+                       priv->trim_trailing_whitespace, "active",
+                       G_SETTINGS_BIND_DEFAULT);
 
       g_object_notify_by_pspec (G_OBJECT (widget), gParamSpecs [PROP_LANGUAGE]);
     }
@@ -188,6 +192,7 @@ gb_editor_settings_widget_class_init (GbEditorSettingsWidgetClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, GbEditorSettingsWidget, show_right_margin);
   gtk_widget_class_bind_template_child_private (widget_class, GbEditorSettingsWidget, smart_home_end);
   gtk_widget_class_bind_template_child_private (widget_class, GbEditorSettingsWidget, tab_width);
+  gtk_widget_class_bind_template_child_private (widget_class, GbEditorSettingsWidget, 
trim_trailing_whitespace);
 
   gParamSpecs [PROP_LANGUAGE] =
     g_param_spec_string ("language",
diff --git a/src/editor/gb-source-view.c b/src/editor/gb-source-view.c
index d206c26..f3e1032 100644
--- a/src/editor/gb-source-view.c
+++ b/src/editor/gb-source-view.c
@@ -230,6 +230,8 @@ gb_source_view_connect_settings (GbSourceView *view)
                        G_SETTINGS_BIND_GET);
       g_settings_bind (settings, "tab-width", view, "tab-width",
                        G_SETTINGS_BIND_GET);
+      g_settings_bind (settings, "trim-trailing-whitespace",
+                       buffer, "trim-trailing-whitespace",
                        G_SETTINGS_BIND_GET);
 
       view->priv->language_settings = settings;
diff --git a/src/resources/ui/gb-editor-settings-widget.ui b/src/resources/ui/gb-editor-settings-widget.ui
index ca0779b..034084b 100644
--- a/src/resources/ui/gb-editor-settings-widget.ui
+++ b/src/resources/ui/gb-editor-settings-widget.ui
@@ -34,9 +34,10 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
+            <property name="halign">start</property>
             <property name="valign">center</property>
             <property name="use_underline">True</property>
-            <property name="halign">start</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>
@@ -56,9 +57,10 @@
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
+                <property name="halign">start</property>
                 <property name="valign">baseline</property>
                 <property name="use_underline">True</property>
-                <property name="halign">start</property>
+                <property name="xalign">0.5</property>
                 <property name="draw_indicator">True</property>
               </object>
               <packing>
@@ -96,9 +98,10 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
+            <property name="halign">start</property>
             <property name="valign">center</property>
             <property name="use_underline">True</property>
-            <property name="halign">start</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>
@@ -113,8 +116,9 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
-            <property name="valign">center</property>
             <property name="halign">start</property>
+            <property name="valign">center</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>
@@ -123,6 +127,23 @@
             <property name="position">3</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkCheckButton" id="trim_trailing_whitespace">
+            <property name="label" translatable="yes">Trim trailing whitespace when saving 
document</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">False</property>
+            <property name="halign">start</property>
+            <property name="valign">center</property>
+            <property name="xalign">0</property>
+            <property name="draw_indicator">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">4</property>
+          </packing>
+        </child>
       </object>
       <packing>
         <property name="left_attach">0</property>
@@ -155,10 +176,11 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
+            <property name="halign">start</property>
             <property name="valign">center</property>
             <property name="margin_start">12</property>
             <property name="use_underline">True</property>
-            <property name="halign">start</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>
@@ -173,10 +195,11 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
+            <property name="halign">start</property>
             <property name="valign">center</property>
             <property name="margin_start">12</property>
             <property name="use_underline">True</property>
-            <property name="halign">start</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>
@@ -261,10 +284,11 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
+            <property name="halign">start</property>
             <property name="valign">center</property>
             <property name="margin_start">12</property>
             <property name="use_underline">True</property>
-            <property name="halign">start</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>
@@ -279,10 +303,11 @@
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="receives_default">False</property>
+            <property name="halign">start</property>
             <property name="valign">center</property>
             <property name="margin_start">12</property>
             <property name="use_underline">True</property>
-            <property name="halign">start</property>
+            <property name="xalign">0.5</property>
             <property name="draw_indicator">True</property>
           </object>
           <packing>


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