[gtksourceview/wip/chergert/snippets] snippets: more XML parsing and query/lookup of snippets
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/snippets] snippets: more XML parsing and query/lookup of snippets
- Date: Tue, 28 Jan 2020 23:15:10 +0000 (UTC)
commit 5c3c1ff38360d67710f9d694c3861f964fed23fc
Author: Christian Hergert <chergert redhat com>
Date: Tue Jan 28 15:14:53 2020 -0800
snippets: more XML parsing and query/lookup of snippets
gtksourceview/gtksourcesnippetbundle-private.h | 24 ++-
gtksourceview/gtksourcesnippetbundle.c | 229 ++++++++++++++++++++++++-
gtksourceview/gtksourcesnippetchunk-private.h | 3 +
gtksourceview/gtksourcesnippetmanager.c | 159 +++++++++++++----
gtksourceview/gtksourcesnippetmanager.h | 21 ++-
tests/test-snippets.c | 24 ++-
6 files changed, 410 insertions(+), 50 deletions(-)
---
diff --git a/gtksourceview/gtksourcesnippetbundle-private.h b/gtksourceview/gtksourcesnippetbundle-private.h
index 0b1e0d75..1cb71d79 100644
--- a/gtksourceview/gtksourcesnippetbundle-private.h
+++ b/gtksourceview/gtksourcesnippetbundle-private.h
@@ -19,7 +19,7 @@
#pragma once
-#include <glib-object.h>
+#include <gio/gio.h>
#include "gtksourcetypes.h"
#include "gtksourcetypes-private.h"
@@ -40,7 +40,25 @@ typedef struct
G_DECLARE_FINAL_TYPE (GtkSourceSnippetBundle, _gtk_source_snippet_bundle, GTK_SOURCE, SNIPPET_BUNDLE,
GObject)
-GtkSourceSnippetBundle *_gtk_source_snippet_bundle_new_from_file (const gchar *path,
- GtkSourceSnippetManager *manager);
+G_GNUC_INTERNAL
+GtkSourceSnippetBundle *_gtk_source_snippet_bundle_new (void);
+G_GNUC_INTERNAL
+GtkSourceSnippetBundle *_gtk_source_snippet_bundle_new_from_file (const gchar *path,
+ GtkSourceSnippetManager *manager);
+G_GNUC_INTERNAL
+void _gtk_source_snippet_bundle_merge (GtkSourceSnippetBundle *self,
+ GtkSourceSnippetBundle *other);
+G_GNUC_INTERNAL
+const gchar **_gtk_source_snippet_bundle_list_groups (GtkSourceSnippetBundle *self);
+G_GNUC_INTERNAL
+GtkSourceSnippet *_gtk_source_snippet_bundle_get_snippet (GtkSourceSnippetBundle *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger);
+G_GNUC_INTERNAL
+GListModel *_gtk_source_snippet_bundle_list_matching (GtkSourceSnippetBundle *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger_prefix);
G_END_DECLS
diff --git a/gtksourceview/gtksourcesnippetbundle.c b/gtksourceview/gtksourcesnippetbundle.c
index 24ac6e08..2ee758aa 100644
--- a/gtksourceview/gtksourcesnippetbundle.c
+++ b/gtksourceview/gtksourcesnippetbundle.c
@@ -41,7 +41,37 @@ typedef struct
GString *text;
} ParseState;
-G_DEFINE_TYPE (GtkSourceSnippetBundle, _gtk_source_snippet_bundle, G_TYPE_OBJECT)
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtkSourceSnippetBundle, _gtk_source_snippet_bundle, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static gint
+compare_infos (const GtkSourceSnippetInfo *info_a,
+ const GtkSourceSnippetInfo *info_b)
+{
+ gint ret = g_strcmp0 (info_a->language, info_b->language);
+
+ if (ret == 0)
+ {
+ ret = g_strcmp0 (info_a->trigger, info_b->trigger);
+ }
+
+ return ret;
+}
+
+static void
+gtk_source_snippet_bundle_dispose (GObject *object)
+{
+ GtkSourceSnippetBundle *self = (GtkSourceSnippetBundle *)object;
+
+ if (self->infos->len > 0)
+ {
+ g_array_remove_range (self->infos, 0, self->infos->len);
+ }
+
+ G_OBJECT_CLASS (_gtk_source_snippet_bundle_parent_class)->dispose (object);
+}
static void
gtk_source_snippet_bundle_finalize (GObject *object)
@@ -58,6 +88,7 @@ _gtk_source_snippet_bundle_class_init (GtkSourceSnippetBundleClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = gtk_source_snippet_bundle_dispose;
object_class->finalize = gtk_source_snippet_bundle_finalize;
}
@@ -361,9 +392,9 @@ gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle *self,
state.text = g_string_new (NULL);
context = g_markup_parse_context_new (&snippets_parser,
- (G_MARKUP_TREAT_CDATA_AS_TEXT |
- G_MARKUP_PREFIX_ERROR_POSITION),
- &state, NULL);
+ (G_MARKUP_TREAT_CDATA_AS_TEXT |
+ G_MARKUP_PREFIX_ERROR_POSITION),
+ &state, NULL);
ret = g_markup_parse_context_parse (context, contents, length, NULL);
@@ -377,6 +408,8 @@ gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle *self,
g_markup_parse_context_free (context);
g_free (contents);
+ g_array_sort (self->infos, (GCompareFunc) compare_infos);
+
#if 0
for (guint i = 0; i < self->infos->len; i++)
{
@@ -390,6 +423,13 @@ gtk_source_snippet_bundle_parse (GtkSourceSnippetBundle *self,
return ret;
}
+
+GtkSourceSnippetBundle *
+_gtk_source_snippet_bundle_new (void)
+{
+ return g_object_new (GTK_SOURCE_TYPE_SNIPPET_BUNDLE, NULL);
+}
+
GtkSourceSnippetBundle *
_gtk_source_snippet_bundle_new_from_file (const gchar *path,
GtkSourceSnippetManager *manager)
@@ -399,7 +439,7 @@ _gtk_source_snippet_bundle_new_from_file (const gchar *path,
g_return_val_if_fail (path != NULL, NULL);
g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (manager), NULL);
- self = g_object_new (GTK_SOURCE_TYPE_SNIPPET_BUNDLE, NULL);
+ self = _gtk_source_snippet_bundle_new ();
if (!gtk_source_snippet_bundle_parse (self, manager, path))
{
@@ -408,3 +448,182 @@ _gtk_source_snippet_bundle_new_from_file (const gchar *path,
return g_steal_pointer (&self);
}
+
+void
+_gtk_source_snippet_bundle_merge (GtkSourceSnippetBundle *self,
+ GtkSourceSnippetBundle *other)
+{
+ g_return_if_fail (GTK_SOURCE_IS_SNIPPET_BUNDLE (self));
+ g_return_if_fail (!other || GTK_SOURCE_IS_SNIPPET_BUNDLE (other));
+
+ if (other == NULL || other->infos->len == 0)
+ {
+ return;
+ }
+
+ g_array_append_vals (self->infos, other->infos->data, other->infos->len);
+ g_array_sort (self->infos, (GCompareFunc) compare_infos);
+}
+
+const gchar **
+_gtk_source_snippet_bundle_list_groups (GtkSourceSnippetBundle *self)
+{
+ GHashTable *ht;
+ guint len;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_BUNDLE (self), NULL);
+
+ ht = g_hash_table_new (NULL, NULL);
+
+ for (guint i = 0; i < self->infos->len; i++)
+ {
+ const GtkSourceSnippetInfo *info = &g_array_index (self->infos, GtkSourceSnippetInfo, i);
+
+ /* We can use pointer comparison because all of these strings
+ * are interned using the same #GStringChunk with
+ * g_string_chunk_insert_const().
+ */
+ if (!g_hash_table_contains (ht, info->group))
+ {
+ g_hash_table_add (ht, (gchar *)info->group);
+ }
+ }
+
+ return (const gchar **)g_hash_table_get_keys_as_array (ht, &len);
+}
+
+static GtkSourceSnippet *
+create_snippet_from_info (const GtkSourceSnippetInfo *info)
+{
+ GtkSourceSnippet *snippet;
+
+ g_assert (info != NULL);
+
+ snippet = gtk_source_snippet_new (info->trigger, info->language);
+ gtk_source_snippet_set_description (snippet, info->description);
+
+ g_warning ("TODO: Parse snippet text");
+
+ return g_steal_pointer (&snippet);
+}
+
+static gboolean
+info_matches (const GtkSourceSnippetInfo *info,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger,
+ gboolean trigger_prefix_only)
+{
+ g_assert (info != NULL);
+
+ if (group != NULL && g_strcmp0 (group, info->group) != 0)
+ return FALSE;
+
+ if (language_id != NULL && g_strcmp0 (language_id, info->language) != 0)
+ return FALSE;
+
+ if (trigger != NULL)
+ {
+ if (info->trigger == NULL)
+ return FALSE;
+
+ if (trigger_prefix_only)
+ {
+ if (!g_str_has_prefix (info->trigger, trigger))
+ return FALSE;
+ }
+ else
+ {
+ if (!g_str_equal (trigger, info->trigger))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+GtkSourceSnippet *
+_gtk_source_snippet_bundle_get_snippet (GtkSourceSnippetBundle *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_BUNDLE (self), NULL);
+
+ /* TODO: This could use bsearch(), but the complication here is that
+ * we want to ignore fields when the key field is NULL and the
+ * sort order for infos doesn't match what we are querying, so
+ * we would need an alternate index.
+ */
+
+ for (guint i = 0; i < self->infos->len; i++)
+ {
+ const GtkSourceSnippetInfo *info = &g_array_index (self->infos, GtkSourceSnippetInfo, i);
+
+ if (info_matches (info, group, language_id, trigger, FALSE))
+ {
+ return create_snippet_from_info (info);
+ }
+ }
+
+ return NULL;
+}
+
+GListModel *
+_gtk_source_snippet_bundle_list_matching (GtkSourceSnippetBundle *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger_prefix)
+{
+ GtkSourceSnippetBundle *ret;
+
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_BUNDLE (self), NULL);
+
+ ret = _gtk_source_snippet_bundle_new ();
+
+ for (guint i = 0; i < self->infos->len; i++)
+ {
+ const GtkSourceSnippetInfo *info = &g_array_index (self->infos, GtkSourceSnippetInfo, i);
+
+ if (info_matches (info, group, language_id, trigger_prefix, TRUE))
+ {
+ g_array_append_vals (ret->infos, info, 1);
+ }
+ }
+
+ return G_LIST_MODEL (g_steal_pointer (&ret));
+}
+
+static GType
+gtk_source_snippet_bundle_get_item_type (GListModel *model)
+{
+ return GTK_SOURCE_TYPE_SNIPPET;
+}
+
+static guint
+gtk_source_snippet_bundle_get_n_items (GListModel *model)
+{
+ return GTK_SOURCE_SNIPPET_BUNDLE (model)->infos->len;
+}
+
+static gpointer
+gtk_source_snippet_bundle_get_item (GListModel *model,
+ guint position)
+{
+ GtkSourceSnippetBundle *self = GTK_SOURCE_SNIPPET_BUNDLE (model);
+
+ if (position >= self->infos->len)
+ {
+ return NULL;
+ }
+
+ return create_snippet_from_info (&g_array_index (self->infos, GtkSourceSnippetInfo, position));
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+ iface->get_item_type = gtk_source_snippet_bundle_get_item_type;
+ iface->get_n_items = gtk_source_snippet_bundle_get_n_items;
+ iface->get_item = gtk_source_snippet_bundle_get_item;
+}
diff --git a/gtksourceview/gtksourcesnippetchunk-private.h b/gtksourceview/gtksourcesnippetchunk-private.h
index e19d621f..052aa864 100644
--- a/gtksourceview/gtksourcesnippetchunk-private.h
+++ b/gtksourceview/gtksourcesnippetchunk-private.h
@@ -42,9 +42,12 @@ struct _GtkSourceSnippetChunk
guint text_set : 1;
};
+G_GNUC_INTERNAL
void _gtk_source_snippet_chunk_save_text (GtkSourceSnippetChunk *chunk);
+G_GNUC_INTERNAL
gboolean _gtk_source_snippet_chunk_contains (GtkSourceSnippetChunk *chunk,
const GtkTextIter *iter);
+G_GNUC_INTERNAL
gboolean _gtk_source_snippet_chunk_get_bounds (GtkSourceSnippetChunk *chunk,
GtkTextIter *begin,
GtkTextIter *end);
diff --git a/gtksourceview/gtksourcesnippetmanager.c b/gtksourceview/gtksourcesnippetmanager.c
index 886ee37b..d3a5a21b 100644
--- a/gtksourceview/gtksourcesnippetmanager.c
+++ b/gtksourceview/gtksourcesnippetmanager.c
@@ -47,10 +47,29 @@
struct _GtkSourceSnippetManager
{
- GObject parent_instance;
- GStringChunk *strings;
- gchar **snippet_dirs;
- GPtrArray *bundles;
+ GObject parent_instance;
+
+ /* To reduce the number of duplicated strings, we use a GStringChunk
+ * so that all of the GtkSourceSnippetInfo structs can point to const
+ * data. The bundles use _gtk_source_snippet_manager_intern() to get
+ * an "interned" string inside this string chunk.
+ */
+ GStringChunk *strings;
+
+ /* The snippet search path to look up files containing snippets like
+ * "license.snippets".
+ */
+ gchar **search_path;
+
+ /* The GtkSourceSnippetBundle handles both parsing a single snippet
+ * file on disk as well as collecting all the parsed files together.
+ * The strings contained in it are "const", and reference @strings
+ * to reduce duplicated memory as well as fragmentation.
+ *
+ * When searching for matching snippets, by language, name etc, we
+ * query the @bundle.
+ */
+ GtkSourceSnippetBundle *bundle;
};
enum {
@@ -64,13 +83,26 @@ static GParamSpec *properties[N_PROPS];
G_DEFINE_TYPE (GtkSourceSnippetManager, gtk_source_snippet_manager, G_TYPE_OBJECT)
+static void
+gtk_source_snippet_manager_dispose (GObject *object)
+{
+ GtkSourceSnippetManager *self = GTK_SOURCE_SNIPPET_MANAGER (object);
+
+ if (self->bundle != NULL)
+ {
+ g_object_run_dispose (G_OBJECT (self->bundle));
+ }
+
+ G_OBJECT_CLASS (gtk_source_snippet_manager_parent_class)->dispose (object);
+}
+
static void
gtk_source_snippet_manager_finalize (GObject *object)
{
GtkSourceSnippetManager *self = GTK_SOURCE_SNIPPET_MANAGER (object);
- g_clear_pointer (&self->bundles, g_ptr_array_unref);
- g_clear_pointer (&self->snippet_dirs, g_strfreev);
+ g_clear_object (&self->bundle);
+ g_clear_pointer (&self->search_path, g_strfreev);
g_clear_pointer (&self->strings, g_string_chunk_free);
G_OBJECT_CLASS (gtk_source_snippet_manager_parent_class)->finalize (object);
@@ -121,7 +153,8 @@ gtk_source_snippet_manager_class_init (GtkSourceSnippetManagerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = gtk_source_snippet_manager_finalize;
+ object_class->dispose = gtk_source_snippet_manager_dispose;
+ object_class->finalize = gtk_source_snippet_manager_finalize;
object_class->set_property = gtk_source_snippet_manager_set_property;
object_class->get_property = gtk_source_snippet_manager_get_property;
@@ -148,7 +181,6 @@ gtk_source_snippet_manager_class_init (GtkSourceSnippetManagerClass *klass)
static void
gtk_source_snippet_manager_init (GtkSourceSnippetManager *self)
{
- self->bundles = g_ptr_array_new_with_free_func (g_object_unref);
}
/**
@@ -222,18 +254,18 @@ _gtk_source_snippet_manager_intern (GtkSourceSnippetManager *self,
*/
void
gtk_source_snippet_manager_set_search_path (GtkSourceSnippetManager *self,
- const gchar * const *dirs)
+ const gchar * const *dirs)
{
gchar **tmp;
g_return_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (self));
- tmp = self->snippet_dirs;
+ tmp = self->search_path;
if (dirs == NULL)
- self->snippet_dirs = _gtk_source_utils_get_default_dirs (SNIPPET_DIR);
+ self->search_path = _gtk_source_utils_get_default_dirs (SNIPPET_DIR);
else
- self->snippet_dirs = g_strdupv ((gchar **)dirs);
+ self->search_path = g_strdupv ((gchar **)dirs);
g_strfreev (tmp);
@@ -258,15 +290,16 @@ gtk_source_snippet_manager_get_search_path (GtkSourceSnippetManager *self)
{
g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (self), NULL);
- if (self->snippet_dirs == NULL)
- self->snippet_dirs = _gtk_source_utils_get_default_dirs (SNIPPET_DIR);
+ if (self->search_path == NULL)
+ self->search_path = _gtk_source_utils_get_default_dirs (SNIPPET_DIR);
- return (const gchar * const *)self->snippet_dirs;
+ return (const gchar * const *)self->search_path;
}
static void
ensure_snippets (GtkSourceSnippetManager *self)
{
+ GtkSourceSnippetBundle *bundle;
GSList *filenames;
g_assert (GTK_SOURCE_IS_SNIPPET_MANAGER (self));
@@ -276,44 +309,112 @@ ensure_snippets (GtkSourceSnippetManager *self)
SNIPPET_FILE_SUFFIX,
TRUE);
+ bundle = _gtk_source_snippet_bundle_new ();
+
for (const GSList *f = filenames; f; f = f->next)
{
const gchar *filename = f->data;
- GtkSourceSnippetBundle *bundle;
+ GtkSourceSnippetBundle *parsed;
- bundle = _gtk_source_snippet_bundle_new_from_file (filename, self);
+ parsed = _gtk_source_snippet_bundle_new_from_file (filename, self);
- if (bundle != NULL)
- g_ptr_array_add (self->bundles, bundle);
+ if (parsed != NULL)
+ _gtk_source_snippet_bundle_merge (bundle, parsed);
else
g_warning ("Error reading snippet file '%s'", filename);
+
+ g_clear_object (&parsed);
}
+ g_clear_object (&self->bundle);
+ self->bundle = g_steal_pointer (&bundle);
+
g_slist_free_full (filenames, g_free);
+
+ g_return_if_fail (GTK_SOURCE_IS_SNIPPET_BUNDLE (self->bundle));
}
/**
- * gtk_source_snippet_manager_get_snippets:
+ * gtk_source_snippet_manager_list_groups:
* @self: a #GtkSourceSnippetManager
- * @language_id: (nullable): the language identifier for the snippets or %NULL
- * for only global snippets
*
- * Gets the snippets for a specific language.
+ * List all the known groups within the snippet manager.
*
- * The resulting list also contains global snippets that apply to
- * any language, if any.
+ * The result should be freed with g_free(), and the invidual strings are
+ * owned by @self and should never be freed by the caller.
*
- * Returns: (transfer full) (nullable): a #GListModel, or %NULL
+ * Returns: (transfer container) (array zero-terminated=1) (element-type utf8):
+ * An array of strings which should be freed with g_free().
+ *
+ * Since: 5.0
+ */
+const gchar **
+gtk_source_snippet_manager_list_groups (GtkSourceSnippetManager *self)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (self), NULL);
+
+ ensure_snippets (self);
+
+ return _gtk_source_snippet_bundle_list_groups (self->bundle);
+}
+
+/**
+ * gtk_source_snippet_manager_list_matching:
+ * @self: a #GtkSourceSnippetManager
+ * @group: (nullable): a group name or %NULL
+ * @language_id: (nullable): a #GtkSourceLanguage:id or %NULL
+ * @trigger_prefix: (nullable): a prefix for a trigger to activate
+ *
+ * Queries the known snippets for those matching @group, @language_id, and/or
+ * @trigger_prefix. If any of these are %NULL, they will be ignored when
+ * filtering the available snippets.
+ *
+ * The #GListModel only contains information about the available snippets until
+ * g_list_model_get_item() is called for a specific snippet. This helps reduce
+ * the number of #GObject's that are created at runtime to those needed by
+ * the calling application.
+ *
+ * Returns: (transfer full): a #GListModel of #GtkSourceSnippet.
*
* Since: 5.0
*/
GListModel *
-gtk_source_snippet_manager_get_snippets (GtkSourceSnippetManager *self,
- const gchar *language_id)
+gtk_source_snippet_manager_list_matching (GtkSourceSnippetManager *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger_prefix)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (self), NULL);
+
+ ensure_snippets (self);
+
+ return _gtk_source_snippet_bundle_list_matching (self->bundle, group, language_id, trigger_prefix);
+}
+
+/**
+ * gtk_source_snippet_manager_get_snippet:
+ * @self: a #GtkSourceSnippetManager
+ * @group: (nullable): a group name or %NULL
+ * @language_id: (nullable): a #GtkSourceLanguage:id or %NULL
+ * @trigger: the trigger for the snippet
+ *
+ * Queries the known snippets for the first matching @group, @language_id,
+ * and/or @trigger. If @group or @language_id are %NULL, they will be ignored.
+ *
+ * Returns: (transfer full) (nullable): a #GtkSourceSnippet or %NULL if no
+ * matching snippet was found.
+ *
+ * Since: 5.0
+ */
+GtkSourceSnippet *
+gtk_source_snippet_manager_get_snippet (GtkSourceSnippetManager *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger)
{
g_return_val_if_fail (GTK_SOURCE_IS_SNIPPET_MANAGER (self), NULL);
ensure_snippets (self);
- return NULL;
+ return _gtk_source_snippet_bundle_get_snippet (self->bundle, group, language_id, trigger);
}
diff --git a/gtksourceview/gtksourcesnippetmanager.h b/gtksourceview/gtksourcesnippetmanager.h
index ee9b4a95..b6f51b95 100644
--- a/gtksourceview/gtksourcesnippetmanager.h
+++ b/gtksourceview/gtksourcesnippetmanager.h
@@ -35,14 +35,23 @@ GTK_SOURCE_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (GtkSourceSnippetManager, gtk_source_snippet_manager, GTK_SOURCE, SNIPPET_MANAGER,
GObject)
GTK_SOURCE_AVAILABLE_IN_5_0
-GtkSourceSnippetManager *gtk_source_snippet_manager_get_default (void);
+GtkSourceSnippetManager *gtk_source_snippet_manager_get_default (void);
GTK_SOURCE_AVAILABLE_IN_5_0
-const gchar * const *gtk_source_snippet_manager_get_search_path (GtkSourceSnippetManager *self);
+const gchar * const *gtk_source_snippet_manager_get_search_path (GtkSourceSnippetManager *self);
GTK_SOURCE_AVAILABLE_IN_5_0
-void gtk_source_snippet_manager_set_search_path (GtkSourceSnippetManager *self,
- const gchar * const *dirs);
+void gtk_source_snippet_manager_set_search_path (GtkSourceSnippetManager *self,
+ const gchar * const *dirs);
GTK_SOURCE_AVAILABLE_IN_5_0
-GListModel *gtk_source_snippet_manager_get_snippets (GtkSourceSnippetManager *self,
- const gchar *language_id);
+GtkSourceSnippet *gtk_source_snippet_manager_get_snippet (GtkSourceSnippetManager *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar *trigger);
+GTK_SOURCE_AVAILABLE_IN_5_0
+const gchar **gtk_source_snippet_manager_list_groups (GtkSourceSnippetManager *self);
+GTK_SOURCE_AVAILABLE_IN_5_0
+GListModel *gtk_source_snippet_manager_list_matching (GtkSourceSnippetManager *self,
+ const gchar *group,
+ const gchar *language_id,
+ const gchar
*trigger_prefix);
G_END_DECLS
diff --git a/tests/test-snippets.c b/tests/test-snippets.c
index 2d1e26be..4ba45b60 100644
--- a/tests/test-snippets.c
+++ b/tests/test-snippets.c
@@ -22,24 +22,34 @@
#include <gtksourceview/gtksource.h>
#include <gtksourceview/gtksourceinit.h>
+static const gchar *search_path[] = {
+ TOP_SRCDIR"/data/snippets",
+ NULL
+};
+
gint
main (gint argc,
gchar *argv[])
{
GtkSourceSnippetManager *mgr;
- GListModel *model;
- static const gchar *search_path[] = {
- TOP_SRCDIR"/data/snippets",
- NULL
- };
+ GtkSourceSnippet *snippet;
+ const gchar **groups;
gtk_source_init ();
mgr = gtk_source_snippet_manager_get_default ();
gtk_source_snippet_manager_set_search_path (mgr, search_path);
- model = gtk_source_snippet_manager_get_snippets (mgr, "c");
- g_clear_object (&model);
+ /* Update if you add new groups to data/snippets/ */
+ groups = gtk_source_snippet_manager_list_groups (mgr);
+ g_assert_cmpint (1, ==, g_strv_length ((gchar **)groups));
+ g_assert_cmpstr (groups[0], ==, "Licenses");
+ g_free (groups);
+
+ /* Make sure we can get gpl3 snippet for C language */
+ snippet = gtk_source_snippet_manager_get_snippet (mgr, NULL, "c", "gpl3");
+ g_assert_nonnull (snippet);
+ g_assert_finalize_object (snippet);
gtk_source_finalize ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]