[gnome-builder] patternspec: add search match helper



commit 871613147be417d645b00ed671eb5c2f583fc029
Author: Christian Hergert <christian hergert me>
Date:   Sun Mar 29 00:56:17 2015 -0700

    patternspec: add search match helper
    
    This simple pattern matcher allows for multiple words in the input
    string. It will use simple word boundaries in the haystack (space or
    underline).
    
    "gtk widg" would match "gtk_widget_show".

 libide/Makefile.am        |    2 +
 libide/ide-pattern-spec.c |  159 +++++++++++++++++++++++++++++++++++++++++++++
 libide/ide-pattern-spec.h |   41 ++++++++++++
 libide/ide.h              |    1 +
 4 files changed, 203 insertions(+), 0 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index aec1cbf..bddd37c 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -109,6 +109,8 @@ libide_1_0_la_public_sources = \
        libide/ide-log.h \
        libide/ide-object.c \
        libide/ide-object.h \
+       libide/ide-pattern-spec.c \
+       libide/ide-pattern-spec.h \
        libide/ide-process.c \
        libide/ide-process.h \
        libide/ide-progress.c \
diff --git a/libide/ide-pattern-spec.c b/libide/ide-pattern-spec.c
new file mode 100644
index 0000000..4507842
--- /dev/null
+++ b/libide/ide-pattern-spec.c
@@ -0,0 +1,159 @@
+/* ide-pattern-spec.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define G_LOG_DOMAIN "ide-pattern-spec"
+
+#include <string.h>
+
+#include "ide-pattern-spec.h"
+
+G_DEFINE_BOXED_TYPE (IdePatternSpec, ide_pattern_spec,
+                     ide_pattern_spec_ref, ide_pattern_spec_unref)
+
+/**
+ * SECTION:ide-pattern-spec:
+ *
+ * This works similar to GPatternSpec except the query syntax is different.
+ * It tries to mtach word boundaries, but with matching partial words up
+ * to those boundaries. For example, "gtk widg" would match "gtk_widget_show".
+ * Word boundaries include '_' and ' '. If any character is uppercase, then
+ * case sensitivity is used.
+ */
+
+struct _IdePatternSpec
+{
+  volatile gint   ref_count;
+  gchar          *needle;
+  gchar         **parts;
+  guint           case_sensitive : 1;
+};
+
+IdePatternSpec *
+ide_pattern_spec_new (const gchar *needle)
+{
+  IdePatternSpec *self;
+  const gchar *tmp;
+
+  g_return_val_if_fail (needle, NULL);
+
+  self = g_new0 (IdePatternSpec, 1);
+  self->ref_count = 1;
+  self->needle = g_strdup (needle);
+  self->parts = g_strsplit (needle, " ", 0);
+  self->case_sensitive = FALSE;
+
+  for (tmp = needle; tmp; tmp = g_utf8_next_char (tmp))
+    {
+      if (g_unichar_isupper (g_utf8_get_char (tmp)))
+        {
+          self->case_sensitive = TRUE;
+          break;
+        }
+    }
+
+  return self;
+}
+
+static void
+ide_pattern_spec_free (IdePatternSpec *self)
+{
+  g_strfreev (self->parts);
+  g_free (self->needle);
+  g_free (self);
+}
+
+static inline gboolean
+is_word_break (gunichar ch)
+{
+  return (ch == ' ' || ch == '_');
+}
+
+static const gchar *
+next_word_start (const gchar *haystack)
+{
+  for (; *haystack; haystack = g_utf8_next_char (haystack))
+    {
+      gunichar ch = g_utf8_get_char (haystack);
+
+      if (is_word_break (ch))
+        break;
+    }
+
+  for (; *haystack; haystack = g_utf8_next_char (haystack))
+    {
+      gunichar ch = g_utf8_get_char (haystack);
+
+      if (is_word_break (ch))
+        continue;
+
+      break;
+    }
+
+  g_return_val_if_fail (*haystack == '\0' || !is_word_break (*haystack), NULL);
+
+  return haystack;
+}
+
+gboolean
+ide_pattern_spec_match (IdePatternSpec *self,
+                        const gchar    *haystack)
+{
+  gsize i;
+
+  g_return_val_if_fail (self, FALSE);
+  g_return_val_if_fail (haystack, FALSE);
+
+  for (i = 0; (haystack != NULL) && self->parts [i]; i++)
+    {
+      if (self->parts [i][0] == '\0')
+        continue;
+
+      if (self->case_sensitive)
+        haystack = strstr (haystack, self->parts [i]);
+      else
+        haystack = strcasestr (haystack, self->parts [i]);
+
+      if (haystack == NULL)
+        return FALSE;
+
+      haystack = next_word_start (haystack + strlen (self->parts [i]));
+    }
+
+  return TRUE;
+}
+
+IdePatternSpec *
+ide_pattern_spec_ref (IdePatternSpec *self)
+{
+  g_return_val_if_fail (self, NULL);
+  g_return_val_if_fail (self->ref_count > 0, NULL);
+
+  g_atomic_int_inc (&self->ref_count);
+
+  return self;
+}
+
+void
+ide_pattern_spec_unref (IdePatternSpec *self)
+{
+  g_return_if_fail (self);
+  g_return_if_fail (self->ref_count > 0);
+
+  if (g_atomic_int_dec_and_test (&self->ref_count))
+    ide_pattern_spec_free (self);
+}
diff --git a/libide/ide-pattern-spec.h b/libide/ide-pattern-spec.h
new file mode 100644
index 0000000..66ddda0
--- /dev/null
+++ b/libide/ide-pattern-spec.h
@@ -0,0 +1,41 @@
+/* ide-pattern-spec.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef IDE_MATCH_PATTERN_H
+#define IDE_MATCH_PATTERN_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _IdePatternSpec IdePatternSpec;
+
+#define IDE_TYPE_PATTERN_SPEC (ide_pattern_spec_get_type())
+
+GType           ide_pattern_spec_get_type (void);
+IdePatternSpec *ide_pattern_spec_new      (const gchar    *keywords);
+IdePatternSpec *ide_pattern_spec_ref      (IdePatternSpec *self);
+void            ide_pattern_spec_unref    (IdePatternSpec *self);
+gboolean        ide_pattern_spec_match    (IdePatternSpec *self,
+                                           const gchar     *haystack);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdePatternSpec, ide_pattern_spec_unref)
+
+G_END_DECLS
+
+#endif /* IDE_MATCH_PATTERN_H */
diff --git a/libide/ide.h b/libide/ide.h
index ab3c64f..26c4957 100644
--- a/libide/ide.h
+++ b/libide/ide.h
@@ -54,6 +54,7 @@ G_BEGIN_DECLS
 #include "ide-language.h"
 #include "ide-log.h"
 #include "ide-object.h"
+#include "ide-pattern-spec.h"
 #include "ide-process.h"
 #include "ide-progress.h"
 #include "ide-project.h"


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