[gnome-builder/albfan/grep-filters] grep: add path filters



commit a7a8e045484ae8da2479816f2648bec6caf1efe7
Author: Alberto Fanjul <albertofanjul gmail com>
Date:   Sat Nov 3 22:14:49 2018 +0100

    grep: add path filters
    
    file filter allow to select filenames
    ignore filter allow to ignore directories

 src/plugins/grep/gbp-grep-model.c    | 134 +++++++++++++++++++++++++++++++++++
 src/plugins/grep/gbp-grep-model.h    |  80 +++++++++++----------
 src/plugins/grep/gbp-grep-popover.c  |  38 ++++++++++
 src/plugins/grep/gbp-grep-popover.ui |  37 +++++++---
 4 files changed, 243 insertions(+), 46 deletions(-)
---
diff --git a/src/plugins/grep/gbp-grep-model.c b/src/plugins/grep/gbp-grep-model.c
index ef0ea9e8a..4a7c16bc9 100644
--- a/src/plugins/grep/gbp-grep-model.c
+++ b/src/plugins/grep/gbp-grep-model.c
@@ -47,6 +47,14 @@ struct _GbpGrepModel
    */
   gchar *query;
 
+  /* The filter text, which we use to select filenames in result.
+   */
+  gchar **file_filter;
+
+  /* The filter text, which we use to ignore dirs in result.
+   */
+  gchar **ignore_filter;
+
   /* We need to do client-side processing to extract the exact message
    * locations after grep gives us the matching lines. This allows us to
    * create IdeTextEdit source ranges later as well as creating the
@@ -93,6 +101,8 @@ enum {
   PROP_RECURSIVE,
   PROP_USE_REGEX,
   PROP_QUERY,
+  PROP_FILE_FILTER,
+  PROP_IGNORE_FILTER,
   N_PROPS
 };
 
@@ -281,6 +291,14 @@ gbp_grep_model_get_property (GObject    *object,
       g_value_set_string (value, gbp_grep_model_get_query (self));
       break;
 
+    case PROP_FILE_FILTER:
+      g_value_set_boxed (value, gbp_grep_model_get_file_filter (self));
+      break;
+
+    case PROP_IGNORE_FILTER:
+      g_value_set_boxed (value, gbp_grep_model_get_ignore_filter (self));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -320,6 +338,14 @@ gbp_grep_model_set_property (GObject      *object,
       gbp_grep_model_set_query (self, g_value_get_string (value));
       break;
 
+    case PROP_FILE_FILTER:
+      gbp_grep_model_set_file_filter (self, g_value_get_boxed (value));
+      break;
+
+    case PROP_IGNORE_FILTER:
+      gbp_grep_model_set_ignore_filter (self, g_value_get_boxed (value));
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     }
@@ -364,6 +390,14 @@ gbp_grep_model_class_init (GbpGrepModelClass *klass)
     g_param_spec_string ("query", NULL, NULL, NULL,
                          (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
 
+  properties [PROP_FILE_FILTER] =
+    g_param_spec_boxed ("file-filter", NULL, NULL, G_TYPE_STRV,
+                        (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
+  properties [PROP_IGNORE_FILTER] =
+    g_param_spec_boxed ("ignore-filter", NULL, NULL, G_TYPE_STRV,
+                        (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
+
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
   line_regex = g_regex_new ("([a-zA-Z0-9\\+\\-\\.\\/_]+):(\\d+):(.*)", 0, 0, NULL);
@@ -424,6 +458,22 @@ gbp_grep_model_get_query (GbpGrepModel *self)
   return self->query;
 }
 
+const gchar * const *
+gbp_grep_model_get_file_filter (GbpGrepModel *self)
+{
+  g_return_val_if_fail (GBP_IS_GREP_MODEL (self), NULL);
+
+  return (const gchar * const *)self->file_filter;
+}
+
+const gchar * const *
+gbp_grep_model_get_ignore_filter (GbpGrepModel *self)
+{
+  g_return_val_if_fail (GBP_IS_GREP_MODEL (self), NULL);
+
+  return (const gchar * const *)self->ignore_filter;
+}
+
 void
 gbp_grep_model_set_query (GbpGrepModel *self,
                           const gchar  *query)
@@ -439,6 +489,36 @@ gbp_grep_model_set_query (GbpGrepModel *self,
     }
 }
 
+void
+gbp_grep_model_set_ignore_filter (GbpGrepModel        *self,
+                                  const gchar * const *ignore_filter)
+{
+  g_return_if_fail (GBP_IS_GREP_MODEL (self));
+
+  if (self->ignore_filter != (gchar **)ignore_filter)
+    {
+      g_strfreev (self->ignore_filter);
+      self->ignore_filter = g_strdupv ((gchar **)ignore_filter);
+      gbp_grep_model_clear_regex (self);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_IGNORE_FILTER]);
+    }
+}
+
+void
+gbp_grep_model_set_file_filter (GbpGrepModel        *self,
+                                const gchar * const *file_filter)
+{
+  g_return_if_fail (GBP_IS_GREP_MODEL (self));
+
+  if (self->file_filter != (gchar **)file_filter)
+    {
+      g_strfreev (self->file_filter);
+      self->file_filter = g_strdupv ((gchar **)file_filter);
+      gbp_grep_model_clear_regex (self);
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE_FILTER]);
+    }
+}
+
 /**
  * gbp_grep_model_get_directory:
  * @self: a #GbpGrepModel
@@ -573,6 +653,9 @@ gbp_grep_model_create_launcher (GbpGrepModel *self)
   GFile *workdir;
   GType git_vcs;
   gboolean use_git_grep = FALSE;
+  gchar **file_filters;
+  gchar **ignore_filters;
+  gsize i;
 
   g_assert (GBP_IS_GREP_MODEL (self));
   g_assert (self->query != NULL);
@@ -664,6 +747,57 @@ gbp_grep_model_create_launcher (GbpGrepModel *self)
       ide_subprocess_launcher_push_argv (launcher, "^.{0,256}$");
     }
 
+  if (self->file_filter != NULL)
+    {
+      if (use_git_grep)
+        {
+          ide_subprocess_launcher_push_argv (launcher, "--");
+        }
+
+      for (i = 0; self->file_filter [i]; i++)
+        {
+          gchar *file_filter = self->file_filter [i];
+          g_autofree gchar *file_filter_pattern;
+          if (use_git_grep)
+            {
+              file_filter_pattern = g_strconcat ("*/", file_filter, NULL);
+              ide_subprocess_launcher_push_argv (launcher, file_filter_pattern);
+            }
+          else
+            {
+              file_filter_pattern = g_strdup (file_filter);
+              ide_subprocess_launcher_push_argv (launcher, "--include");
+              ide_subprocess_launcher_push_argv (launcher, file_filter);
+            }
+        }
+    }
+
+  if (self->ignore_filter != NULL)
+    {
+      if (use_git_grep && self->file_filter == NULL)
+        {
+          ide_subprocess_launcher_push_argv (launcher, "--");
+        }
+
+      for (i = 0; self->ignore_filter [i]; i++)
+        {
+          gchar *ignore_filter = self->ignore_filter [i];
+
+          g_autofree gchar *ignore_filter_pattern;
+          if (use_git_grep)
+            {
+              ignore_filter_pattern = g_strconcat (":(exclude)", ignore_filter, "/", NULL);
+              ide_subprocess_launcher_push_argv (launcher, ignore_filter_pattern);
+            }
+          else
+            {
+              ignore_filter_pattern = g_strdup (ignore_filter);
+              ide_subprocess_launcher_push_argv (launcher, "--exclude-dir");
+              ide_subprocess_launcher_push_argv (launcher, ignore_filter);
+            }
+        }
+    }
+
   if (g_file_test (path, G_FILE_TEST_IS_DIR))
     {
       ide_subprocess_launcher_set_cwd (launcher, path);
diff --git a/src/plugins/grep/gbp-grep-model.h b/src/plugins/grep/gbp-grep-model.h
index 863934bf6..b639d441c 100644
--- a/src/plugins/grep/gbp-grep-model.h
+++ b/src/plugins/grep/gbp-grep-model.h
@@ -45,42 +45,48 @@ typedef struct
 
 G_DECLARE_FINAL_TYPE (GbpGrepModel, gbp_grep_model, GBP, GREP_MODEL, IdeObject)
 
-GbpGrepModel *gbp_grep_model_new                    (IdeContext              *context);
-GFile        *gbp_grep_model_get_directory          (GbpGrepModel            *self);
-void          gbp_grep_model_set_directory          (GbpGrepModel            *self,
-                                                     GFile                   *directory);
-gboolean      gbp_grep_model_get_use_regex          (GbpGrepModel            *self);
-void          gbp_grep_model_set_use_regex          (GbpGrepModel            *self,
-                                                     gboolean                 use_regex);
-gboolean      gbp_grep_model_get_recursive          (GbpGrepModel            *self);
-void          gbp_grep_model_set_recursive          (GbpGrepModel            *self,
-                                                     gboolean                 recursive);
-gboolean      gbp_grep_model_get_case_sensitive     (GbpGrepModel            *self);
-void          gbp_grep_model_set_case_sensitive     (GbpGrepModel            *self,
-                                                     gboolean                 case_sensitive);
-gboolean      gbp_grep_model_get_at_word_boundaries (GbpGrepModel            *self);
-void          gbp_grep_model_set_at_word_boundaries (GbpGrepModel            *self,
-                                                     gboolean                 at_word_boundaries);
-const gchar  *gbp_grep_model_get_query              (GbpGrepModel            *self);
-void          gbp_grep_model_set_query              (GbpGrepModel            *self,
-                                                     const gchar             *query);
-GPtrArray    *gbp_grep_model_create_edits           (GbpGrepModel            *self);
-void          gbp_grep_model_select_all             (GbpGrepModel            *self);
-void          gbp_grep_model_select_none            (GbpGrepModel            *self);
-void          gbp_grep_model_toggle_mode            (GbpGrepModel            *self);
-void          gbp_grep_model_toggle_row             (GbpGrepModel            *self,
-                                                     GtkTreeIter             *iter);
-void          gbp_grep_model_get_line               (GbpGrepModel            *self,
-                                                     GtkTreeIter             *iter,
-                                                     const GbpGrepModelLine **line);
-GFile        *gbp_grep_model_get_file               (GbpGrepModel            *self,
-                                                     const gchar             *path);
-void          gbp_grep_model_scan_async             (GbpGrepModel            *self,
-                                                     GCancellable            *cancellable,
-                                                     GAsyncReadyCallback      callback,
-                                                     gpointer                 user_data);
-gboolean      gbp_grep_model_scan_finish            (GbpGrepModel            *self,
-                                                     GAsyncResult            *result,
-                                                     GError                 **error);
+GbpGrepModel        *gbp_grep_model_new                    (IdeContext              *context);
+GFile               *gbp_grep_model_get_directory          (GbpGrepModel            *self);
+void                 gbp_grep_model_set_directory          (GbpGrepModel            *self,
+                                                            GFile                   *directory);
+gboolean             gbp_grep_model_get_use_regex          (GbpGrepModel            *self);
+void                 gbp_grep_model_set_use_regex          (GbpGrepModel            *self,
+                                                            gboolean                 use_regex);
+gboolean             gbp_grep_model_get_recursive          (GbpGrepModel            *self);
+void                 gbp_grep_model_set_recursive          (GbpGrepModel            *self,
+                                                            gboolean                 recursive);
+gboolean             gbp_grep_model_get_case_sensitive     (GbpGrepModel            *self);
+void                 gbp_grep_model_set_case_sensitive     (GbpGrepModel            *self,
+                                                            gboolean                 case_sensitive);
+gboolean             gbp_grep_model_get_at_word_boundaries (GbpGrepModel            *self);
+void                 gbp_grep_model_set_at_word_boundaries (GbpGrepModel            *self,
+                                                            gboolean                 at_word_boundaries);
+const gchar         *gbp_grep_model_get_query              (GbpGrepModel            *self);
+void                 gbp_grep_model_set_query              (GbpGrepModel            *self,
+                                                            const gchar             *query);
+const gchar * const *gbp_grep_model_get_file_filter        (GbpGrepModel            *self);
+void                 gbp_grep_model_set_file_filter        (GbpGrepModel            *self,
+                                                            const gchar * const     *file_filter);
+const gchar * const *gbp_grep_model_get_ignore_filter      (GbpGrepModel            *self);
+void                 gbp_grep_model_set_ignore_filter      (GbpGrepModel            *self,
+                                                            const gchar * const     *ignore_filter);
+GPtrArray           *gbp_grep_model_create_edits           (GbpGrepModel            *self);
+void                 gbp_grep_model_select_all             (GbpGrepModel            *self);
+void                 gbp_grep_model_select_none            (GbpGrepModel            *self);
+void                 gbp_grep_model_toggle_mode            (GbpGrepModel            *self);
+void                 gbp_grep_model_toggle_row             (GbpGrepModel            *self,
+                                                            GtkTreeIter             *iter);
+void                 gbp_grep_model_get_line               (GbpGrepModel            *self,
+                                                            GtkTreeIter             *iter,
+                                                            const GbpGrepModelLine **line);
+GFile               *gbp_grep_model_get_file               (GbpGrepModel            *self,
+                                                            const gchar             *path);
+void                 gbp_grep_model_scan_async             (GbpGrepModel            *self,
+                                                            GCancellable            *cancellable,
+                                                            GAsyncReadyCallback      callback,
+                                                            gpointer                 user_data);
+gboolean             gbp_grep_model_scan_finish            (GbpGrepModel            *self,
+                                                            GAsyncResult            *result,
+                                                            GError                 **error);
 
 G_END_DECLS
diff --git a/src/plugins/grep/gbp-grep-popover.c b/src/plugins/grep/gbp-grep-popover.c
index af2df8e2a..7c6610ec3 100644
--- a/src/plugins/grep/gbp-grep-popover.c
+++ b/src/plugins/grep/gbp-grep-popover.c
@@ -37,6 +37,10 @@ struct _GbpGrepPopover
   GFile          *file;
 
   GtkEntry       *entry;
+  GtkEntry       *file_filter;
+  GtkEntry       *ignore_filter;
+  char          **file_filters;
+  char          **ignore_filters;
   GtkButton      *button;
   GtkCheckButton *regex_button;
   GtkCheckButton *whole_button;
@@ -90,6 +94,10 @@ gbp_grep_popover_button_clicked_cb (GbpGrepPopover *self,
   gboolean at_word_boundaries;
   gboolean case_sensitive;
   gboolean recursive;
+  gchar *file_filter;
+  gchar **file_filters;
+  gchar *ignore_filter;
+  gchar **ignore_filters;
 
   g_assert (GBP_IS_GREP_POPOVER (self));
   g_assert (GTK_IS_BUTTON (button));
@@ -111,6 +119,34 @@ gbp_grep_popover_button_clicked_cb (GbpGrepPopover *self,
   gbp_grep_model_set_case_sensitive (model, case_sensitive);
   gbp_grep_model_set_query (model, gtk_entry_get_text (self->entry));
 
+  file_filter = gtk_entry_get_text (self->file_filter);
+  if (file_filter != NULL)
+    {
+      file_filter = g_strdup (file_filter);
+      if (g_strcmp0 (g_strstrip (file_filter), "") != 0)
+        {
+          file_filters = g_strsplit (g_strstrip (file_filter), ",", 0);
+          for (int i = 0; file_filters[i]; i++) {
+            file_filters[i] = g_strstrip (file_filters[i]);
+          }
+          gbp_grep_model_set_file_filter (model, (const gchar * const *)file_filters);
+        }
+    }
+
+  ignore_filter = gtk_entry_get_text (self->ignore_filter);
+  if (ignore_filter != NULL)
+    {
+      ignore_filter = g_strdup (ignore_filter);
+      if (g_strcmp0 (g_strstrip (ignore_filter), "") != 0)
+        {
+          ignore_filters = g_strsplit (g_strstrip (ignore_filter), ",", 0);
+          for (int i = 0; ignore_filters[i]; i++) {
+            ignore_filters[i] = g_strstrip (ignore_filters[i]);
+          }
+          gbp_grep_model_set_ignore_filter (model, (const gchar * const *)ignore_filters);
+        }
+    }
+
   if (gtk_widget_get_visible (GTK_WIDGET (self->recursive_button)))
     gbp_grep_model_set_recursive (model, recursive);
   else
@@ -218,6 +254,8 @@ gbp_grep_popover_class_init (GbpGrepPopoverClass *klass)
   gtk_widget_class_set_template_from_resource (widget_class, "/plugins/grep/gbp-grep-popover.ui");
   gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, button);
   gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, entry);
+  gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, file_filter);
+  gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, ignore_filter);
   gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, regex_button);
   gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, whole_button);
   gtk_widget_class_bind_template_child (widget_class, GbpGrepPopover, case_button);
diff --git a/src/plugins/grep/gbp-grep-popover.ui b/src/plugins/grep/gbp-grep-popover.ui
index 2a8baa2c8..80b406183 100644
--- a/src/plugins/grep/gbp-grep-popover.ui
+++ b/src/plugins/grep/gbp-grep-popover.ui
@@ -19,10 +19,9 @@
         </child>
         <child>
           <object class="GtkBox">
-            <property name="margin-top">6</property>
-            <property name="orientation">horizontal</property>
-            <property name="spacing">6</property>
-            <property name="visible">true</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
             <child>
               <object class="GtkEntry" id="entry">
                 <property name="placeholder-text" translatable="yes">Search for…</property>
@@ -31,14 +30,34 @@
               </object>
             </child>
             <child>
-              <object class="GtkButton" id="button">
+              <object class="GtkEntry" id="file_filter">
+                <property name="placeholder-text" translatable="yes">File filter…</property>
+                <property name="width-chars">24</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkEntry" id="ignore_filter">
+                <property name="placeholder-text" translatable="yes">Dirs to ignore…</property>
+                <property name="width-chars">24</property>
+                <property name="visible">true</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkButton" id="button">
                 <property name="hexpand">false</property>
                 <property name="halign">end</property>
-                <property name="label" translatable="yes">Find</property>
+                    <property name="label" translatable="yes">Find</property>
                 <property name="visible">true</property>
-                <style>
-                  <class name="suggested-action"/>
-                </style>
+                    <style>
+                      <class name="suggested-action"/>
+                    </style>
+                  </object>
+                </child>
               </object>
             </child>
           </object>


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