[gnome-builder/wip/chergert/completion] snippets: refactor snippets to reduce memory overhead



commit e4a93cd9984bdf88e5309e856296623b4cd32e7b
Author: Christian Hergert <chergert redhat com>
Date:   Fri Jun 1 03:30:50 2018 -0700

    snippets: refactor snippets to reduce memory overhead
    
    This combines a few things as we get started on cleaning up the snippet
    system. First, we drop the Source from the name since it just makes things
    too long. Most importantly, IdeSnippetStorage allows us to keep mapped
    files or gresouces (also mapped) and parse information about the snippets
    without creating them. Then we can create snippets on demand when the user
    activates a snippet from completion.
    
    The completion provider has not yet been finished.

 src/libide/ide-context.c                           |  54 +--
 src/libide/ide-context.h                           |   4 +-
 src/libide/ide-types.h                             |   9 +-
 src/libide/ide.h                                   |  10 +-
 ...-source-snippet-chunk.c => ide-snippet-chunk.c} | 150 +++----
 src/libide/snippets/ide-snippet-chunk.h            |  64 +++
 .../snippets/ide-snippet-completion-provider.c     |  58 +++
 ...rovider.h => ide-snippet-completion-provider.h} |  23 +-
 ...rce-snippet-context.c => ide-snippet-context.c} |  92 ++--
 ...rce-snippet-context.h => ide-snippet-context.h} |  30 +-
 src/libide/snippets/ide-snippet-model.c            | 177 ++++++++
 src/libide/snippets/ide-snippet-model.h            |  42 ++
 ...ource-snippet-parser.c => ide-snippet-parser.c} | 204 +++++----
 src/libide/snippets/ide-snippet-parser.h           |  46 ++
 src/libide/snippets/ide-snippet-private.h          |  59 +++
 src/libide/snippets/ide-snippet-storage.c          | 443 ++++++++++++++++++++
 src/libide/snippets/ide-snippet-storage.h          |  73 ++++
 .../{ide-source-snippet.c => ide-snippet.c}        | 462 ++++++++++-----------
 src/libide/snippets/ide-snippet.h                  |  71 ++++
 src/libide/snippets/ide-source-snippet-chunk.h     |  62 ---
 .../snippets/ide-source-snippet-completion-item.c  | 179 --------
 .../snippets/ide-source-snippet-completion-item.h  |  37 --
 .../ide-source-snippet-completion-provider.c       | 442 --------------------
 src/libide/snippets/ide-source-snippet-parser.h    |  41 --
 src/libide/snippets/ide-source-snippet-private.h   |  58 ---
 src/libide/snippets/ide-source-snippet.h           |  71 ----
 src/libide/snippets/ide-source-snippets-manager.c  | 404 ------------------
 src/libide/snippets/ide-source-snippets-manager.h  |  50 ---
 src/libide/snippets/ide-source-snippets.c          | 210 ----------
 src/libide/snippets/ide-source-snippets.h          |  52 ---
 src/libide/snippets/meson.build                    |  30 +-
 src/libide/sourceview/ide-source-view.c            | 121 +++---
 src/libide/sourceview/ide-source-view.h            |   4 +-
 src/plugins/clang/ide-clang-completion-item.c      |  72 ++--
 src/plugins/clang/ide-clang-completion-item.h      |   2 +-
 src/plugins/clang/ide-clang-completion-provider.c  |  16 +-
 src/plugins/ctags/ide-ctags-completion-item.c      |  34 +-
 src/plugins/ctags/ide-ctags-completion-item.h      |   2 +-
 src/plugins/ctags/ide-ctags-completion-provider.c  |   2 +-
 src/plugins/jedi/jedi_plugin.py                    |  14 +-
 src/tests/test-snippet-parser.c                    |  26 +-
 src/tests/test-snippet.c                           | 324 ---------------
 42 files changed, 1733 insertions(+), 2591 deletions(-)
---
diff --git a/src/libide/ide-context.c b/src/libide/ide-context.c
index 90ed4df91..830a2fe59 100644
--- a/src/libide/ide-context.c
+++ b/src/libide/ide-context.c
@@ -53,7 +53,7 @@
 #include "runtimes/ide-runtime-manager.h"
 #include "search/ide-search-engine.h"
 #include "search/ide-search-provider.h"
-#include "snippets/ide-source-snippets-manager.h"
+#include "snippets/ide-snippet-storage.h"
 #include "testing/ide-test-manager.h"
 #include "toolchain/ide-toolchain-manager.h"
 #include "transfers/ide-transfer-manager.h"
@@ -82,7 +82,7 @@
  * #IdeBufferManager, #IdeBuildManager, #IdeBuildSystem,
  * #IdeConfigurationManager, #IdeDiagnosticsManager, #IdeDebugManager,
  * #IdeDeviceManager, #IdeRuntimeManager, #IdeRunManager, #IdeSearchEngine,
- * #IdeSourceSnippetsManager, #IdeTestManager, #IdeProject, and #IdeVcs.
+ * #IdeSnippetStorage, #IdeTestManager, #IdeProject, and #IdeVcs.
  *
  * ## Services
  *
@@ -124,7 +124,7 @@ struct _IdeContext
   IdeRuntimeManager        *runtime_manager;
   IdeToolchainManager      *toolchain_manager;
   IdeSearchEngine          *search_engine;
-  IdeSourceSnippetsManager *snippets_manager;
+  IdeSnippetStorage        *snippets;
   IdeTestManager           *test_manager;
   IdeProject               *project;
   GFile                    *project_file;
@@ -168,7 +168,7 @@ enum {
   PROP_RUNTIME_MANAGER,
   PROP_TOOLCHAIN_MANAGER,
   PROP_SEARCH_ENGINE,
-  PROP_SNIPPETS_MANAGER,
+  PROP_SNIPPETS,
   PROP_VCS,
   PROP_UNSAVED_FILES,
   LAST_PROP
@@ -316,18 +316,20 @@ ide_context_get_documentation (IdeContext *self)
 }
 
 /**
- * ide_context_get_snippets_manager:
+ * ide_context_get_snippets:
  *
- * Gets the #IdeContext:snippets-manager property.
+ * Gets the #IdeContext:snippets property.
  *
- * Returns: (transfer none): An #IdeSourceSnippetsManager.
+ * Returns: (transfer none): An #IdeSnippetStorage.
+ *
+ * Since: 3.30
  */
-IdeSourceSnippetsManager *
-ide_context_get_snippets_manager (IdeContext *self)
+IdeSnippetStorage *
+ide_context_get_snippets (IdeContext *self)
 {
   g_return_val_if_fail (IDE_IS_CONTEXT (self), NULL);
 
-  return self->snippets_manager;
+  return self->snippets;
 }
 
 /**
@@ -675,8 +677,8 @@ ide_context_get_property (GObject    *object,
       g_value_set_object (value, ide_context_get_search_engine (self));
       break;
 
-    case PROP_SNIPPETS_MANAGER:
-      g_value_set_object (value, ide_context_get_snippets_manager (self));
+    case PROP_SNIPPETS:
+      g_value_set_object (value, ide_context_get_snippets (self));
       break;
 
     case PROP_UNSAVED_FILES:
@@ -793,12 +795,12 @@ ide_context_class_init (IdeContextClass *klass)
                          IDE_TYPE_SEARCH_ENGINE,
                          (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
-  properties [PROP_SNIPPETS_MANAGER] =
-    g_param_spec_object ("snippets-manager",
-                         "Snippets Manager",
+  properties [PROP_SNIPPETS] =
+    g_param_spec_object ("snippets",
+                         "Snippets",
                          "The snippets manager for the context.",
-                         IDE_TYPE_SOURCE_SNIPPETS_MANAGER,
-                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+                         IDE_TYPE_SNIPPET_STORAGE,
+                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   properties [PROP_UNSAVED_FILES] =
     g_param_spec_object ("unsaved-files",
@@ -935,7 +937,7 @@ ide_context_init (IdeContext *self)
                                       "context", self,
                                       NULL);
 
-  self->snippets_manager = g_object_new (IDE_TYPE_SOURCE_SNIPPETS_MANAGER, NULL);
+  self->snippets = ide_snippet_storage_new ();
 
   IDE_EXIT;
 }
@@ -1270,13 +1272,15 @@ ide_context_init_snippets_cb (GObject      *object,
                               GAsyncResult *result,
                               gpointer      user_data)
 {
-  IdeSourceSnippetsManager *manager = (IdeSourceSnippetsManager *)object;
+  IdeSnippetStorage *storage = (IdeSnippetStorage *)object;
   g_autoptr(IdeTask) task = user_data;
   g_autoptr(GError) error = NULL;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPETS_MANAGER (manager));
+  g_assert (IDE_IS_SNIPPET_STORAGE (storage));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_TASK (task));
 
-  if (!ide_source_snippets_manager_load_finish (manager, result, &error))
+  if (!ide_snippet_storage_load_finish (storage, result, &error))
     ide_task_return_error (task, g_steal_pointer (&error));
   else
     ide_task_return_boolean (task, TRUE);
@@ -1295,10 +1299,10 @@ ide_context_init_snippets (gpointer             source_object,
 
   task = ide_task_new (self, cancellable, callback, user_data);
 
-  ide_source_snippets_manager_load_async (self->snippets_manager,
-                                          cancellable,
-                                          ide_context_init_snippets_cb,
-                                          g_object_ref (task));
+  ide_snippet_storage_load_async (self->snippets,
+                                  cancellable,
+                                  ide_context_init_snippets_cb,
+                                  g_object_ref (task));
 }
 
 static void
diff --git a/src/libide/ide-context.h b/src/libide/ide-context.h
index 3892ae927..afeb2852c 100644
--- a/src/libide/ide-context.h
+++ b/src/libide/ide-context.h
@@ -68,8 +68,8 @@ IDE_AVAILABLE_IN_ALL
 IdeSettings              *ide_context_get_settings              (IdeContext           *self,
                                                                  const gchar          *schema_id,
                                                                  const gchar          *relative_path);
-IDE_AVAILABLE_IN_ALL
-IdeSourceSnippetsManager *ide_context_get_snippets_manager      (IdeContext           *self);
+IDE_AVAILABLE_IN_3_30
+IdeSnippetStorage        *ide_context_get_snippets              (IdeContext           *self);
 IDE_AVAILABLE_IN_3_28
 IdeTestManager           *ide_context_get_test_manager          (IdeContext           *self);
 IDE_AVAILABLE_IN_ALL
diff --git a/src/libide/ide-types.h b/src/libide/ide-types.h
index bdd77a789..fd8180bdb 100644
--- a/src/libide/ide-types.h
+++ b/src/libide/ide-types.h
@@ -106,11 +106,10 @@ typedef struct _IdeSettings                    IdeSettings;
 typedef struct _IdeSourceLocation              IdeSourceLocation;
 typedef struct _IdeSourceRange                 IdeSourceRange;
 
-typedef struct _IdeSourceSnippet               IdeSourceSnippet;
-typedef struct _IdeSourceSnippetChunk          IdeSourceSnippetChunk;
-typedef struct _IdeSourceSnippetContext        IdeSourceSnippetContext;
-typedef struct _IdeSourceSnippets              IdeSourceSnippets;
-typedef struct _IdeSourceSnippetsManager       IdeSourceSnippetsManager;
+typedef struct _IdeSnippet                     IdeSnippet;
+typedef struct _IdeSnippetChunk                IdeSnippetChunk;
+typedef struct _IdeSnippetContext              IdeSnippetContext;
+typedef struct _IdeSnippetStorage              IdeSnippetStorage;
 
 typedef struct _IdeSubprocess                  IdeSubprocess;
 typedef struct _IdeSubprocessLauncher          IdeSubprocessLauncher;
diff --git a/src/libide/ide.h b/src/libide/ide.h
index 69a6ae111..52741e32d 100644
--- a/src/libide/ide.h
+++ b/src/libide/ide.h
@@ -159,12 +159,10 @@ G_BEGIN_DECLS
 #include "search/ide-search-reducer.h"
 #include "search/ide-search-result.h"
 #include "search/ide-tagged-entry.h"
-#include "snippets/ide-source-snippet-chunk.h"
-#include "snippets/ide-source-snippet-context.h"
-#include "snippets/ide-source-snippet-parser.h"
-#include "snippets/ide-source-snippet.h"
-#include "snippets/ide-source-snippets-manager.h"
-#include "snippets/ide-source-snippets.h"
+#include "snippets/ide-snippet.h"
+#include "snippets/ide-snippet-chunk.h"
+#include "snippets/ide-snippet-context.h"
+#include "snippets/ide-snippet-storage.h"
 #include "sourceview/ide-indenter.h"
 #include "sourceview/ide-language.h"
 #include "sourceview/ide-source-map.h"
diff --git a/src/libide/snippets/ide-source-snippet-chunk.c b/src/libide/snippets/ide-snippet-chunk.c
similarity index 58%
rename from src/libide/snippets/ide-source-snippet-chunk.c
rename to src/libide/snippets/ide-snippet-chunk.c
index d3da32064..22e92b98a 100644
--- a/src/libide/snippets/ide-source-snippet-chunk.c
+++ b/src/libide/snippets/ide-snippet-chunk.c
@@ -1,4 +1,4 @@
-/* ide-source-snippet-chunk.c
+/* ide-snippet-chunk.c
  *
  * Copyright 2013 Christian Hergert <christian hergert me>
  *
@@ -22,27 +22,27 @@
 
 #include <glib/gi18n.h>
 
-#include "snippets/ide-source-snippet-chunk.h"
-#include "snippets/ide-source-snippet-context.h"
+#include "ide-snippet-chunk.h"
+#include "ide-snippet-context.h"
 
 /**
- * SECTION:ide-source-snippet-chunk
- * @title: IdeSourceSnippetChunk
+ * SECTION:ide-snippet-chunk
+ * @title: IdeSnippetChunk
  * @short_description: An chunk of text within the source snippet
  *
- * The #IdeSourceSnippetChunk represents a single chunk of text that
+ * The #IdeSnippetChunk represents a single chunk of text that
  * may or may not be an edit point within the snippet. Chunks that are
  * an edit point (also called a tab stop) have the
- * #IdeSourceSnippetChunk:tab-stop property set.
+ * #IdeSnippetChunk:tab-stop property set.
  *
- * Since: 3.18
+ * Since: 3.30
  */
 
-struct _IdeSourceSnippetChunk
+struct _IdeSnippetChunk
 {
   GObject                  parent_instance;
 
-  IdeSourceSnippetContext *context;
+  IdeSnippetContext *context;
   guint                    context_changed_handler;
   gint                     tab_stop;
   gchar                   *spec;
@@ -50,7 +50,7 @@ struct _IdeSourceSnippetChunk
   guint                    text_set : 1;
 };
 
-G_DEFINE_TYPE (IdeSourceSnippetChunk, ide_source_snippet_chunk, G_TYPE_OBJECT)
+G_DEFINE_TYPE (IdeSnippetChunk, ide_snippet_chunk, G_TYPE_OBJECT)
 
 enum {
   PROP_0,
@@ -64,27 +64,27 @@ enum {
 
 static GParamSpec *properties[LAST_PROP];
 
-IdeSourceSnippetChunk *
-ide_source_snippet_chunk_new (void)
+IdeSnippetChunk *
+ide_snippet_chunk_new (void)
 {
-  return g_object_new (IDE_TYPE_SOURCE_SNIPPET_CHUNK, NULL);
+  return g_object_new (IDE_TYPE_SNIPPET_CHUNK, NULL);
 }
 
 /**
- * ide_source_snippet_chunk_copy:
+ * ide_snippet_chunk_copy:
  *
  * Copies the source snippet.
  *
- * Returns: (transfer full): An #IdeSourceSnippetChunk.
+ * Returns: (transfer full): An #IdeSnippetChunk.
  */
-IdeSourceSnippetChunk *
-ide_source_snippet_chunk_copy (IdeSourceSnippetChunk *chunk)
+IdeSnippetChunk *
+ide_snippet_chunk_copy (IdeSnippetChunk *chunk)
 {
-  IdeSourceSnippetChunk *ret;
+  IdeSnippetChunk *ret;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CHUNK (chunk), NULL);
 
-  ret = g_object_new (IDE_TYPE_SOURCE_SNIPPET_CHUNK,
+  ret = g_object_new (IDE_TYPE_SNIPPET_CHUNK,
                       "spec", chunk->spec,
                       "tab-stop", chunk->tab_stop,
                       NULL);
@@ -93,43 +93,43 @@ ide_source_snippet_chunk_copy (IdeSourceSnippetChunk *chunk)
 }
 
 static void
-on_context_changed (IdeSourceSnippetContext *context,
-                    IdeSourceSnippetChunk   *chunk)
+on_context_changed (IdeSnippetContext *context,
+                    IdeSnippetChunk   *chunk)
 {
   gchar *text;
 
-  g_assert (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
-  g_assert (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_assert (IDE_IS_SNIPPET_CHUNK (chunk));
+  g_assert (IDE_IS_SNIPPET_CONTEXT (context));
 
   if (!chunk->text_set)
     {
-      text = ide_source_snippet_context_expand (context, chunk->spec);
-      ide_source_snippet_chunk_set_text (chunk, text);
+      text = ide_snippet_context_expand (context, chunk->spec);
+      ide_snippet_chunk_set_text (chunk, text);
       g_free (text);
     }
 }
 
 /**
- * ide_source_snippet_chunk_get_context:
+ * ide_snippet_chunk_get_context:
  *
  * Gets the context for the snippet insertion.
  *
- * Returns: (transfer none): An #IdeSourceSnippetContext.
+ * Returns: (transfer none): An #IdeSnippetContext.
  */
-IdeSourceSnippetContext *
-ide_source_snippet_chunk_get_context (IdeSourceSnippetChunk *chunk)
+IdeSnippetContext *
+ide_snippet_chunk_get_context (IdeSnippetChunk *chunk)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CHUNK (chunk), NULL);
 
   return chunk->context;
 }
 
 void
-ide_source_snippet_chunk_set_context (IdeSourceSnippetChunk   *chunk,
-                                      IdeSourceSnippetContext *context)
+ide_snippet_chunk_set_context (IdeSnippetChunk   *chunk,
+                                      IdeSnippetContext *context)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
-  g_return_if_fail (!context || IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (!context || IDE_IS_SNIPPET_CONTEXT (context));
 
   if (context != chunk->context)
     {
@@ -158,17 +158,17 @@ ide_source_snippet_chunk_set_context (IdeSourceSnippetChunk   *chunk,
 }
 
 const gchar *
-ide_source_snippet_chunk_get_spec (IdeSourceSnippetChunk *chunk)
+ide_snippet_chunk_get_spec (IdeSnippetChunk *chunk)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CHUNK (chunk), NULL);
   return chunk->spec;
 }
 
 void
-ide_source_snippet_chunk_set_spec (IdeSourceSnippetChunk *chunk,
+ide_snippet_chunk_set_spec (IdeSnippetChunk *chunk,
                                    const gchar           *spec)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
 
   g_free (chunk->spec);
   chunk->spec = g_strdup (spec);
@@ -176,33 +176,33 @@ ide_source_snippet_chunk_set_spec (IdeSourceSnippetChunk *chunk,
 }
 
 gint
-ide_source_snippet_chunk_get_tab_stop (IdeSourceSnippetChunk *chunk)
+ide_snippet_chunk_get_tab_stop (IdeSnippetChunk *chunk)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk), 0);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CHUNK (chunk), 0);
   return chunk->tab_stop;
 }
 
 void
-ide_source_snippet_chunk_set_tab_stop (IdeSourceSnippetChunk *chunk,
+ide_snippet_chunk_set_tab_stop (IdeSnippetChunk *chunk,
                                        gint                   tab_stop)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
   chunk->tab_stop = tab_stop;
   g_object_notify_by_pspec (G_OBJECT (chunk), properties[PROP_TAB_STOP]);
 }
 
 const gchar *
-ide_source_snippet_chunk_get_text (IdeSourceSnippetChunk *chunk)
+ide_snippet_chunk_get_text (IdeSnippetChunk *chunk)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CHUNK (chunk), NULL);
   return chunk->text ? chunk->text : "";
 }
 
 void
-ide_source_snippet_chunk_set_text (IdeSourceSnippetChunk *chunk,
+ide_snippet_chunk_set_text (IdeSnippetChunk *chunk,
                                    const gchar           *text)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
 
   if (chunk->text != text)
     {
@@ -213,18 +213,18 @@ ide_source_snippet_chunk_set_text (IdeSourceSnippetChunk *chunk,
 }
 
 gboolean
-ide_source_snippet_chunk_get_text_set (IdeSourceSnippetChunk *chunk)
+ide_snippet_chunk_get_text_set (IdeSnippetChunk *chunk)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CHUNK (chunk), FALSE);
 
   return chunk->text_set;
 }
 
 void
-ide_source_snippet_chunk_set_text_set (IdeSourceSnippetChunk *chunk,
+ide_snippet_chunk_set_text_set (IdeSnippetChunk *chunk,
                                        gboolean               text_set)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
 
   text_set = !!text_set;
 
@@ -236,45 +236,45 @@ ide_source_snippet_chunk_set_text_set (IdeSourceSnippetChunk *chunk,
 }
 
 static void
-ide_source_snippet_chunk_finalize (GObject *object)
+ide_snippet_chunk_finalize (GObject *object)
 {
-  IdeSourceSnippetChunk *chunk = (IdeSourceSnippetChunk *)object;
+  IdeSnippetChunk *chunk = (IdeSnippetChunk *)object;
 
   g_clear_pointer (&chunk->spec, g_free);
   g_clear_pointer (&chunk->text, g_free);
   g_clear_object (&chunk->context);
 
-  G_OBJECT_CLASS (ide_source_snippet_chunk_parent_class)->finalize (object);
+  G_OBJECT_CLASS (ide_snippet_chunk_parent_class)->finalize (object);
 }
 
 static void
-ide_source_snippet_chunk_get_property (GObject    *object,
+ide_snippet_chunk_get_property (GObject    *object,
                                        guint       prop_id,
                                        GValue     *value,
                                        GParamSpec *pspec)
 {
-  IdeSourceSnippetChunk *chunk = IDE_SOURCE_SNIPPET_CHUNK (object);
+  IdeSnippetChunk *chunk = IDE_SNIPPET_CHUNK (object);
 
   switch (prop_id)
     {
     case PROP_CONTEXT:
-      g_value_set_object (value, ide_source_snippet_chunk_get_context (chunk));
+      g_value_set_object (value, ide_snippet_chunk_get_context (chunk));
       break;
 
     case PROP_SPEC:
-      g_value_set_string (value, ide_source_snippet_chunk_get_spec (chunk));
+      g_value_set_string (value, ide_snippet_chunk_get_spec (chunk));
       break;
 
     case PROP_TAB_STOP:
-      g_value_set_int (value, ide_source_snippet_chunk_get_tab_stop (chunk));
+      g_value_set_int (value, ide_snippet_chunk_get_tab_stop (chunk));
       break;
 
     case PROP_TEXT:
-      g_value_set_string (value, ide_source_snippet_chunk_get_text (chunk));
+      g_value_set_string (value, ide_snippet_chunk_get_text (chunk));
       break;
 
     case PROP_TEXT_SET:
-      g_value_set_boolean (value, ide_source_snippet_chunk_get_text_set (chunk));
+      g_value_set_boolean (value, ide_snippet_chunk_get_text_set (chunk));
       break;
 
     default:
@@ -283,33 +283,33 @@ ide_source_snippet_chunk_get_property (GObject    *object,
 }
 
 static void
-ide_source_snippet_chunk_set_property (GObject      *object,
+ide_snippet_chunk_set_property (GObject      *object,
                                        guint         prop_id,
                                        const GValue *value,
                                        GParamSpec   *pspec)
 {
-  IdeSourceSnippetChunk *chunk = IDE_SOURCE_SNIPPET_CHUNK (object);
+  IdeSnippetChunk *chunk = IDE_SNIPPET_CHUNK (object);
 
   switch (prop_id)
     {
     case PROP_CONTEXT:
-      ide_source_snippet_chunk_set_context (chunk, g_value_get_object (value));
+      ide_snippet_chunk_set_context (chunk, g_value_get_object (value));
       break;
 
     case PROP_TAB_STOP:
-      ide_source_snippet_chunk_set_tab_stop (chunk, g_value_get_int (value));
+      ide_snippet_chunk_set_tab_stop (chunk, g_value_get_int (value));
       break;
 
     case PROP_SPEC:
-      ide_source_snippet_chunk_set_spec (chunk, g_value_get_string (value));
+      ide_snippet_chunk_set_spec (chunk, g_value_get_string (value));
       break;
 
     case PROP_TEXT:
-      ide_source_snippet_chunk_set_text (chunk, g_value_get_string (value));
+      ide_snippet_chunk_set_text (chunk, g_value_get_string (value));
       break;
 
     case PROP_TEXT_SET:
-      ide_source_snippet_chunk_set_text_set (chunk, g_value_get_boolean (value));
+      ide_snippet_chunk_set_text_set (chunk, g_value_get_boolean (value));
       break;
 
     default:
@@ -318,19 +318,19 @@ ide_source_snippet_chunk_set_property (GObject      *object,
 }
 
 static void
-ide_source_snippet_chunk_class_init (IdeSourceSnippetChunkClass *klass)
+ide_snippet_chunk_class_init (IdeSnippetChunkClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->finalize = ide_source_snippet_chunk_finalize;
-  object_class->get_property = ide_source_snippet_chunk_get_property;
-  object_class->set_property = ide_source_snippet_chunk_set_property;
+  object_class->finalize = ide_snippet_chunk_finalize;
+  object_class->get_property = ide_snippet_chunk_get_property;
+  object_class->set_property = ide_snippet_chunk_set_property;
 
   properties[PROP_CONTEXT] =
     g_param_spec_object ("context",
                          "Context",
                          "The snippet context.",
-                         IDE_TYPE_SOURCE_SNIPPET_CONTEXT,
+                         IDE_TYPE_SNIPPET_CONTEXT,
                          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   properties[PROP_SPEC] =
@@ -367,7 +367,7 @@ ide_source_snippet_chunk_class_init (IdeSourceSnippetChunkClass *klass)
 }
 
 static void
-ide_source_snippet_chunk_init (IdeSourceSnippetChunk *chunk)
+ide_snippet_chunk_init (IdeSnippetChunk *chunk)
 {
   chunk->tab_stop = -1;
   chunk->spec = g_strdup ("");
diff --git a/src/libide/snippets/ide-snippet-chunk.h b/src/libide/snippets/ide-snippet-chunk.h
new file mode 100644
index 000000000..7f69fd539
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-chunk.h
@@ -0,0 +1,64 @@
+/* ide-snippet-chunk.h
+ *
+ * Copyright 2013 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/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+#include "ide-version-macros.h"
+
+#include "snippets/ide-snippet-context.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SNIPPET_CHUNK (ide_snippet_chunk_get_type())
+
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeSnippetChunk, ide_snippet_chunk, IDE, SNIPPET_CHUNK, GObject)
+
+IDE_AVAILABLE_IN_3_30
+IdeSnippetChunk   *ide_snippet_chunk_new          (void);
+IDE_AVAILABLE_IN_3_30
+IdeSnippetChunk   *ide_snippet_chunk_copy         (IdeSnippetChunk   *chunk);
+IDE_AVAILABLE_IN_3_30
+IdeSnippetContext *ide_snippet_chunk_get_context  (IdeSnippetChunk   *chunk);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_chunk_set_context  (IdeSnippetChunk   *chunk,
+                                                   IdeSnippetContext *context);
+IDE_AVAILABLE_IN_3_30
+const gchar       *ide_snippet_chunk_get_spec     (IdeSnippetChunk   *chunk);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_chunk_set_spec     (IdeSnippetChunk   *chunk,
+                                                   const gchar       *spec);
+IDE_AVAILABLE_IN_3_30
+gint               ide_snippet_chunk_get_tab_stop (IdeSnippetChunk   *chunk);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_chunk_set_tab_stop (IdeSnippetChunk   *chunk,
+                                                   gint              tab_stop);
+IDE_AVAILABLE_IN_3_30
+const gchar       *ide_snippet_chunk_get_text     (IdeSnippetChunk   *chunk);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_chunk_set_text     (IdeSnippetChunk   *chunk,
+                                                   const gchar       *text);
+IDE_AVAILABLE_IN_3_30
+gboolean           ide_snippet_chunk_get_text_set (IdeSnippetChunk   *chunk);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_chunk_set_text_set (IdeSnippetChunk   *chunk,
+                                                   gboolean          text_set);
+
+G_END_DECLS
diff --git a/src/libide/snippets/ide-snippet-completion-provider.c 
b/src/libide/snippets/ide-snippet-completion-provider.c
new file mode 100644
index 000000000..eb30d3892
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-completion-provider.c
@@ -0,0 +1,58 @@
+/* ide-snippet-completion-provider.c
+ *
+ * Copyright © 2018 Christian Hergert <chergert redhat com>
+ *
+ * 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-snippet-completion-provider.h"
+
+#include "ide-snippet-completion-provider.h"
+
+struct _IdeSnippetCompletionProvider
+{
+  IdeObject parent_instance;
+};
+
+G_DEFINE_TYPE (IdeSnippetCompletionProvider, ide_snippet_completion_provider, IDE_TYPE_OBJECT)
+
+static void
+ide_snippet_completion_provider_finalize (GObject *object)
+{
+  IdeSnippetCompletionProvider *self = (IdeSnippetCompletionProvider *)object;
+
+  G_OBJECT_CLASS (ide_snippet_completion_provider_parent_class)->finalize (object);
+}
+
+static void
+ide_snippet_completion_provider_class_init (IdeSnippetCompletionProviderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_snippet_completion_provider_finalize;
+}
+
+static void
+ide_snippet_completion_provider_init (IdeSnippetCompletionProvider *self)
+{
+}
+
+void
+ide_snippet_completion_provider_set_language (IdeSnippetCompletionProvider *self,
+                                              const gchar                  *lang_id)
+{
+  g_return_if_fail (IDE_IS_SNIPPET_COMPLETION_PROVIDER (self));
+
+  ide_snippet_model_set_language (self->model, lang_id);
+}
diff --git a/src/libide/snippets/ide-source-snippet-completion-provider.h 
b/src/libide/snippets/ide-snippet-completion-provider.h
similarity index 51%
rename from src/libide/snippets/ide-source-snippet-completion-provider.h
rename to src/libide/snippets/ide-snippet-completion-provider.h
index b87ae9a0d..08ba84bf2 100644
--- a/src/libide/snippets/ide-source-snippet-completion-provider.h
+++ b/src/libide/snippets/ide-snippet-completion-provider.h
@@ -1,6 +1,6 @@
-/* ide-source-snippet-completion-provider.h
+/* ide-snippet-completion-provider.h
  *
- * Copyright 2013 Christian Hergert <christian hergert me>
+ * Copyright 2018 Christian Hergert <chergert redhat com>
  *
  * 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
@@ -18,19 +18,20 @@
 
 #pragma once
 
-#include <gtksourceview/gtksource.h>
-
-#include "snippets/ide-source-snippets.h"
-#include "sourceview/ide-source-view.h"
+#include "completion/ide-completion-provider.h"
+#include "snippets/ide-snippet.h"
 
 G_BEGIN_DECLS
 
-#define IDE_SOURCE_SNIPPET_COMPLETION_PROVIDER_PRIORITY 1000
-#define IDE_TYPE_SOURCE_SNIPPET_COMPLETION_PROVIDER     (ide_source_snippet_completion_provider_get_type())
+#define IDE_TYPE_SNIPPET_COMPLETION_PROVIDER (ide_snippet_completion_provider_get_type())
 
-G_DECLARE_FINAL_TYPE (IdeSourceSnippetCompletionProvider, ide_source_snippet_completion_provider, IDE, 
SOURCE_SNIPPET_COMPLETION_PROVIDER, GObject)
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeSnippetCompletionProvider, ide_snippet_completion_provider, IDE, 
SNIPPET_COMPLETION_PROVIDER, IdeObject)
 
-GtkSourceCompletionProvider *ide_source_snippet_completion_provider_new (IdeSourceView     *source_view,
-                                                                         IdeSourceSnippets *snippets);
+IDE_AVAILABLE_IN_3_30
+IdeSnippetCompletionProvider *ide_snippet_completion_provider_new          (void);
+IDE_AVAILABLE_IN_3_30
+void                          ide_snippet_completion_provider_set_language (IdeSnippetCompletionProvider 
*self,
+                                                                            const gchar                  
*lang_id);
 
 G_END_DECLS
diff --git a/src/libide/snippets/ide-source-snippet-context.c b/src/libide/snippets/ide-snippet-context.c
similarity index 84%
rename from src/libide/snippets/ide-source-snippet-context.c
rename to src/libide/snippets/ide-snippet-context.c
index 663f177ef..1f332e429 100644
--- a/src/libide/snippets/ide-source-snippet-context.c
+++ b/src/libide/snippets/ide-snippet-context.c
@@ -1,4 +1,4 @@
-/* ide-source-snippet-context.c
+/* ide-snippet-context.c
  *
  * Copyright 2013 Christian Hergert <christian hergert me>
  *
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define G_LOG_DOMAIN "ide-source-snippets-context"
+#define G_LOG_DOMAIN "ide-snippets-context"
 
 #include "config.h"
 
@@ -24,25 +24,25 @@
 #include <glib/gi18n.h>
 #include <stdlib.h>
 
-#include "snippets/ide-source-snippet-context.h"
+#include "ide-snippet-context.h"
 
 /**
- * SECTION:ide-source-snippet-context
- * @title: IdeSourceSnippetContext
- * @short_description: Context for expanding #IdeSourceSnippetChunk
+ * SECTION:ide-snippet-context
+ * @title: IdeSnippetContext
+ * @short_description: Context for expanding #IdeSnippetChunk
  *
  * This class is currently used primary as a hashtable. However, the longer
  * term goal is to have it hold onto a GjsContext as well as other languages
- * so that #IdeSourceSnippetChunk can expand themselves by executing
+ * so that #IdeSnippetChunk can expand themselves by executing
  * script within the context.
  *
- * The #IdeSourceSnippet will build the context and then expand each of the
+ * The #IdeSnippet will build the context and then expand each of the
  * chunks during the insertion/edit phase.
  *
- * Since: 3.18
+ * Since: 3.30
  */
 
-struct _IdeSourceSnippetContext
+struct _IdeSnippetContext
 {
   GObject     parent_instance;
 
@@ -53,12 +53,12 @@ struct _IdeSourceSnippetContext
   guint       use_spaces : 1;
 };
 
-struct _IdeSourceSnippetContextClass
+struct _IdeSnippetContextClass
 {
   GObjectClass parent;
 };
 
-G_DEFINE_TYPE (IdeSourceSnippetContext, ide_source_snippet_context, G_TYPE_OBJECT)
+G_DEFINE_TYPE (IdeSnippetContext, ide_snippet_context, G_TYPE_OBJECT)
 
 enum {
   CHANGED,
@@ -70,20 +70,20 @@ typedef gchar *(*InputFilter) (const gchar *input);
 static GHashTable *filters;
 static guint signals[LAST_SIGNAL];
 
-IdeSourceSnippetContext *
-ide_source_snippet_context_new (void)
+IdeSnippetContext *
+ide_snippet_context_new (void)
 {
-  return g_object_new (IDE_TYPE_SOURCE_SNIPPET_CONTEXT, NULL);
+  return g_object_new (IDE_TYPE_SNIPPET_CONTEXT, NULL);
 }
 
 void
-ide_source_snippet_context_dump (IdeSourceSnippetContext *context)
+ide_snippet_context_dump (IdeSnippetContext *context)
 {
   GHashTableIter iter;
   gpointer key;
   gpointer value;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
 
   g_hash_table_iter_init (&iter, context->variables);
   while (g_hash_table_iter_next (&iter, &key, &value))
@@ -91,42 +91,42 @@ ide_source_snippet_context_dump (IdeSourceSnippetContext *context)
 }
 
 void
-ide_source_snippet_context_clear_variables (IdeSourceSnippetContext *context)
+ide_snippet_context_clear_variables (IdeSnippetContext *context)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
 
   g_hash_table_remove_all (context->variables);
 }
 
 void
-ide_source_snippet_context_add_variable (IdeSourceSnippetContext *context,
+ide_snippet_context_add_variable (IdeSnippetContext *context,
                                         const gchar            *key,
                                         const gchar            *value)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
   g_return_if_fail (key);
 
   g_hash_table_replace (context->variables, g_strdup (key), g_strdup (value));
 }
 
 void
-ide_source_snippet_context_add_shared_variable (IdeSourceSnippetContext *context,
+ide_snippet_context_add_shared_variable (IdeSnippetContext *context,
                                                 const gchar             *key,
                                                 const gchar             *value)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
   g_return_if_fail (key);
 
   g_hash_table_replace (context->shared, g_strdup (key), g_strdup (value));
 }
 
 const gchar *
-ide_source_snippet_context_get_variable (IdeSourceSnippetContext *context,
+ide_snippet_context_get_variable (IdeSnippetContext *context,
                                         const gchar            *key)
 {
   const gchar *ret;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CONTEXT (context), NULL);
 
   if (!(ret = g_hash_table_lookup (context->variables, key)))
     ret = g_hash_table_lookup (context->shared, key);
@@ -521,7 +521,7 @@ scan_forward (const gchar  *input,
 }
 
 gchar *
-ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
+ide_snippet_context_expand (IdeSnippetContext *context,
                                    const gchar             *input)
 {
   const gchar *expand;
@@ -532,7 +532,7 @@ ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
   glong n;
   gint i;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_CONTEXT (context), NULL);
   g_return_val_if_fail (input, NULL);
 
   is_dynamic = (*input == '$');
@@ -564,7 +564,7 @@ ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
               input--;
               g_snprintf (key, sizeof key, "%ld", n);
               key[sizeof key - 1] = '\0';
-              expand = ide_source_snippet_context_get_variable (context, key);
+              expand = ide_snippet_context_get_variable (context, key);
               if (expand)
                 g_string_append (str, expand);
               continue;
@@ -576,7 +576,7 @@ ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
                   g_autofree gchar *lkey = NULL;
 
                   lkey = g_strndup (input, strchr (input, '|') - input);
-                  expand = ide_source_snippet_context_get_variable (context, lkey);
+                  expand = ide_snippet_context_get_variable (context, lkey);
                   if (expand)
                     {
                       g_string_append (str, expand);
@@ -587,7 +587,7 @@ ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
                 }
               else
                 {
-                  expand = ide_source_snippet_context_get_variable (context, input);
+                  expand = ide_snippet_context_get_variable (context, input);
                   if (expand)
                     g_string_append (str, expand);
                   else
@@ -615,7 +615,7 @@ ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
 
               input = endpos;
 
-              expanded = ide_source_snippet_context_expand (context, slice);
+              expanded = ide_snippet_context_expand (context, slice);
 
               g_string_append (str, expanded);
 
@@ -649,58 +649,58 @@ ide_source_snippet_context_expand (IdeSourceSnippetContext *context,
 }
 
 void
-ide_source_snippet_context_set_tab_width (IdeSourceSnippetContext *context,
+ide_snippet_context_set_tab_width (IdeSnippetContext *context,
                                          gint                    tab_width)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
   context->tab_width = tab_width;
 }
 
 void
-ide_source_snippet_context_set_use_spaces (IdeSourceSnippetContext *context,
+ide_snippet_context_set_use_spaces (IdeSnippetContext *context,
                                           gboolean                use_spaces)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
   context->use_spaces = !!use_spaces;
 }
 
 void
-ide_source_snippet_context_set_line_prefix (IdeSourceSnippetContext *context,
+ide_snippet_context_set_line_prefix (IdeSnippetContext *context,
                                            const gchar            *line_prefix)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
   g_free (context->line_prefix);
   context->line_prefix = g_strdup (line_prefix);
 }
 
 void
-ide_source_snippet_context_emit_changed (IdeSourceSnippetContext *context)
+ide_snippet_context_emit_changed (IdeSnippetContext *context)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CONTEXT (context));
+  g_return_if_fail (IDE_IS_SNIPPET_CONTEXT (context));
   g_signal_emit (context, signals[CHANGED], 0);
 }
 
 static void
-ide_source_snippet_context_finalize (GObject *object)
+ide_snippet_context_finalize (GObject *object)
 {
-  IdeSourceSnippetContext *context = (IdeSourceSnippetContext *)object;
+  IdeSnippetContext *context = (IdeSnippetContext *)object;
 
   g_clear_pointer (&context->shared, (GDestroyNotify)g_hash_table_unref);
   g_clear_pointer (&context->variables, (GDestroyNotify)g_hash_table_unref);
   g_clear_pointer (&context->line_prefix, g_free);
 
-  G_OBJECT_CLASS (ide_source_snippet_context_parent_class)->finalize (object);
+  G_OBJECT_CLASS (ide_snippet_context_parent_class)->finalize (object);
 }
 
 static void
-ide_source_snippet_context_class_init (IdeSourceSnippetContextClass *klass)
+ide_snippet_context_class_init (IdeSnippetContextClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->finalize = ide_source_snippet_context_finalize;
+  object_class->finalize = ide_snippet_context_finalize;
 
   signals[CHANGED] = g_signal_new ("changed",
-                                    IDE_TYPE_SOURCE_SNIPPET_CONTEXT,
+                                    IDE_TYPE_SNIPPET_CONTEXT,
                                     G_SIGNAL_RUN_FIRST,
                                     0,
                                     NULL, NULL, NULL,
@@ -725,7 +725,7 @@ ide_source_snippet_context_class_init (IdeSourceSnippetContextClass *klass)
 }
 
 static void
-ide_source_snippet_context_init (IdeSourceSnippetContext *context)
+ide_snippet_context_init (IdeSnippetContext *context)
 {
   GDateTime *dt;
   gchar *str;
diff --git a/src/libide/snippets/ide-source-snippet-context.h b/src/libide/snippets/ide-snippet-context.h
similarity index 59%
rename from src/libide/snippets/ide-source-snippet-context.h
rename to src/libide/snippets/ide-snippet-context.h
index a50a5b358..c34cb0aae 100644
--- a/src/libide/snippets/ide-source-snippet-context.h
+++ b/src/libide/snippets/ide-snippet-context.h
@@ -1,4 +1,4 @@
-/* ide-source-snippet-context.h
+/* ide-snippet-context.h
  *
  * Copyright 2013 Christian Hergert <christian hergert me>
  *
@@ -24,42 +24,42 @@
 
 G_BEGIN_DECLS
 
-#define IDE_TYPE_SOURCE_SNIPPET_CONTEXT (ide_source_snippet_context_get_type())
+#define IDE_TYPE_SNIPPET_CONTEXT (ide_snippet_context_get_type())
 
 IDE_AVAILABLE_IN_ALL
-G_DECLARE_FINAL_TYPE (IdeSourceSnippetContext, ide_source_snippet_context,
-                      IDE, SOURCE_SNIPPET_CONTEXT, GObject)
+G_DECLARE_FINAL_TYPE (IdeSnippetContext, ide_snippet_context,
+                      IDE, SNIPPET_CONTEXT, GObject)
 
 IDE_AVAILABLE_IN_ALL
-IdeSourceSnippetContext *ide_source_snippet_context_new                 (void);
+IdeSnippetContext *ide_snippet_context_new                 (void);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_emit_changed        (IdeSourceSnippetContext *context);
+void                     ide_snippet_context_emit_changed        (IdeSnippetContext *context);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_clear_variables     (IdeSourceSnippetContext *context);
+void                     ide_snippet_context_clear_variables     (IdeSnippetContext *context);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_add_variable        (IdeSourceSnippetContext *context,
+void                     ide_snippet_context_add_variable        (IdeSnippetContext *context,
                                                                          const gchar             *key,
                                                                          const gchar             *value);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_add_shared_variable (IdeSourceSnippetContext *context,
+void                     ide_snippet_context_add_shared_variable (IdeSnippetContext *context,
                                                                          const gchar             *key,
                                                                          const gchar             *value);
 IDE_AVAILABLE_IN_ALL
-const gchar             *ide_source_snippet_context_get_variable        (IdeSourceSnippetContext *context,
+const gchar             *ide_snippet_context_get_variable        (IdeSnippetContext *context,
                                                                          const gchar             *key);
 IDE_AVAILABLE_IN_ALL
-gchar                   *ide_source_snippet_context_expand              (IdeSourceSnippetContext *context,
+gchar                   *ide_snippet_context_expand              (IdeSnippetContext *context,
                                                                          const gchar             *input);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_set_tab_width       (IdeSourceSnippetContext *context,
+void                     ide_snippet_context_set_tab_width       (IdeSnippetContext *context,
                                                                          gint                     tab_size);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_set_use_spaces      (IdeSourceSnippetContext *context,
+void                     ide_snippet_context_set_use_spaces      (IdeSnippetContext *context,
                                                                          gboolean                 
use_spaces);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_set_line_prefix     (IdeSourceSnippetContext *context,
+void                     ide_snippet_context_set_line_prefix     (IdeSnippetContext *context,
                                                                          const gchar             
*line_prefix);
 IDE_AVAILABLE_IN_ALL
-void                     ide_source_snippet_context_dump                (IdeSourceSnippetContext *context);
+void                     ide_snippet_context_dump                (IdeSnippetContext *context);
 
 G_END_DECLS
diff --git a/src/libide/snippets/ide-snippet-model.c b/src/libide/snippets/ide-snippet-model.c
new file mode 100644
index 000000000..f3aee2b0c
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-model.c
@@ -0,0 +1,177 @@
+/* ide-snippet-model.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "ide-snippet-model"
+
+#include "ide-snippet.h"
+#include "ide-snippet-model.h"
+#include "ide-snippet-parser.h"
+
+struct _IdeSnippetModel
+{
+  GObject            parent_instance;
+  IdeSnippetStorage *storage;
+  GPtrArray         *items;
+  gchar             *prefix;
+  gchar             *language;
+};
+
+static void list_model_iface_init (GListModelInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (IdeSnippetModel, ide_snippet_model, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, list_model_iface_init))
+
+static void
+ide_snippet_model_finalize (GObject *object)
+{
+  IdeSnippetModel *self = (IdeSnippetModel *)object;
+
+  g_clear_pointer (&self->language, g_free);
+  g_clear_pointer (&self->prefix, g_free);
+  g_clear_pointer (&self->items, g_ptr_array_unref);
+  g_clear_object (&self->storage);
+
+  G_OBJECT_CLASS (ide_snippet_model_parent_class)->finalize (object);
+}
+
+static void
+ide_snippet_model_class_init (IdeSnippetModelClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_snippet_model_finalize;
+}
+
+static void
+ide_snippet_model_init (IdeSnippetModel *self)
+{
+  self->items = g_ptr_array_new ();
+}
+
+IdeSnippetModel *
+ide_snippet_model_new (IdeSnippetStorage *storage)
+{
+  IdeSnippetModel *self;
+
+  self = g_object_new (IDE_TYPE_SNIPPET_MODEL, NULL);
+  self->storage = g_object_ref (storage);
+
+  return self;
+}
+
+static void
+foreach_cb (IdeSnippetStorage    *storage,
+            const IdeSnippetInfo *info,
+            gpointer              user_data)
+{
+  IdeSnippetModel *self = user_data;
+  /* You can only add items to storage, and the pointer is
+   * guaranteed alive while we own self->storage.
+   */
+  g_ptr_array_add (self->items, (gpointer)info);
+}
+
+static void
+ide_snippet_model_update (IdeSnippetModel *self)
+{
+  guint old_len;
+
+  g_assert (IDE_IS_SNIPPET_MODEL (self));
+
+  old_len = self->items->len;
+
+  if (self->items->len)
+    g_ptr_array_remove_range (self->items, 0, self->items->len);
+
+  ide_snippet_storage_query (self->storage, self->language, self->prefix, foreach_cb, self);
+
+  if (old_len || self->items->len)
+    g_list_model_items_changed (G_LIST_MODEL (self), 0, old_len, self->items->len);
+}
+
+void
+ide_snippet_model_set_prefix (IdeSnippetModel *self,
+                              const gchar     *prefix)
+{
+  g_return_if_fail (IDE_IS_SNIPPET_MODEL (self));
+
+  if (g_strcmp0 (prefix, self->prefix) != 0)
+    {
+      g_free (self->prefix);
+      self->prefix = g_strdup (prefix);
+      ide_snippet_model_update (self);
+    }
+}
+
+void
+ide_snippet_model_set_language (IdeSnippetModel *self,
+                                const gchar     *language)
+{
+  g_return_if_fail (IDE_IS_SNIPPET_MODEL (self));
+
+  if (g_strcmp0 (language, self->language) != 0)
+    {
+      g_free (self->language);
+      self->language = g_strdup (language);
+      ide_snippet_model_update (self);
+    }
+}
+
+static GType
+ide_snippet_model_get_item_type (GListModel *model)
+{
+  return IDE_TYPE_SNIPPET;
+}
+
+static guint
+ide_snippet_model_get_n_items (GListModel *model)
+{
+  return IDE_SNIPPET_MODEL (model)->items->len;
+}
+
+static gpointer
+ide_snippet_model_get_item (GListModel *model,
+                            guint       position)
+{
+  IdeSnippetModel *self = IDE_SNIPPET_MODEL (model);
+  const IdeSnippetInfo *info = g_ptr_array_index (self->items, position);
+  g_autoptr(IdeSnippetParser) parser = ide_snippet_parser_new ();
+  g_autoptr(GError) error = NULL;
+  GList *items;
+
+  if (!ide_snippet_parser_load_from_data (parser, info->begin, info->len, &error))
+    {
+      g_message ("Failed to parse snippet: %s\n", error->message);
+      return ide_snippet_new (NULL, NULL);
+    }
+
+  if (!(items = ide_snippet_parser_get_snippets (parser)))
+    return ide_snippet_new (NULL, NULL);
+
+  return g_object_ref (items->data);
+}
+
+static void
+list_model_iface_init (GListModelInterface *iface)
+{
+  iface->get_item_type = ide_snippet_model_get_item_type;
+  iface->get_n_items = ide_snippet_model_get_n_items;
+  iface->get_item = ide_snippet_model_get_item;
+}
diff --git a/src/libide/snippets/ide-snippet-model.h b/src/libide/snippets/ide-snippet-model.h
new file mode 100644
index 000000000..d959eb65a
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-model.h
@@ -0,0 +1,42 @@
+/* ide-snippet-model.h
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#include "ide-version-macros.h"
+#include "ide-snippet-storage.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SNIPPET_MODEL (ide_snippet_model_get_type())
+
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeSnippetModel, ide_snippet_model, IDE, SNIPPET_MODEL, GObject)
+
+IDE_AVAILABLE_IN_3_30
+IdeSnippetModel *ide_snippet_model_new          (IdeSnippetStorage *storage);
+IDE_AVAILABLE_IN_3_30
+void             ide_snippet_model_set_language (IdeSnippetModel   *self,
+                                                 const gchar       *language_id);
+IDE_AVAILABLE_IN_3_30
+void             ide_snippet_model_set_prefix   (IdeSnippetModel   *self,
+                                                 const gchar       *prefix);
+
+G_END_DECLS
diff --git a/src/libide/snippets/ide-source-snippet-parser.c b/src/libide/snippets/ide-snippet-parser.c
similarity index 69%
rename from src/libide/snippets/ide-source-snippet-parser.c
rename to src/libide/snippets/ide-snippet-parser.c
index d75a52f42..a425d7d47 100644
--- a/src/libide/snippets/ide-source-snippet-parser.c
+++ b/src/libide/snippets/ide-snippet-parser.c
@@ -1,4 +1,4 @@
-/* ide-source-snippet-parser.c
+/* ide-snippet-parser.c
  *
  * Copyright 2013 Christian Hergert <christian hergert me>
  *
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define G_LOG_DOMAIN "ide-source-snippet-parser"
+#define G_LOG_DOMAIN "ide-snippet-parser"
 
 #include "config.h"
 
@@ -24,24 +24,25 @@
 #include <glib/gi18n.h>
 #include <stdlib.h>
 
-#include "snippets/ide-source-snippet.h"
-#include "snippets/ide-source-snippet-chunk.h"
-#include "snippets/ide-source-snippet-parser.h"
-#include "snippets/ide-source-snippet-private.h"
+#include "snippets/ide-snippet.h"
+#include "snippets/ide-snippet-chunk.h"
+#include "snippets/ide-snippet-parser.h"
+#include "snippets/ide-snippet-private.h"
+#include "util/ide-line-reader.h"
 
 /**
- * SECTION:ide-source-snippet-parser
- * @title: IdeSourceSnippetParser
+ * SECTION:ide-snippet-parser
+ * @title: IdeSnippetParser
  * @short_description: A parser for Builder's snippet text format
  *
- * The #IdeSourceSnippetParser can be used to parse ".snippets" formatted
+ * The #IdeSnippetParser can be used to parse ".snippets" formatted
  * text files. This is generally only used internally by Builder, but can
  * be used by plugins under certain situations.
  *
- * Since: 3.18
+ * Since: 3.30
  */
 
-struct _IdeSourceSnippetParser
+struct _IdeSnippetParser
 {
   GObject  parent_instance;
 
@@ -60,7 +61,7 @@ struct _IdeSourceSnippetParser
   guint    had_error : 1;
 };
 
-G_DEFINE_TYPE (IdeSourceSnippetParser, ide_source_snippet_parser, G_TYPE_OBJECT)
+G_DEFINE_TYPE (IdeSnippetParser, ide_snippet_parser, G_TYPE_OBJECT)
 
 enum {
   PARSING_ERROR,
@@ -69,49 +70,49 @@ enum {
 
 static guint signals [N_SIGNALS];
 
-IdeSourceSnippetParser *
-ide_source_snippet_parser_new (void)
+IdeSnippetParser *
+ide_snippet_parser_new (void)
 {
-  return g_object_new (IDE_TYPE_SOURCE_SNIPPET_PARSER, NULL);
+  return g_object_new (IDE_TYPE_SNIPPET_PARSER, NULL);
 }
 
 static void
-ide_source_snippet_parser_flush_chunk (IdeSourceSnippetParser *parser)
+ide_snippet_parser_flush_chunk (IdeSnippetParser *parser)
 {
-  IdeSourceSnippetChunk *chunk;
+  IdeSnippetChunk *chunk;
 
   if (parser->cur_text->len)
     {
-      chunk = ide_source_snippet_chunk_new ();
-      ide_source_snippet_chunk_set_spec (chunk, parser->cur_text->str);
+      chunk = ide_snippet_chunk_new ();
+      ide_snippet_chunk_set_spec (chunk, parser->cur_text->str);
       parser->chunks = g_list_append (parser->chunks, chunk);
       g_string_truncate (parser->cur_text, 0);
     }
 }
 
 static void
-ide_source_snippet_parser_store (IdeSourceSnippetParser *parser)
+ide_snippet_parser_store (IdeSnippetParser *parser)
 {
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
   GList *scope_iter;
   GList *chunck_iter;
 
-  ide_source_snippet_parser_flush_chunk (parser);
+  ide_snippet_parser_flush_chunk (parser);
   for (scope_iter = parser->scope; scope_iter; scope_iter = scope_iter->next)
     {
-      snippet = ide_source_snippet_new (parser->cur_name, scope_iter->data);
-      ide_source_snippet_set_description (snippet, parser->cur_desc);
+      snippet = ide_snippet_new (parser->cur_name, scope_iter->data);
+      ide_snippet_set_description (snippet, parser->cur_desc);
 
       for (chunck_iter = parser->chunks; chunck_iter; chunck_iter = chunck_iter->next)
         {
 #if 0
           g_printerr ("%s:  Tab: %02d  Link: %02d  Text: %s\n",
                       parser->cur_name,
-                      ide_source_snippet_chunk_get_tab_stop (chunck_iter->data),
-                      ide_source_snippet_chunk_get_linked_chunk (chunck_iter->data),
-                      ide_source_snippet_chunk_get_text (chunck_iter->data));
+                      ide_snippet_chunk_get_tab_stop (chunck_iter->data),
+                      ide_snippet_chunk_get_linked_chunk (chunck_iter->data),
+                      ide_snippet_chunk_get_text (chunck_iter->data));
 #endif
-          ide_source_snippet_add_chunk (snippet, chunck_iter->data);
+          ide_snippet_add_chunk (snippet, chunck_iter->data);
         }
 
       parser->snippets = g_list_append (parser->snippets, snippet);
@@ -119,10 +120,10 @@ ide_source_snippet_parser_store (IdeSourceSnippetParser *parser)
 }
 
 static void
-ide_source_snippet_parser_finish (IdeSourceSnippetParser *parser)
+ide_snippet_parser_finish (IdeSnippetParser *parser)
 {
   if (parser->cur_name)
-    ide_source_snippet_parser_store(parser);
+    ide_snippet_parser_store(parser);
 
   g_clear_pointer (&parser->cur_name, g_free);
 
@@ -141,62 +142,62 @@ ide_source_snippet_parser_finish (IdeSourceSnippetParser *parser)
 }
 
 static void
-ide_source_snippet_parser_do_part_simple (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_part_simple (IdeSnippetParser *parser,
                                           const gchar            *line)
 {
   g_string_append (parser->cur_text, line);
 }
 
 static void
-ide_source_snippet_parser_do_part_n (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_part_n (IdeSnippetParser *parser,
                                      gint                    n,
                                      const gchar            *inner)
 {
-  IdeSourceSnippetChunk *chunk;
+  IdeSnippetChunk *chunk;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_PARSER (parser));
+  g_return_if_fail (IDE_IS_SNIPPET_PARSER (parser));
   g_return_if_fail (n >= -1);
   g_return_if_fail (inner);
 
-  chunk = ide_source_snippet_chunk_new ();
-  ide_source_snippet_chunk_set_spec (chunk, n ? inner : "");
-  ide_source_snippet_chunk_set_tab_stop (chunk, n);
+  chunk = ide_snippet_chunk_new ();
+  ide_snippet_chunk_set_spec (chunk, n ? inner : "");
+  ide_snippet_chunk_set_tab_stop (chunk, n);
   parser->chunks = g_list_append (parser->chunks, chunk);
 }
 
 static void
-ide_source_snippet_parser_do_part_linked (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_part_linked (IdeSnippetParser *parser,
                                           gint                    n)
 {
-  IdeSourceSnippetChunk *chunk;
+  IdeSnippetChunk *chunk;
   gchar text[12];
 
-  chunk = ide_source_snippet_chunk_new ();
+  chunk = ide_snippet_chunk_new ();
   if (n)
     {
       g_snprintf (text, sizeof text, "$%d", n);
       text[sizeof text - 1] = '\0';
-      ide_source_snippet_chunk_set_spec (chunk, text);
+      ide_snippet_chunk_set_spec (chunk, text);
     }
   else
     {
-      ide_source_snippet_chunk_set_spec (chunk, "");
-      ide_source_snippet_chunk_set_tab_stop (chunk, 0);
+      ide_snippet_chunk_set_spec (chunk, "");
+      ide_snippet_chunk_set_tab_stop (chunk, 0);
     }
   parser->chunks = g_list_append (parser->chunks, chunk);
 }
 
 static void
-ide_source_snippet_parser_do_part_named (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_part_named (IdeSnippetParser *parser,
                                          const gchar            *name)
 {
-  IdeSourceSnippetChunk *chunk;
+  IdeSnippetChunk *chunk;
   gchar *spec;
 
-  chunk = ide_source_snippet_chunk_new ();
+  chunk = ide_snippet_chunk_new ();
   spec = g_strdup_printf ("$%s", name);
-  ide_source_snippet_chunk_set_spec (chunk, spec);
-  ide_source_snippet_chunk_set_tab_stop (chunk, -1);
+  ide_snippet_chunk_set_spec (chunk, spec);
+  ide_snippet_chunk_set_tab_stop (chunk, -1);
   parser->chunks = g_list_append (parser->chunks, chunk);
   g_free (spec);
 }
@@ -302,7 +303,7 @@ parse_variable (const gchar  *line,
 }
 
 static void
-ide_source_snippet_parser_do_part (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_part (IdeSnippetParser *parser,
                                    const gchar            *line)
 {
   const gchar *dollar;
@@ -322,7 +323,7 @@ again:
 
   if (!(dollar = strchr (line, '$')))
     {
-      ide_source_snippet_parser_do_part_simple (parser, line);
+      ide_snippet_parser_do_part_simple (parser, line);
       return;
     }
 
@@ -339,7 +340,7 @@ again:
   if (dollar != line)
     {
       str = g_strndup (line, (dollar - line));
-      ide_source_snippet_parser_do_part_simple (parser, str);
+      ide_snippet_parser_do_part_simple (parser, str);
       g_free (str);
       line = dollar;
     }
@@ -349,7 +350,7 @@ parse_dollar:
 
   if (!parse_variable (line, &n, &inner, &line, &name))
     {
-      ide_source_snippet_parser_do_part_simple (parser, line);
+      ide_snippet_parser_do_part_simple (parser, line);
       return;
     }
 
@@ -358,18 +359,18 @@ parse_dollar:
   g_printerr ("  Left over: \"%s\"\n", line);
 #endif
 
-  ide_source_snippet_parser_flush_chunk (parser);
+  ide_snippet_parser_flush_chunk (parser);
 
   if (inner)
     {
-      ide_source_snippet_parser_do_part_n (parser, n, inner);
+      ide_snippet_parser_do_part_n (parser, n, inner);
       g_free (inner);
       inner = NULL;
     }
   else if (n == -2 && name)
-    ide_source_snippet_parser_do_part_named (parser, name);
+    ide_snippet_parser_do_part_named (parser, name);
   else
-    ide_source_snippet_parser_do_part_linked (parser, n);
+    ide_snippet_parser_do_part_linked (parser, n);
 
   g_free (name);
 
@@ -385,14 +386,14 @@ parse_dollar:
 }
 
 static void
-ide_source_snippet_parser_do_snippet (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_snippet (IdeSnippetParser *parser,
                                       const gchar            *line)
 {
   parser->cur_name = g_strstrip (g_strdup (&line[8]));
 }
 
 static void
-ide_source_snippet_parser_do_snippet_scope (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_snippet_scope (IdeSnippetParser *parser,
                                             const gchar            *line)
 {
   gchar **scope_list;
@@ -422,7 +423,7 @@ ide_source_snippet_parser_do_snippet_scope (IdeSourceSnippetParser *parser,
 }
 
 static void
-ide_source_snippet_parser_do_snippet_description (IdeSourceSnippetParser *parser,
+ide_snippet_parser_do_snippet_description (IdeSnippetParser *parser,
                                                   const gchar            *line)
 {
   if (parser->cur_desc)
@@ -435,7 +436,7 @@ ide_source_snippet_parser_do_snippet_description (IdeSourceSnippetParser *parser
 }
 
 static void
-ide_source_snippet_parser_feed_line (IdeSourceSnippetParser *parser,
+ide_snippet_parser_feed_line (IdeSnippetParser *parser,
                                      gchar                  *basename,
                                      const gchar            *line)
 {
@@ -477,15 +478,15 @@ ide_source_snippet_parser_feed_line (IdeSourceSnippetParser *parser,
 
           if (parser->cur_text->len || parser->chunks)
             g_string_append_c (parser->cur_text, '\n');
-          ide_source_snippet_parser_do_part (parser, line);
+          ide_snippet_parser_do_part (parser, line);
         }
       break;
 
     case 's':
       if (g_str_has_prefix (line, "snippet"))
         {
-          ide_source_snippet_parser_finish (parser);
-          ide_source_snippet_parser_do_snippet (parser, line);
+          ide_snippet_parser_finish (parser);
+          ide_snippet_parser_do_snippet (parser, line);
           break;
         }
 
@@ -493,7 +494,7 @@ ide_source_snippet_parser_feed_line (IdeSourceSnippetParser *parser,
     case '-':
       if (parser->cur_text->len || parser->chunks)
         {
-          ide_source_snippet_parser_store(parser);
+          ide_snippet_parser_store(parser);
 
           g_string_truncate (parser->cur_text, 0);
 
@@ -507,13 +508,13 @@ ide_source_snippet_parser_feed_line (IdeSourceSnippetParser *parser,
 
       if (g_str_has_prefix(line, "- scope"))
         {
-          ide_source_snippet_parser_do_snippet_scope (parser, line);
+          ide_snippet_parser_do_snippet_scope (parser, line);
           break;
         }
 
       if (g_str_has_prefix(line, "- desc"))
         {
-          ide_source_snippet_parser_do_snippet_description (parser, line);
+          ide_snippet_parser_do_snippet_description (parser, line);
           break;
         }
 
@@ -530,9 +531,9 @@ ide_source_snippet_parser_feed_line (IdeSourceSnippetParser *parser,
 }
 
 gboolean
-ide_source_snippet_parser_load_from_file (IdeSourceSnippetParser *parser,
-                                          GFile                  *file,
-                                          GError                **error)
+ide_snippet_parser_load_from_file (IdeSnippetParser  *parser,
+                                   GFile             *file,
+                                   GError           **error)
 {
   GFileInputStream *file_stream;
   g_autoptr(GDataInputStream) data_stream = NULL;
@@ -540,7 +541,7 @@ ide_source_snippet_parser_load_from_file (IdeSourceSnippetParser *parser,
   gchar *line;
   gchar *basename = NULL;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_PARSER (parser), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET_PARSER (parser), FALSE);
   g_return_val_if_fail (G_IS_FILE (file), FALSE);
 
   basename = g_file_get_basename (file);
@@ -581,30 +582,71 @@ again:
     }
   else if (line)
     {
-      ide_source_snippet_parser_feed_line (parser, basename, line);
+      ide_snippet_parser_feed_line (parser, basename, line);
       g_free (line);
       goto again;
     }
 
-  ide_source_snippet_parser_finish (parser);
-  g_free(basename);
+  ide_snippet_parser_finish (parser);
+  g_free (basename);
 
   g_set_object (&parser->current_file, NULL);
 
   return TRUE;
 }
 
+gboolean
+ide_snippet_parser_load_from_data (IdeSnippetParser  *parser,
+                                   const gchar       *data,
+                                   gssize             data_len,
+                                   GError           **error)
+{
+  IdeLineReader reader;
+  gchar *line;
+  gsize line_len;
+
+  g_return_val_if_fail (IDE_IS_SNIPPET_PARSER (parser), FALSE);
+  g_return_val_if_fail (data != NULL, FALSE);
+
+  if (data_len < 0)
+    data_len = strlen (data);
+
+  ide_line_reader_init (&reader, (gchar *)data, data_len);
+
+  while ((line = ide_line_reader_next (&reader, &line_len)))
+    {
+      g_autofree gchar *copy = NULL;
+
+      if (parser->had_error)
+        {
+          g_set_error (error,
+                       G_IO_ERROR,
+                       G_IO_ERROR_INVALID_DATA,
+                       "<data>:%d: invalid snippet",
+                       parser->lineno);
+          return FALSE;
+        }
+
+      copy = g_strndup (line, line_len);
+      ide_snippet_parser_feed_line (parser, "<data>", copy);
+    }
+
+  ide_snippet_parser_finish (parser);
+
+  return TRUE;
+}
+
 GList *
-ide_source_snippet_parser_get_snippets (IdeSourceSnippetParser *parser)
+ide_snippet_parser_get_snippets (IdeSnippetParser *parser)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET_PARSER (parser), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET_PARSER (parser), NULL);
   return parser->snippets;
 }
 
 static void
-ide_source_snippet_parser_finalize (GObject *object)
+ide_snippet_parser_finalize (GObject *object)
 {
-  IdeSourceSnippetParser *self = IDE_SOURCE_SNIPPET_PARSER (object);
+  IdeSnippetParser *self = IDE_SNIPPET_PARSER (object);
 
   g_list_foreach (self->snippets, (GFunc) g_object_unref, NULL);
   g_list_free (self->snippets);
@@ -634,16 +676,16 @@ ide_source_snippet_parser_finalize (GObject *object)
       self->cur_desc = NULL;
     }
 
-  G_OBJECT_CLASS (ide_source_snippet_parser_parent_class)->finalize (object);
+  G_OBJECT_CLASS (ide_snippet_parser_parent_class)->finalize (object);
 }
 
 static void
-ide_source_snippet_parser_class_init (IdeSourceSnippetParserClass *klass)
+ide_snippet_parser_class_init (IdeSnippetParserClass *klass)
 {
   GObjectClass *object_class;
 
   object_class = G_OBJECT_CLASS (klass);
-  object_class->finalize = ide_source_snippet_parser_finalize;
+  object_class->finalize = ide_snippet_parser_finalize;
 
   signals [PARSING_ERROR] =
     g_signal_new ("parsing-error",
@@ -660,7 +702,7 @@ ide_source_snippet_parser_class_init (IdeSourceSnippetParserClass *klass)
 }
 
 static void
-ide_source_snippet_parser_init (IdeSourceSnippetParser *parser)
+ide_snippet_parser_init (IdeSnippetParser *parser)
 {
   parser->lineno = -1;
   parser->cur_text = g_string_new (NULL);
diff --git a/src/libide/snippets/ide-snippet-parser.h b/src/libide/snippets/ide-snippet-parser.h
new file mode 100644
index 000000000..1aceda3cc
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-parser.h
@@ -0,0 +1,46 @@
+/* ide-snippet-parser.h
+ *
+ * Copyright 2013 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/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#include "ide-version-macros.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SNIPPET_PARSER (ide_snippet_parser_get_type())
+
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeSnippetParser, ide_snippet_parser, IDE, SNIPPET_PARSER, GObject)
+
+IDE_AVAILABLE_IN_3_30
+IdeSnippetParser *ide_snippet_parser_new            (void);
+IDE_AVAILABLE_IN_3_30
+gboolean          ide_snippet_parser_load_from_data (IdeSnippetParser  *parser,
+                                                     const gchar       *data,
+                                                     gssize             data_len,
+                                                     GError           **error);
+IDE_AVAILABLE_IN_3_30
+gboolean          ide_snippet_parser_load_from_file (IdeSnippetParser  *parser,
+                                                     GFile             *file,
+                                                     GError           **error);
+IDE_AVAILABLE_IN_3_30
+GList            *ide_snippet_parser_get_snippets   (IdeSnippetParser  *parser);
+
+G_END_DECLS
diff --git a/src/libide/snippets/ide-snippet-private.h b/src/libide/snippets/ide-snippet-private.h
new file mode 100644
index 000000000..03423c482
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-private.h
@@ -0,0 +1,59 @@
+/* ide-snippet-private.h
+ *
+ * Copyright 2013 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "ide-snippet.h"
+
+G_BEGIN_DECLS
+
+gboolean         ide_snippet_begin               (IdeSnippet    *self,
+                                                  GtkTextBuffer *buffer,
+                                                  GtkTextIter   *iter);
+void             ide_snippet_pause               (IdeSnippet    *self);
+void             ide_snippet_unpause             (IdeSnippet    *self);
+void             ide_snippet_finish              (IdeSnippet    *self);
+gboolean         ide_snippet_move_next           (IdeSnippet    *self);
+gboolean         ide_snippet_move_previous       (IdeSnippet    *self);
+void             ide_snippet_before_insert_text  (IdeSnippet    *self,
+                                                  GtkTextBuffer *buffer,
+                                                  GtkTextIter   *iter,
+                                                  gchar         *text,
+                                                  gint           len);
+void             ide_snippet_after_insert_text   (IdeSnippet    *self,
+                                                  GtkTextBuffer *buffer,
+                                                  GtkTextIter   *iter,
+                                                  gchar         *text,
+                                                  gint           len);
+void             ide_snippet_before_delete_range (IdeSnippet    *self,
+                                                  GtkTextBuffer *buffer,
+                                                  GtkTextIter   *begin,
+                                                  GtkTextIter   *end);
+void             ide_snippet_after_delete_range  (IdeSnippet    *self,
+                                                  GtkTextBuffer *buffer,
+                                                  GtkTextIter   *begin,
+                                                  GtkTextIter   *end);
+gboolean         ide_snippet_insert_set          (IdeSnippet    *self,
+                                                  GtkTextMark   *mark);
+void             ide_snippet_dump                (IdeSnippet    *self);
+GtkTextMark     *ide_snippet_get_mark_begin      (IdeSnippet    *self);
+GtkTextMark     *ide_snippet_get_mark_end        (IdeSnippet    *self);
+
+G_END_DECLS
diff --git a/src/libide/snippets/ide-snippet-storage.c b/src/libide/snippets/ide-snippet-storage.c
new file mode 100644
index 000000000..f318babd3
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-storage.c
@@ -0,0 +1,443 @@
+/* ide-snippet-storage.c
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#include "config.h"
+
+#define G_LOG_DOMAIN "ide-snippet-storage"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "snippets/ide-snippet-storage.h"
+#include "util/ide-line-reader.h"
+
+#define SNIPPETS_DIRECTORY "/org/gnome/builder/snippets/"
+
+/**
+ * SECTION:ide-snippet-storage
+ * @title: IdeSnippetStorage
+ * @short_description: storage and loading of snippets
+ *
+ * The #IdeSnippetStorage object manages parsing snippet files from disk.
+ * To avoid creating lots of small allocations, it delays parsing of
+ * snippets fully until necessary.
+ *
+ * To do this, mapped files are used and just enough information is
+ * extracted to describe the snippets. Then snippets are inflated and
+ * fully parsed when requested.
+ *
+ * In doing so, we can use #GStringChunk for the meta-data, and then only
+ * create all the small strings when we inflate the snippet and its chunks.
+ *
+ * Since: 3.30
+ */
+
+struct _IdeSnippetStorage
+{
+  GObject       parent_instance;
+  GStringChunk *strings;
+  GArray       *infos;
+  GPtrArray    *bytes;
+
+  guint         loaded : 1;
+};
+
+typedef struct
+{
+  gchar *name;
+  gchar *desc;
+  gchar *scopes;
+  const gchar *beginptr;
+  const gchar *endptr;
+} LoadState;
+
+G_DEFINE_TYPE (IdeSnippetStorage, ide_snippet_storage, G_TYPE_OBJECT)
+
+static void
+ide_snippet_storage_finalize (GObject *object)
+{
+  IdeSnippetStorage *self = (IdeSnippetStorage *)object;
+
+  g_clear_pointer (&self->bytes, g_ptr_array_unref);
+  g_clear_pointer (&self->strings, g_string_chunk_free);
+  g_clear_pointer (&self->infos, g_array_unref);
+
+  G_OBJECT_CLASS (ide_snippet_storage_parent_class)->finalize (object);
+}
+
+static void
+ide_snippet_storage_class_init (IdeSnippetStorageClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_snippet_storage_finalize;
+}
+
+static void
+ide_snippet_storage_init (IdeSnippetStorage *self)
+{
+  self->strings = g_string_chunk_new (4096);
+  self->infos = g_array_new (FALSE, FALSE, sizeof (IdeSnippetInfo));
+  self->bytes = g_ptr_array_new_with_free_func ((GDestroyNotify)g_bytes_unref);
+}
+
+IdeSnippetStorage *
+ide_snippet_storage_new (void)
+{
+  return g_object_new (IDE_TYPE_SNIPPET_STORAGE, NULL);
+}
+
+static gint
+snippet_info_compare (gconstpointer a,
+                      gconstpointer b)
+{
+  const IdeSnippetInfo *ai = a;
+  const IdeSnippetInfo *bi = b;
+  gint r;
+
+  if (!(r = g_strcmp0 (ai->lang, bi->lang)))
+    r = g_strcmp0 (ai->name, bi->name);
+
+  return r;
+}
+
+static gboolean
+str_starts_with (const gchar *str,
+                 gsize        len,
+                 const gchar *needle)
+{
+  gsize needle_len = strlen (needle);
+  if (len < needle_len)
+    return FALSE;
+  return strncmp (str, needle, needle_len) == 0;
+}
+
+static void
+flush_load_state (IdeSnippetStorage *self,
+                  const gchar       *default_scope,
+                  LoadState         *state)
+{
+  g_auto(GStrv) scopes = NULL;
+  IdeSnippetInfo info = {0};
+  gboolean needs_default = TRUE;
+
+  if (state->name == NULL)
+    goto cleanup;
+
+  g_assert (state->beginptr);
+  g_assert (state->endptr);
+  g_assert (state->endptr > state->beginptr);
+
+  if (state->scopes != NULL)
+    scopes = g_strsplit (state->scopes, ",", 0);
+
+  info.name = g_string_chunk_insert_const (self->strings, state->name);
+  if (state->desc)
+    info.desc = g_string_chunk_insert_const (self->strings, state->desc);
+
+  info.begin = state->beginptr;
+  info.len = state->endptr - state->beginptr;
+
+  if (scopes != NULL)
+    {
+      for (guint i = 0; scopes[i] != NULL; i++)
+        {
+          g_strstrip (scopes[i]);
+          if (g_strcmp0 (scopes[i], default_scope) == 0)
+            needs_default = FALSE;
+          info.lang = g_string_chunk_insert_const (self->strings, scopes[i]);
+          g_array_append_val (self->infos, info);
+        }
+    }
+
+  if (needs_default && default_scope)
+    {
+      info.lang = g_string_chunk_insert_const (self->strings, default_scope);
+      g_array_append_val (self->infos, info);
+    }
+
+cleanup:
+  g_clear_pointer (&state->name, g_free);
+  g_clear_pointer (&state->desc, g_free);
+  g_clear_pointer (&state->scopes, g_free);
+}
+
+void
+ide_snippet_storage_add (IdeSnippetStorage *self,
+                         const gchar       *default_scope,
+                         GBytes            *bytes)
+{
+  IdeLineReader reader;
+  LoadState state = {0};
+  const gchar *data;
+  const gchar *line;
+  gsize line_len;
+  gsize len;
+
+  g_return_if_fail (IDE_IS_SNIPPET_STORAGE (self));
+  g_return_if_fail (bytes != NULL);
+
+  g_ptr_array_add (self->bytes, g_bytes_ref (bytes));
+
+  data = g_bytes_get_data (bytes, &len);
+  state.beginptr = data;
+
+  ide_line_reader_init (&reader, (gchar *)data, len);
+
+#define COPY_AFTER(dst, str) \
+  G_STMT_START { \
+    g_free (state.dst); \
+    state.dst = g_strstrip(g_strndup(line + strlen(str), line_len - strlen(str))); \
+  } G_STMT_END
+
+  while ((line = ide_line_reader_next (&reader, &line_len)))
+    {
+      if (str_starts_with (line, line_len, "snippet "))
+        {
+          if (state.name)
+            flush_load_state (self, default_scope, &state);
+          state.beginptr = line;
+          COPY_AFTER (name, "snippet ");
+        }
+      else if (str_starts_with (line, line_len, "- desc "))
+        COPY_AFTER (desc, "- desc");
+      else if (str_starts_with (line, line_len, "- scope "))
+        COPY_AFTER (scopes, "- scope ");
+
+      state.endptr = line + line_len;
+    }
+
+#undef COPY_AFTER
+
+  flush_load_state (self, default_scope, &state);
+
+  g_array_sort (self->infos, snippet_info_compare);
+}
+
+/**
+ * ide_snippet_storage_query:
+ * @self: a #IdeSnippetStorage
+ * @foreach: (scope call): the closure to call for each info
+ * @user_data: closure data for @foreach
+ *
+ * This will call @foreach for every item that has been loaded.
+ *
+ * Since: 3.30
+ */
+void
+ide_snippet_storage_foreach (IdeSnippetStorage        *self,
+                             IdeSnippetStorageForeach  foreach,
+                             gpointer                  user_data)
+{
+  g_return_if_fail (IDE_IS_SNIPPET_STORAGE (self));
+  g_return_if_fail (foreach != NULL);
+
+  for (guint i = 0; i < self->infos->len; i++)
+    {
+      const IdeSnippetInfo *info = &g_array_index (self->infos, IdeSnippetInfo, i);
+
+      foreach (self, info, user_data);
+    }
+}
+
+static gint
+query_compare (gconstpointer a,
+               gconstpointer b)
+{
+  const IdeSnippetInfo *ai = a;
+  const IdeSnippetInfo *bi = b;
+  gboolean r;
+  
+  if (!(r = g_strcmp0 (ai->lang, bi->lang)))
+    {
+      if (g_str_has_prefix (bi->name, ai->name))
+        return 0;
+      r = g_strcmp0 (ai->name, bi->name);
+    }
+
+  return r;
+}
+
+/**
+ * ide_snippet_storage_query:
+ * @self: a #IdeSnippetStorage
+ * @lang: language to query
+ * @prefix: (nullable): prefix for query
+ * @foreach: (scope call): the closure to call for each match
+ * @user_data: closure data for @foreach
+ *
+ * This will call @foreach for every info that matches the query. This is
+ * useful when building autocompletion lists based on word prefixes.
+ *
+ * Since: 3.30
+ */
+void
+ide_snippet_storage_query (IdeSnippetStorage        *self,
+                           const gchar              *lang,
+                           const gchar              *prefix,
+                           IdeSnippetStorageForeach  foreach,
+                           gpointer                  user_data)
+{
+  IdeSnippetInfo key = { 0 };
+  const IdeSnippetInfo *endptr;
+  const IdeSnippetInfo *base;
+
+  g_return_if_fail (IDE_IS_SNIPPET_STORAGE (self));
+  g_return_if_fail (lang != NULL);
+  g_return_if_fail (foreach != NULL);
+
+  if (self->infos->len == 0)
+    return;
+
+  if (prefix == NULL)
+    prefix = "";
+
+  key.lang = lang;
+  key.name = prefix;
+
+  base = bsearch (&key,
+                  self->infos->data,
+                  self->infos->len,
+                  sizeof (IdeSnippetInfo),
+                  query_compare);
+
+  if (base == NULL)
+    return;
+
+  while ((gpointer)base > (gpointer)self->infos->data)
+    {
+      const IdeSnippetInfo *prev = base - 1;
+
+      if (base->lang == prev->lang && g_str_has_prefix (prev->name, prefix))
+        base = prev;
+      else
+        break;
+    }
+
+  endptr = &g_array_index (self->infos, IdeSnippetInfo, self->infos->len);
+
+  for (; base < endptr; base++)
+    {
+      if (g_strcmp0 (base->lang, lang) != 0)
+        break;
+
+      if (!g_str_has_prefix (base->name, prefix) != 0)
+        break;
+
+      foreach (self, base, user_data);
+    }
+}
+
+void
+ide_snippet_storage_load_async (IdeSnippetStorage   *self,
+                                GCancellable        *cancellable,
+                                GAsyncReadyCallback  callback,
+                                gpointer             user_data)
+{
+  g_autofree gchar *local = NULL;
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(GDir) dir = NULL;
+  g_autoptr(GError) error = NULL;
+  g_auto(GStrv) names = NULL;
+
+  g_return_if_fail (IDE_IS_SNIPPET_STORAGE (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_snippet_storage_load_async);
+
+  if (self->loaded)
+    {
+      g_task_return_boolean (task, TRUE);
+      return;
+    }
+
+  self->loaded = TRUE;
+
+  if (!(names = g_resources_enumerate_children (SNIPPETS_DIRECTORY,
+                                                G_RESOURCE_LOOKUP_FLAGS_NONE,
+                                                &error)))
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  for (guint i = 0; names[i] != NULL; i++)
+    {
+      g_autofree gchar *path = g_build_filename (SNIPPETS_DIRECTORY, names[i], NULL);
+      g_autoptr(GBytes) bytes = g_resources_lookup_data (path, 0, NULL);
+      g_autofree gchar *base = NULL;
+      const gchar *dot;
+
+      if (bytes == NULL)
+        continue;
+
+      if ((dot = strrchr (names[i], '.')))
+        base = g_strndup (names[i], dot - names[i]);
+
+      ide_snippet_storage_add (self, base, bytes);
+    }
+
+  /* TODO: Do this async */
+
+  local = g_build_filename (g_get_user_config_dir (),
+                            "gnome-builder",
+                            "snippets",
+                            NULL);
+
+  if ((dir = g_dir_open (local, 0, NULL)))
+    {
+      const gchar *name;
+
+      while ((name = g_dir_read_name (dir)))
+        {
+          g_autofree gchar *path = g_build_filename (local, name, NULL);
+          g_autoptr(GMappedFile) mf = NULL;
+          g_autoptr(GBytes) bytes = NULL;
+          g_autofree gchar *base = NULL;
+          const gchar *dot;
+
+          if (!(mf = g_mapped_file_new (path, FALSE, &error)))
+            {
+              g_message ("%s", error->message);
+              g_clear_error (&error);
+              continue;
+            }
+
+          bytes = g_mapped_file_get_bytes (mf);
+
+          if ((dot = strrchr (name, '.')))
+            base = g_strndup (name, dot - name);
+
+          ide_snippet_storage_add (self, base, bytes);
+        }
+    }
+
+  g_task_return_boolean (task, TRUE);
+}
+
+gboolean
+ide_snippet_storage_load_finish (IdeSnippetStorage  *self,
+                                 GAsyncResult       *result,
+                                 GError            **error)
+{
+  g_return_val_if_fail (IDE_IS_SNIPPET_STORAGE (self), FALSE);
+  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+  return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/src/libide/snippets/ide-snippet-storage.h b/src/libide/snippets/ide-snippet-storage.h
new file mode 100644
index 000000000..ef4854d88
--- /dev/null
+++ b/src/libide/snippets/ide-snippet-storage.h
@@ -0,0 +1,73 @@
+/* ide-snippet-storage.h
+ *
+ * Copyright 2018 Christian Hergert <chergert redhat com>
+ *
+ * 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/>.
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#include "ide-types.h"
+#include "ide-version-macros.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SNIPPET_STORAGE (ide_snippet_storage_get_type())
+
+typedef struct
+{
+  const gchar *lang;
+  const gchar *name;
+  const gchar *desc;
+  /*< private >*/
+  const gchar *begin;
+  goffset      len;
+} IdeSnippetInfo;
+
+typedef void (*IdeSnippetStorageForeach) (IdeSnippetStorage    *self,
+                                          const IdeSnippetInfo *info,
+                                          gpointer              user_data);
+
+IDE_AVAILABLE_IN_3_30
+G_DECLARE_FINAL_TYPE (IdeSnippetStorage, ide_snippet_storage, IDE, SNIPPET_STORAGE, GObject)
+
+IDE_AVAILABLE_IN_3_30
+IdeSnippetStorage *ide_snippet_storage_new         (void);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_storage_add         (IdeSnippetStorage         *self,
+                                                    const gchar               *default_scope,
+                                                    GBytes                    *bytes);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_storage_foreach     (IdeSnippetStorage         *self,
+                                                    IdeSnippetStorageForeach   foreach,
+                                                    gpointer                   user_data);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_storage_query       (IdeSnippetStorage         *self,
+                                                    const gchar               *lang,
+                                                    const gchar               *prefix,
+                                                    IdeSnippetStorageForeach   foreach,
+                                                    gpointer                   user_data);
+IDE_AVAILABLE_IN_3_30
+void               ide_snippet_storage_load_async  (IdeSnippetStorage         *self,
+                                                    GCancellable              *cancellable,
+                                                    GAsyncReadyCallback        callback,
+                                                    gpointer                   user_data);
+IDE_AVAILABLE_IN_3_30
+gboolean           ide_snippet_storage_load_finish (IdeSnippetStorage         *self,
+                                                    GAsyncResult              *result,
+                                                    GError                   **error);
+
+G_END_DECLS
diff --git a/src/libide/snippets/ide-source-snippet.c b/src/libide/snippets/ide-snippet.c
similarity index 66%
rename from src/libide/snippets/ide-source-snippet.c
rename to src/libide/snippets/ide-snippet.c
index 17d24db01..a285a72ae 100644
--- a/src/libide/snippets/ide-source-snippet.c
+++ b/src/libide/snippets/ide-snippet.c
@@ -1,4 +1,4 @@
-/* ide-source-snippet.c
+/* ide-snippet.c
  *
  * Copyright 2013 Christian Hergert <christian hergert me>
  *
@@ -16,7 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#define G_LOG_DOMAIN "ide-source-snippet"
+#define G_LOG_DOMAIN "ide-snippet"
 
 #include "config.h"
 
@@ -25,27 +25,27 @@
 
 #include "ide-debug.h"
 
-#include "snippets/ide-source-snippet.h"
-#include "snippets/ide-source-snippet-private.h"
-#include "snippets/ide-source-snippet-chunk.h"
-#include "snippets/ide-source-snippet-context.h"
+#include "ide-snippet.h"
+#include "ide-snippet-private.h"
+#include "ide-snippet-chunk.h"
+#include "ide-snippet-context.h"
 
 /**
- * SECTION:ide-source-snippet
- * @title: IdeSourceSnippet
+ * SECTION:ide-snippet
+ * @title: IdeSnippet
  * @short_description: A snippet to be inserted into a file
  *
- * The #IdeSourceSnippet represents a single snippet that may be inserted
+ * The #IdeSnippet represents a single snippet that may be inserted
  * into the #IdeSourceView.
  */
 
 #define TAG_SNIPPET_TAB_STOP "snippet::tab-stop"
 
-struct _IdeSourceSnippet
+struct _IdeSnippet
 {
-  IdeObject                parent_instance;
+  GObject                  parent_instance;
 
-  IdeSourceSnippetContext *snippet_context;
+  IdeSnippetContext       *snippet_context;
   GtkTextBuffer           *buffer;
   GPtrArray               *chunks;
   GArray                  *runs;
@@ -74,48 +74,48 @@ enum {
   LAST_PROP
 };
 
-G_DEFINE_TYPE (IdeSourceSnippet, ide_source_snippet, G_TYPE_OBJECT)
+G_DEFINE_TYPE (IdeSnippet, ide_snippet, G_TYPE_OBJECT)
 
-DZL_DEFINE_COUNTER (instances, "Snippets", "N Snippets", "Number of IdeSourceSnippet instances.");
+DZL_DEFINE_COUNTER (instances, "Snippets", "N Snippets", "Number of IdeSnippet instances.");
 
 static GParamSpec * properties[LAST_PROP];
 
 /**
- * ide_source_snippet_new:
+ * ide_snippet_new:
  * @trigger: (nullable): the trigger word
  * @language: (nullable): the source language
  *
- * Creates a new #IdeSourceSnippet
+ * Creates a new #IdeSnippet
  *
- * Returns: (transfer full): A new #IdeSourceSnippet
+ * Returns: (transfer full): A new #IdeSnippet
  */
-IdeSourceSnippet *
-ide_source_snippet_new (const gchar *trigger,
+IdeSnippet *
+ide_snippet_new (const gchar *trigger,
                         const gchar *language)
 {
-  return g_object_new (IDE_TYPE_SOURCE_SNIPPET,
+  return g_object_new (IDE_TYPE_SNIPPET,
                        "trigger", trigger,
                        "language", language,
                        NULL);
 }
 
 /**
- * ide_source_snippet_copy:
- * @self: an #IdeSourceSnippet
+ * ide_snippet_copy:
+ * @self: an #IdeSnippet
  *
  * Does a deep copy of the snippet.
  *
- * Returns: (transfer full): An #IdeSourceSnippet.
+ * Returns: (transfer full): An #IdeSnippet.
  */
-IdeSourceSnippet *
-ide_source_snippet_copy (IdeSourceSnippet *self)
+IdeSnippet *
+ide_snippet_copy (IdeSnippet *self)
 {
-  IdeSourceSnippetChunk *chunk;
-  IdeSourceSnippet *ret;
+  IdeSnippetChunk *chunk;
+  IdeSnippet *ret;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
-  ret = g_object_new (IDE_TYPE_SOURCE_SNIPPET,
+  ret = g_object_new (IDE_TYPE_SNIPPET,
                       "trigger", self->trigger,
                       "language", self->language,
                       "description", self->description,
@@ -124,8 +124,8 @@ ide_source_snippet_copy (IdeSourceSnippet *self)
   for (guint i = 0; i < self->chunks->len; i++)
     {
       chunk = g_ptr_array_index (self->chunks, i);
-      chunk = ide_source_snippet_chunk_copy (chunk);
-      ide_source_snippet_add_chunk (ret, chunk);
+      chunk = ide_snippet_chunk_copy (chunk);
+      ide_snippet_add_chunk (ret, chunk);
       g_object_unref (chunk);
     }
 
@@ -133,8 +133,8 @@ ide_source_snippet_copy (IdeSourceSnippet *self)
 }
 
 /**
- * ide_source_snippet_get_tab_stop:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_get_tab_stop:
+ * @self: a #IdeSnippet
  *
  * Gets the current tab stop for the snippet. This is changed
  * as the user Tab's through the edit points.
@@ -142,16 +142,16 @@ ide_source_snippet_copy (IdeSourceSnippet *self)
  * Returns: The tab stop, or -1 if unset.
  */
 gint
-ide_source_snippet_get_tab_stop (IdeSourceSnippet *self)
+ide_snippet_get_tab_stop (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), -1);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), -1);
 
   return self->tab_stop;
 }
 
 /**
- * ide_source_snippet_get_n_chunks:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_get_n_chunks:
+ * @self: a #IdeSnippet
  *
  * Gets the number of chunks in the snippet. Not all chunks
  * are editable.
@@ -159,27 +159,27 @@ ide_source_snippet_get_tab_stop (IdeSourceSnippet *self)
  * Returns: The number of chunks.
  */
 guint
-ide_source_snippet_get_n_chunks (IdeSourceSnippet *self)
+ide_snippet_get_n_chunks (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), 0);
 
   return self->chunks->len;
 }
 
 /**
- * ide_source_snippet_get_nth_chunk:
- * @self: an #IdeSourceSnippet
+ * ide_snippet_get_nth_chunk:
+ * @self: an #IdeSnippet
  * @n: the nth chunk to get
  *
  * Gets the chunk at @n.
  *
- * Returns: (transfer none): an #IdeSourceSnippetChunk
+ * Returns: (transfer none): an #IdeSnippetChunk
  */
-IdeSourceSnippetChunk *
-ide_source_snippet_get_nth_chunk (IdeSourceSnippet *self,
+IdeSnippetChunk *
+ide_snippet_get_nth_chunk (IdeSnippet *self,
                                   guint             n)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), 0);
 
   if (n < self->chunks->len)
     return g_ptr_array_index (self->chunks, n);
@@ -188,33 +188,33 @@ ide_source_snippet_get_nth_chunk (IdeSourceSnippet *self,
 }
 
 /**
- * ide_source_snippet_get_trigger:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_get_trigger:
+ * @self: a #IdeSnippet
  *
  * Gets the trigger for the source snippet
  *
  * Returns: (nullable): A trigger if specified
  */
 const gchar *
-ide_source_snippet_get_trigger (IdeSourceSnippet *self)
+ide_snippet_get_trigger (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
   return self->trigger;
 }
 
 /**
- * ide_source_snippet_set_trigger:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_set_trigger:
+ * @self: a #IdeSnippet
  * @trigger: the trigger word
  *
  * Sets the trigger for the snippet.
  */
 void
-ide_source_snippet_set_trigger (IdeSourceSnippet *self,
+ide_snippet_set_trigger (IdeSnippet *self,
                                 const gchar      *trigger)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
   if (self->trigger != trigger)
     {
@@ -224,8 +224,8 @@ ide_source_snippet_set_trigger (IdeSourceSnippet *self,
 }
 
 /**
- * ide_source_snippet_get_language:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_get_language:
+ * @self: a #IdeSnippet
  *
  * Gets the language used for the source snippet.
  *
@@ -235,26 +235,26 @@ ide_source_snippet_set_trigger (IdeSourceSnippet *self,
  * Returns: the language identifier
  */
 const gchar *
-ide_source_snippet_get_language (IdeSourceSnippet *self)
+ide_snippet_get_language (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
   return self->language;
 }
 
 /**
- * ide_source_snippet_set_language:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_set_language:
+ * @self: a #IdeSnippet
  *
  * Sets the language identifier for the snippet.
  *
  * This should match the #GtkSourceLanguage:id identifier.
  */
 void
-ide_source_snippet_set_language (IdeSourceSnippet *self,
+ide_snippet_set_language (IdeSnippet *self,
                                  const gchar      *language)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
   language = g_intern_string (language);
 
@@ -266,31 +266,31 @@ ide_source_snippet_set_language (IdeSourceSnippet *self,
 }
 
 /**
- * ide_source_snippet_get_description:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_get_description:
+ * @self: a #IdeSnippet
  *
  * Gets the description for the snippet.
  */
 const gchar *
-ide_source_snippet_get_description (IdeSourceSnippet *self)
+ide_snippet_get_description (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
   return self->description;
 }
 
 /**
- * ide_source_snippet_set_description:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_set_description:
+ * @self: a #IdeSnippet
  * @description: the snippet description
  *
  * Sets the description for the snippet.
  */
 void
-ide_source_snippet_set_description (IdeSourceSnippet *self,
+ide_snippet_set_description (IdeSnippet *self,
                                     const gchar      *description)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
   if (self->description != description)
     {
@@ -300,13 +300,13 @@ ide_source_snippet_set_description (IdeSourceSnippet *self,
 }
 
 static gint
-ide_source_snippet_get_offset (IdeSourceSnippet *self,
+ide_snippet_get_offset (IdeSnippet *self,
                                GtkTextIter      *iter)
 {
   GtkTextIter begin;
   gint ret;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), 0);
   g_return_val_if_fail (iter, 0);
 
   gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin);
@@ -317,16 +317,16 @@ ide_source_snippet_get_offset (IdeSourceSnippet *self,
 }
 
 static gint
-ide_source_snippet_get_index (IdeSourceSnippet *self,
+ide_snippet_get_index (IdeSnippet *self,
                               GtkTextIter      *iter)
 {
   gint offset;
   gint run;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), 0);
   g_return_val_if_fail (iter, 0);
 
-  offset = ide_source_snippet_get_offset (self, iter);
+  offset = ide_snippet_get_offset (self, iter);
 
   for (guint i = 0; i < self->runs->len; i++)
     {
@@ -349,14 +349,14 @@ ide_source_snippet_get_index (IdeSourceSnippet *self,
 }
 
 static gboolean
-ide_source_snippet_within_bounds (IdeSourceSnippet *self,
+ide_snippet_within_bounds (IdeSnippet *self,
                                   GtkTextIter      *iter)
 {
   GtkTextIter begin;
   GtkTextIter end;
   gboolean ret;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), FALSE);
   g_return_val_if_fail (iter, FALSE);
 
   gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin);
@@ -369,26 +369,26 @@ ide_source_snippet_within_bounds (IdeSourceSnippet *self,
 }
 
 gboolean
-ide_source_snippet_insert_set (IdeSourceSnippet *self,
+ide_snippet_insert_set (IdeSnippet *self,
                                GtkTextMark      *mark)
 {
   GtkTextIter iter;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), FALSE);
   g_return_val_if_fail (GTK_IS_TEXT_MARK (mark), FALSE);
 
   gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, mark);
 
-  if (!ide_source_snippet_within_bounds (self, &iter))
+  if (!ide_snippet_within_bounds (self, &iter))
     return FALSE;
 
-  self->current_chunk = ide_source_snippet_get_index (self, &iter);
+  self->current_chunk = ide_snippet_get_index (self, &iter);
 
   return TRUE;
 }
 
 static void
-ide_source_snippet_get_nth_chunk_range (IdeSourceSnippet *self,
+ide_snippet_get_nth_chunk_range (IdeSnippet *self,
                                         gint              n,
                                         GtkTextIter      *begin,
                                         GtkTextIter      *end)
@@ -396,7 +396,7 @@ ide_source_snippet_get_nth_chunk_range (IdeSourceSnippet *self,
   gint run;
   gint i;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (n >= 0);
   g_return_if_fail (begin);
   g_return_if_fail (end);
@@ -415,16 +415,16 @@ ide_source_snippet_get_nth_chunk_range (IdeSourceSnippet *self,
 }
 
 void
-ide_source_snippet_get_chunk_range (IdeSourceSnippet      *self,
-                                    IdeSourceSnippetChunk *chunk,
+ide_snippet_get_chunk_range (IdeSnippet      *self,
+                                    IdeSnippetChunk *chunk,
                                     GtkTextIter           *begin,
                                     GtkTextIter           *end)
 {
-  IdeSourceSnippetChunk *item;
+  IdeSnippetChunk *item;
   guint i;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
 
   for (i = 0; i < self->chunks->len; i++)
     {
@@ -432,7 +432,7 @@ ide_source_snippet_get_chunk_range (IdeSourceSnippet      *self,
 
       if (item == chunk)
         {
-          ide_source_snippet_get_nth_chunk_range (self, i, begin, end);
+          ide_snippet_get_nth_chunk_range (self, i, begin, end);
           return;
         }
     }
@@ -441,7 +441,7 @@ ide_source_snippet_get_chunk_range (IdeSourceSnippet      *self,
 }
 
 static void
-ide_source_snippet_select_chunk (IdeSourceSnippet *self,
+ide_snippet_select_chunk (IdeSnippet *self,
                                  gint              n)
 {
   GtkTextIter begin;
@@ -449,11 +449,11 @@ ide_source_snippet_select_chunk (IdeSourceSnippet *self,
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (n >= 0);
   g_return_if_fail ((guint)n < self->runs->len);
 
-  ide_source_snippet_get_nth_chunk_range (self, n, &begin, &end);
+  ide_snippet_get_nth_chunk_range (self, n, &begin, &end);
 
   gtk_text_iter_order (&begin, &end);
 
@@ -486,13 +486,13 @@ ide_source_snippet_select_chunk (IdeSourceSnippet *self,
 }
 
 gboolean
-ide_source_snippet_move_next (IdeSourceSnippet *self)
+ide_snippet_move_next (IdeSnippet *self)
 {
   GtkTextIter iter;
 
   IDE_ENTRY;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), FALSE);
 
   if (self->tab_stop > self->max_tab_stop)
     IDE_RETURN (FALSE);
@@ -501,22 +501,22 @@ ide_source_snippet_move_next (IdeSourceSnippet *self)
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
 
-      if (ide_source_snippet_chunk_get_tab_stop (chunk) == self->tab_stop)
+      if (ide_snippet_chunk_get_tab_stop (chunk) == self->tab_stop)
         {
-          ide_source_snippet_select_chunk (self, i);
+          ide_snippet_select_chunk (self, i);
           IDE_RETURN (TRUE);
         }
     }
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
 
-      if (ide_source_snippet_chunk_get_tab_stop (chunk) == 0)
+      if (ide_snippet_chunk_get_tab_stop (chunk) == 0)
         {
-          ide_source_snippet_select_chunk (self, i);
+          ide_snippet_select_chunk (self, i);
           IDE_RETURN (FALSE);
         }
     }
@@ -531,21 +531,21 @@ ide_source_snippet_move_next (IdeSourceSnippet *self)
 }
 
 gboolean
-ide_source_snippet_move_previous (IdeSourceSnippet *self)
+ide_snippet_move_previous (IdeSnippet *self)
 {
   IDE_ENTRY;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), FALSE);
 
   self->tab_stop = MAX (1, self->tab_stop - 1);
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
 
-      if (ide_source_snippet_chunk_get_tab_stop (chunk) == self->tab_stop)
+      if (ide_snippet_chunk_get_tab_stop (chunk) == self->tab_stop)
         {
-          ide_source_snippet_select_chunk (self, i);
+          ide_snippet_select_chunk (self, i);
           IDE_RETURN (TRUE);
         }
     }
@@ -556,51 +556,51 @@ ide_source_snippet_move_previous (IdeSourceSnippet *self)
 }
 
 static void
-ide_source_snippet_update_context (IdeSourceSnippet *self)
+ide_snippet_update_context (IdeSnippet *self)
 {
-  IdeSourceSnippetContext *context;
+  IdeSnippetContext *context;
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
-  context = ide_source_snippet_get_context (self);
+  context = ide_snippet_get_context (self);
 
-  ide_source_snippet_context_emit_changed (context);
+  ide_snippet_context_emit_changed (context);
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk;
+      IdeSnippetChunk *chunk;
       gint tab_stop;
 
       chunk = g_ptr_array_index (self->chunks, i);
-      tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk);
+      tab_stop = ide_snippet_chunk_get_tab_stop (chunk);
 
       if (tab_stop > 0)
         {
           const gchar *text;
 
-          if (NULL != (text = ide_source_snippet_chunk_get_text (chunk)))
+          if (NULL != (text = ide_snippet_chunk_get_text (chunk)))
             {
               gchar key[12];
 
               g_snprintf (key, sizeof key, "%d", tab_stop);
               key[sizeof key - 1] = '\0';
 
-              ide_source_snippet_context_add_variable (context, key, text);
+              ide_snippet_context_add_variable (context, key, text);
             }
         }
     }
 
-  ide_source_snippet_context_emit_changed (context);
+  ide_snippet_context_emit_changed (context);
 
   IDE_EXIT;
 }
 
 static void
-ide_source_snippet_clear_tags (IdeSourceSnippet *self)
+ide_snippet_clear_tags (IdeSnippet *self)
 {
-  g_assert (IDE_IS_SOURCE_SNIPPET (self));
+  g_assert (IDE_IS_SNIPPET (self));
 
   if (self->mark_begin != NULL && self->mark_end != NULL)
     {
@@ -620,28 +620,28 @@ ide_source_snippet_clear_tags (IdeSourceSnippet *self)
 }
 
 static void
-ide_source_snippet_update_tags (IdeSourceSnippet *self)
+ide_snippet_update_tags (IdeSnippet *self)
 {
   GtkTextBuffer *buffer;
   guint i;
 
-  g_assert (IDE_IS_SOURCE_SNIPPET (self));
+  g_assert (IDE_IS_SNIPPET (self));
 
-  ide_source_snippet_clear_tags (self);
+  ide_snippet_clear_tags (self);
 
   buffer = gtk_text_mark_get_buffer (self->mark_begin);
 
   for (i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
-      gint tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      gint tab_stop = ide_snippet_chunk_get_tab_stop (chunk);
 
       if (tab_stop >= 0)
         {
           GtkTextIter begin;
           GtkTextIter end;
 
-          ide_source_snippet_get_chunk_range (self, chunk, &begin, &end);
+          ide_snippet_get_chunk_range (self, chunk, &begin, &end);
           gtk_text_buffer_apply_tag_by_name (buffer,
                                              TAG_SNIPPET_TAB_STOP,
                                              &begin, &end);
@@ -650,14 +650,14 @@ ide_source_snippet_update_tags (IdeSourceSnippet *self)
 }
 
 gboolean
-ide_source_snippet_begin (IdeSourceSnippet *self,
+ide_snippet_begin (IdeSnippet *self,
                           GtkTextBuffer    *buffer,
                           GtkTextIter      *iter)
 {
-  IdeSourceSnippetContext *context;
+  IdeSnippetContext *context;
   gboolean ret;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), FALSE);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), FALSE);
   g_return_val_if_fail (!self->buffer, FALSE);
   g_return_val_if_fail (!self->mark_begin, FALSE);
   g_return_val_if_fail (!self->mark_end, FALSE);
@@ -666,11 +666,11 @@ ide_source_snippet_begin (IdeSourceSnippet *self,
 
   self->inserted = TRUE;
 
-  context = ide_source_snippet_get_context (self);
+  context = ide_snippet_get_context (self);
 
-  ide_source_snippet_update_context (self);
-  ide_source_snippet_context_emit_changed (context);
-  ide_source_snippet_update_context (self);
+  ide_snippet_update_context (self);
+  ide_snippet_context_emit_changed (context);
+  ide_snippet_update_context (self);
 
   self->buffer = g_object_ref (buffer);
   self->mark_begin = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE);
@@ -681,12 +681,12 @@ ide_source_snippet_begin (IdeSourceSnippet *self,
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk;
+      IdeSnippetChunk *chunk;
       const gchar *text;
 
       chunk = g_ptr_array_index (self->chunks, i);
 
-      if ((text = ide_source_snippet_chunk_get_text (chunk)))
+      if ((text = ide_snippet_chunk_get_text (chunk)))
         {
           gint len;
 
@@ -705,19 +705,19 @@ ide_source_snippet_begin (IdeSourceSnippet *self,
 
   gtk_text_buffer_end_user_action (buffer);
 
-  ide_source_snippet_update_tags (self);
+  ide_snippet_update_tags (self);
 
-  ret = ide_source_snippet_move_next (self);
+  ret = ide_snippet_move_next (self);
 
   return ret;
 }
 
 void
-ide_source_snippet_finish (IdeSourceSnippet *self)
+ide_snippet_finish (IdeSnippet *self)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
-  ide_source_snippet_clear_tags (self);
+  ide_snippet_clear_tags (self);
 
   g_clear_object (&self->mark_begin);
   g_clear_object (&self->mark_end);
@@ -725,37 +725,37 @@ ide_source_snippet_finish (IdeSourceSnippet *self)
 }
 
 void
-ide_source_snippet_pause (IdeSourceSnippet *self)
+ide_snippet_pause (IdeSnippet *self)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 }
 
 void
-ide_source_snippet_unpause (IdeSourceSnippet *self)
+ide_snippet_unpause (IdeSnippet *self)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 }
 
 void
-ide_source_snippet_add_chunk (IdeSourceSnippet      *self,
-                              IdeSourceSnippetChunk *chunk)
+ide_snippet_add_chunk (IdeSnippet      *self,
+                              IdeSnippetChunk *chunk)
 {
   gint tab_stop;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET_CHUNK (chunk));
   g_return_if_fail (!self->inserted);
 
   g_ptr_array_add (self->chunks, g_object_ref (chunk));
 
-  ide_source_snippet_chunk_set_context (chunk, self->snippet_context);
+  ide_snippet_chunk_set_context (chunk, self->snippet_context);
 
-  tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk);
+  tab_stop = ide_snippet_chunk_get_tab_stop (chunk);
   self->max_tab_stop = MAX (self->max_tab_stop, tab_stop);
 }
 
 gchar *
-ide_source_snippet_get_nth_text (IdeSourceSnippet *self,
+ide_snippet_get_nth_text (IdeSnippet *self,
                                  gint              n)
 {
   GtkTextIter iter;
@@ -763,7 +763,7 @@ ide_source_snippet_get_nth_text (IdeSourceSnippet *self,
   gchar *ret;
   gint i;
 
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
   g_return_val_if_fail (n >= 0, NULL);
 
   gtk_text_buffer_get_iter_at_mark (self->buffer, &iter, self->mark_begin);
@@ -780,7 +780,7 @@ ide_source_snippet_get_nth_text (IdeSourceSnippet *self,
 }
 
 static void
-ide_source_snippet_replace_chunk_text (IdeSourceSnippet *self,
+ide_snippet_replace_chunk_text (IdeSnippet *self,
                                        gint              n,
                                        const gchar      *text)
 {
@@ -788,7 +788,7 @@ ide_source_snippet_replace_chunk_text (IdeSourceSnippet *self,
   GtkTextIter end;
   gint diff = 0;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (n >= 0);
   g_return_if_fail (text);
 
@@ -799,7 +799,7 @@ ide_source_snippet_replace_chunk_text (IdeSourceSnippet *self,
    * can be helpful.
    */
 
-  ide_source_snippet_get_nth_chunk_range (self, n, &begin, &end);
+  ide_snippet_get_nth_chunk_range (self, n, &begin, &end);
 
   if (!gtk_text_iter_equal (&begin, &end))
     {
@@ -824,26 +824,26 @@ ide_source_snippet_replace_chunk_text (IdeSourceSnippet *self,
 }
 
 static void
-ide_source_snippet_rewrite_updated_chunks (IdeSourceSnippet *self)
+ide_snippet_rewrite_updated_chunks (IdeSnippet *self)
 {
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
       g_autofree gchar *real_text = NULL;
       const gchar *text;
 
-      text = ide_source_snippet_chunk_get_text (chunk);
-      real_text = ide_source_snippet_get_nth_text (self, i);
+      text = ide_snippet_chunk_get_text (chunk);
+      real_text = ide_snippet_get_nth_text (self, i);
 
       if (!dzl_str_equal0 (text, real_text))
-        ide_source_snippet_replace_chunk_text (self, i, text);
+        ide_snippet_replace_chunk_text (self, i, text);
     }
 }
 
 void
-ide_source_snippet_before_insert_text (IdeSourceSnippet *self,
+ide_snippet_before_insert_text (IdeSnippet *self,
                                        GtkTextBuffer    *buffer,
                                        GtkTextIter      *iter,
                                        gchar            *text,
@@ -854,12 +854,12 @@ ide_source_snippet_before_insert_text (IdeSourceSnippet *self,
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (self->current_chunk >= 0);
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
   g_return_if_fail (iter);
 
-  n = ide_source_snippet_get_index (self, iter);
+  n = ide_snippet_get_index (self, iter);
   utf8_len = g_utf8_strlen (text, len);
   g_array_index (self->runs, gint, n) += utf8_len;
 
@@ -874,51 +874,51 @@ ide_source_snippet_before_insert_text (IdeSourceSnippet *self,
 }
 
 void
-ide_source_snippet_after_insert_text (IdeSourceSnippet *self,
+ide_snippet_after_insert_text (IdeSnippet *self,
                                       GtkTextBuffer    *buffer,
                                       GtkTextIter      *iter,
                                       gchar            *text,
                                       gint              len)
 {
-  IdeSourceSnippetChunk *chunk;
+  IdeSnippetChunk *chunk;
   GtkTextMark *here;
   gchar *new_text;
   gint n;
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (self->current_chunk >= 0);
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
   g_return_if_fail (iter);
 
-  n = ide_source_snippet_get_index (self, iter);
+  n = ide_snippet_get_index (self, iter);
   chunk = g_ptr_array_index (self->chunks, n);
-  new_text = ide_source_snippet_get_nth_text (self, n);
-  ide_source_snippet_chunk_set_text (chunk, new_text);
-  ide_source_snippet_chunk_set_text_set (chunk, TRUE);
+  new_text = ide_snippet_get_nth_text (self, n);
+  ide_snippet_chunk_set_text (chunk, new_text);
+  ide_snippet_chunk_set_text_set (chunk, TRUE);
   g_free (new_text);
 
   here = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE);
 
-  ide_source_snippet_update_context (self);
-  ide_source_snippet_update_context (self);
-  ide_source_snippet_rewrite_updated_chunks (self);
+  ide_snippet_update_context (self);
+  ide_snippet_update_context (self);
+  ide_snippet_rewrite_updated_chunks (self);
 
   gtk_text_buffer_get_iter_at_mark (buffer, iter, here);
   gtk_text_buffer_delete_mark (buffer, here);
 
-  ide_source_snippet_update_tags (self);
+  ide_snippet_update_tags (self);
 
 #if 0
-  ide_source_snippet_context_dump (self->snippet_context);
+  ide_snippet_context_dump (self->snippet_context);
 #endif
 
   IDE_EXIT;
 }
 
 void
-ide_source_snippet_before_delete_range (IdeSourceSnippet *self,
+ide_snippet_before_delete_range (IdeSnippet *self,
                                         GtkTextBuffer    *buffer,
                                         GtkTextIter      *begin,
                                         GtkTextIter      *end)
@@ -932,14 +932,14 @@ ide_source_snippet_before_delete_range (IdeSourceSnippet *self,
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
   g_return_if_fail (begin);
   g_return_if_fail (end);
 
   len = gtk_text_iter_get_offset (end) - gtk_text_iter_get_offset (begin);
 
-  n = ide_source_snippet_get_index (self, begin);
+  n = ide_snippet_get_index (self, begin);
   if (n < 0)
     IDE_EXIT;
 
@@ -969,12 +969,12 @@ ide_source_snippet_before_delete_range (IdeSourceSnippet *self,
 
   for (i = lower_bound; i <= upper_bound; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
       g_autofree gchar *new_text = NULL;
 
-      new_text = ide_source_snippet_get_nth_text (self, i);
-      ide_source_snippet_chunk_set_text (chunk, new_text);
-      ide_source_snippet_chunk_set_text_set (chunk, TRUE);
+      new_text = ide_snippet_get_nth_text (self, i);
+      ide_snippet_chunk_set_text (chunk, new_text);
+      ide_snippet_chunk_set_text_set (chunk, TRUE);
     }
 
 #if 0
@@ -988,7 +988,7 @@ ide_source_snippet_before_delete_range (IdeSourceSnippet *self,
 }
 
 void
-ide_source_snippet_after_delete_range (IdeSourceSnippet *self,
+ide_snippet_after_delete_range (IdeSnippet *self,
                                        GtkTextBuffer    *buffer,
                                        GtkTextIter      *begin,
                                        GtkTextIter      *end)
@@ -997,33 +997,33 @@ ide_source_snippet_after_delete_range (IdeSourceSnippet *self,
 
   IDE_ENTRY;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
   g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
   g_return_if_fail (begin);
   g_return_if_fail (end);
 
   here = gtk_text_buffer_create_mark (buffer, NULL, begin, TRUE);
 
-  ide_source_snippet_update_context (self);
-  ide_source_snippet_update_context (self);
-  ide_source_snippet_rewrite_updated_chunks (self);
+  ide_snippet_update_context (self);
+  ide_snippet_update_context (self);
+  ide_snippet_rewrite_updated_chunks (self);
 
   gtk_text_buffer_get_iter_at_mark (buffer, begin, here);
   gtk_text_buffer_get_iter_at_mark (buffer, end, here);
   gtk_text_buffer_delete_mark (buffer, here);
 
-  ide_source_snippet_update_tags (self);
+  ide_snippet_update_tags (self);
 
 #if 0
-  ide_source_snippet_context_dump (self->snippet_context);
+  ide_snippet_context_dump (self->snippet_context);
 #endif
 
   IDE_EXIT;
 }
 
 /**
- * ide_source_snippet_get_mark_begin:
- * @self: an #IdeSourceSnippet
+ * ide_snippet_get_mark_begin:
+ * @self: an #IdeSnippet
  *
  * Gets the begin text mark, which is only set when the snippet is
  * actively being edited.
@@ -1031,16 +1031,16 @@ ide_source_snippet_after_delete_range (IdeSourceSnippet *self,
  * Returns: (transfer none) (nullable): a #GtkTextMark or %NULL
  */
 GtkTextMark *
-ide_source_snippet_get_mark_begin (IdeSourceSnippet *self)
+ide_snippet_get_mark_begin (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
   return self->mark_begin;
 }
 
 /**
- * ide_source_snippet_get_mark_end:
- * @self: an #IdeSourceSnippet
+ * ide_snippet_get_mark_end:
+ * @self: an #IdeSnippet
  *
  * Gets the end text mark, which is only set when the snippet is
  * actively being edited.
@@ -1048,37 +1048,37 @@ ide_source_snippet_get_mark_begin (IdeSourceSnippet *self)
  * Returns: (transfer none) (nullable): a #GtkTextMark or %NULL
  */
 GtkTextMark *
-ide_source_snippet_get_mark_end (IdeSourceSnippet *self)
+ide_snippet_get_mark_end (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
   return self->mark_end;
 }
 
 /**
- * ide_source_snippet_get_context:
- * @self: an #IdeSourceSnippet
+ * ide_snippet_get_context:
+ * @self: an #IdeSnippet
  *
  * Get's the context used for expanding the snippet.
  *
- * Returns: (nullable) (transfer none): an #IdeSourceSnippetContext
+ * Returns: (nullable) (transfer none): an #IdeSnippetContext
  */
-IdeSourceSnippetContext *
-ide_source_snippet_get_context (IdeSourceSnippet *self)
+IdeSnippetContext *
+ide_snippet_get_context (IdeSnippet *self)
 {
-  g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL);
+  g_return_val_if_fail (IDE_IS_SNIPPET (self), NULL);
 
   if (!self->snippet_context)
     {
-      IdeSourceSnippetChunk *chunk;
+      IdeSnippetChunk *chunk;
       guint i;
 
-      self->snippet_context = ide_source_snippet_context_new ();
+      self->snippet_context = ide_snippet_context_new ();
 
       for (i = 0; i < self->chunks->len; i++)
         {
           chunk = g_ptr_array_index (self->chunks, i);
-          ide_source_snippet_chunk_set_context (chunk, self->snippet_context);
+          ide_snippet_chunk_set_context (chunk, self->snippet_context);
         }
     }
 
@@ -1086,9 +1086,9 @@ ide_source_snippet_get_context (IdeSourceSnippet *self)
 }
 
 static void
-ide_source_snippet_dispose (GObject *object)
+ide_snippet_dispose (GObject *object)
 {
-  IdeSourceSnippet *self = (IdeSourceSnippet *)object;
+  IdeSnippet *self = (IdeSnippet *)object;
 
   if (self->mark_begin)
     {
@@ -1112,30 +1112,30 @@ ide_source_snippet_dispose (GObject *object)
   g_clear_object (&self->buffer);
   g_clear_object (&self->snippet_context);
 
-  G_OBJECT_CLASS (ide_source_snippet_parent_class)->dispose (object);
+  G_OBJECT_CLASS (ide_snippet_parent_class)->dispose (object);
 }
 
 static void
-ide_source_snippet_finalize (GObject *object)
+ide_snippet_finalize (GObject *object)
 {
-  IdeSourceSnippet *self = (IdeSourceSnippet *)object;
+  IdeSnippet *self = (IdeSnippet *)object;
 
   g_clear_pointer (&self->description, g_free);
   g_clear_pointer (&self->trigger, g_free);
   g_clear_object (&self->buffer);
 
-  G_OBJECT_CLASS (ide_source_snippet_parent_class)->finalize (object);
+  G_OBJECT_CLASS (ide_snippet_parent_class)->finalize (object);
 
   DZL_COUNTER_DEC (instances);
 }
 
 static void
-ide_source_snippet_get_property (GObject    *object,
+ide_snippet_get_property (GObject    *object,
                                  guint       prop_id,
                                  GValue     *value,
                                  GParamSpec *pspec)
 {
-  IdeSourceSnippet *self = IDE_SOURCE_SNIPPET (object);
+  IdeSnippet *self = IDE_SNIPPET (object);
 
   switch (prop_id)
     {
@@ -1173,25 +1173,25 @@ ide_source_snippet_get_property (GObject    *object,
 }
 
 static void
-ide_source_snippet_set_property (GObject      *object,
+ide_snippet_set_property (GObject      *object,
                                  guint         prop_id,
                                  const GValue *value,
                                  GParamSpec   *pspec)
 {
-  IdeSourceSnippet *self = IDE_SOURCE_SNIPPET (object);
+  IdeSnippet *self = IDE_SNIPPET (object);
 
   switch (prop_id)
     {
     case PROP_TRIGGER:
-      ide_source_snippet_set_trigger (self, g_value_get_string (value));
+      ide_snippet_set_trigger (self, g_value_get_string (value));
       break;
 
     case PROP_LANGUAGE:
-      ide_source_snippet_set_language (self, g_value_get_string (value));
+      ide_snippet_set_language (self, g_value_get_string (value));
       break;
 
     case PROP_DESCRIPTION:
-      ide_source_snippet_set_description (self, g_value_get_string (value));
+      ide_snippet_set_description (self, g_value_get_string (value));
       break;
 
     default:
@@ -1200,14 +1200,14 @@ ide_source_snippet_set_property (GObject      *object,
 }
 
 static void
-ide_source_snippet_class_init (IdeSourceSnippetClass *klass)
+ide_snippet_class_init (IdeSnippetClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->dispose = ide_source_snippet_dispose;
-  object_class->finalize = ide_source_snippet_finalize;
-  object_class->get_property = ide_source_snippet_get_property;
-  object_class->set_property = ide_source_snippet_set_property;
+  object_class->dispose = ide_snippet_dispose;
+  object_class->finalize = ide_snippet_finalize;
+  object_class->get_property = ide_snippet_get_property;
+  object_class->set_property = ide_snippet_set_property;
 
   properties[PROP_BUFFER] =
     g_param_spec_object ("buffer",
@@ -1264,7 +1264,7 @@ ide_source_snippet_class_init (IdeSourceSnippetClass *klass)
 }
 
 static void
-ide_source_snippet_init (IdeSourceSnippet *self)
+ide_snippet_init (IdeSnippet *self)
 {
   DZL_COUNTER_INC (instances);
 
@@ -1274,18 +1274,18 @@ ide_source_snippet_init (IdeSourceSnippet *self)
 }
 
 /**
- * ide_source_snippet_dump:
- * @self: a #IdeSourceSnippet
+ * ide_snippet_dump:
+ * @self: a #IdeSnippet
  *
  * This is a debugging function to print information about a chunk to stderr.
  * Plugin developers might use this to track down issues when using a snippet.
  */
 void
-ide_source_snippet_dump (IdeSourceSnippet *self)
+ide_snippet_dump (IdeSnippet *self)
 {
   guint offset = 0;
 
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self));
+  g_return_if_fail (IDE_IS_SNIPPET (self));
 
   /* For debugging purposes */
 
@@ -1296,24 +1296,24 @@ ide_source_snippet_dump (IdeSourceSnippet *self)
 
   for (guint i = 0; i < self->chunks->len; i++)
     {
-      IdeSourceSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
+      IdeSnippetChunk *chunk = g_ptr_array_index (self->chunks, i);
       g_autofree gchar *spec_escaped = NULL;
       g_autofree gchar *text_escaped = NULL;
       const gchar *spec;
       const gchar *text;
       gint run_length = g_array_index (self->runs, gint, i);
 
-      g_assert (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk));
+      g_assert (IDE_IS_SNIPPET_CHUNK (chunk));
 
-      text = ide_source_snippet_chunk_get_text (chunk);
+      text = ide_snippet_chunk_get_text (chunk);
       text_escaped = g_strescape (text, NULL);
 
-      spec = ide_source_snippet_chunk_get_spec (chunk);
+      spec = ide_snippet_chunk_get_spec (chunk);
       spec_escaped = g_strescape (spec, NULL);
 
       g_printerr ("  Chunk(nth=%d, tab_stop=%d, position=%d (%d), spec=%s, text=%s)\n",
                   i,
-                  ide_source_snippet_chunk_get_tab_stop (chunk),
+                  ide_snippet_chunk_get_tab_stop (chunk),
                   offset, run_length,
                   spec_escaped,
                   text_escaped);
diff --git a/src/libide/snippets/ide-snippet.h b/src/libide/snippets/ide-snippet.h
new file mode 100644
index 000000000..7de541a85
--- /dev/null
+++ b/src/libide/snippets/ide-snippet.h
@@ -0,0 +1,71 @@
+/* ide-snippet.h
+ *
+ * Copyright 2013 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/>.
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "ide-snippet-chunk.h"
+#include "ide-version-macros.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_SNIPPET (ide_snippet_get_type())
+
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (IdeSnippet, ide_snippet, IDE, SNIPPET, GObject)
+
+IDE_AVAILABLE_IN_ALL
+IdeSnippet              *ide_snippet_new              (const gchar     *trigger,
+                                                       const gchar     *language);
+IDE_AVAILABLE_IN_ALL
+IdeSnippet              *ide_snippet_copy             (IdeSnippet      *self);
+IDE_AVAILABLE_IN_ALL
+const gchar             *ide_snippet_get_trigger      (IdeSnippet      *self);
+IDE_AVAILABLE_IN_ALL
+void                     ide_snippet_set_trigger      (IdeSnippet      *self,
+                                                       const gchar     *trigger);
+IDE_AVAILABLE_IN_ALL
+const gchar             *ide_snippet_get_language     (IdeSnippet      *self);
+IDE_AVAILABLE_IN_ALL
+void                     ide_snippet_set_language     (IdeSnippet      *self,
+                                                       const gchar     *language);
+IDE_AVAILABLE_IN_ALL
+const gchar             *ide_snippet_get_description  (IdeSnippet      *self);
+IDE_AVAILABLE_IN_ALL
+void                     ide_snippet_set_description  (IdeSnippet      *self,
+                                                       const gchar     *description);
+IDE_AVAILABLE_IN_ALL
+void                     ide_snippet_add_chunk        (IdeSnippet      *self,
+                                                       IdeSnippetChunk *chunk);
+IDE_AVAILABLE_IN_ALL
+guint                    ide_snippet_get_n_chunks     (IdeSnippet      *self);
+IDE_AVAILABLE_IN_ALL
+gint                     ide_snippet_get_tab_stop     (IdeSnippet      *self);
+IDE_AVAILABLE_IN_ALL
+IdeSnippetChunk         *ide_snippet_get_nth_chunk    (IdeSnippet      *self,
+                                                       guint            n);
+IDE_AVAILABLE_IN_ALL
+void                     ide_snippet_get_chunk_range  (IdeSnippet      *self,
+                                                       IdeSnippetChunk *chunk,
+                                                       GtkTextIter     *begin,
+                                                       GtkTextIter     *end);
+IDE_AVAILABLE_IN_ALL
+IdeSnippetContext       *ide_snippet_get_context      (IdeSnippet      *self);
+
+G_END_DECLS
diff --git a/src/libide/snippets/meson.build b/src/libide/snippets/meson.build
index 2ef8784c6..dfb7d2612 100644
--- a/src/libide/snippets/meson.build
+++ b/src/libide/snippets/meson.build
@@ -1,27 +1,23 @@
 snippets_headers = [
-  'ide-source-snippet-chunk.h',
-  'ide-source-snippet-context.h',
-  'ide-source-snippet.h',
-  'ide-source-snippets-manager.h',
-  'ide-source-snippets.h',
+  'ide-snippet-chunk.h',
+  'ide-snippet-context.h',
+  'ide-snippet-model.h',
+  'ide-snippet-storage.h',
+  'ide-snippet.h',
 ]
 
 snippets_sources = [
-  'ide-source-snippet-chunk.c',
-  'ide-source-snippet-context.c',
-  'ide-source-snippet.c',
-  'ide-source-snippets-manager.c',
-  'ide-source-snippets.c',
+  'ide-snippet-parser.h',
+  'ide-snippet-private.h',
 ]
 
 snippets_private_sources = [
-  'ide-source-snippet-completion-item.c',
-  'ide-source-snippet-completion-item.h',
-  'ide-source-snippet-completion-provider.c',
-  'ide-source-snippet-completion-provider.h',
-  'ide-source-snippet-parser.c',
-  'ide-source-snippet-parser.h',
-  'ide-source-snippet-private.h',
+  'ide-snippet.c',
+  'ide-snippet-chunk.c',
+  'ide-snippet-context.c',
+  'ide-snippet-model.c',
+  'ide-snippet-parser.c',
+  'ide-snippet-storage.c',
 ]
 
 libide_public_headers += files(snippets_headers)
diff --git a/src/libide/sourceview/ide-source-view.c b/src/libide/sourceview/ide-source-view.c
index 68cf7c2d0..f6e184b43 100644
--- a/src/libide/sourceview/ide-source-view.c
+++ b/src/libide/sourceview/ide-source-view.c
@@ -44,11 +44,10 @@
 #include "plugins/ide-extension-adapter.h"
 #include "plugins/ide-extension-set-adapter.h"
 #include "rename/ide-rename-provider.h"
-#include "snippets/ide-source-snippet-chunk.h"
-#include "snippets/ide-source-snippet-context.h"
-#include "snippets/ide-source-snippet-private.h"
-#include "snippets/ide-source-snippet.h"
-#include "snippets/ide-source-snippets-manager.h"
+#include "snippets/ide-snippet-chunk.h"
+#include "snippets/ide-snippet-context.h"
+#include "snippets/ide-snippet-private.h"
+#include "snippets/ide-snippet.h"
 #include "sourceview/ide-cursor.h"
 #include "sourceview/ide-indenter.h"
 #include "sourceview/ide-omni-gutter-renderer.h"
@@ -975,7 +974,7 @@ ide_source_view__buffer_insert_text_cb (IdeSourceView *self,
                                         GtkTextBuffer *buffer)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (iter != NULL);
@@ -990,7 +989,7 @@ ide_source_view__buffer_insert_text_cb (IdeSourceView *self,
   if (NULL != (snippet = g_queue_peek_head (priv->snippets)))
     {
       ide_source_view_block_handlers (self);
-      ide_source_snippet_before_insert_text (snippet, buffer, iter, text, len);
+      ide_snippet_before_insert_text (snippet, buffer, iter, text, len);
       ide_source_view_unblock_handlers (self);
     }
 }
@@ -1003,7 +1002,7 @@ ide_source_view__buffer_insert_text_after_cb (IdeSourceView *self,
                                               GtkTextBuffer *buffer)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
   GtkTextIter insert;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
@@ -1020,11 +1019,11 @@ ide_source_view__buffer_insert_text_after_cb (IdeSourceView *self,
       GtkTextMark *end;
 
       ide_source_view_block_handlers (self);
-      ide_source_snippet_after_insert_text (snippet, buffer, iter, text, len);
+      ide_snippet_after_insert_text (snippet, buffer, iter, text, len);
       ide_source_view_unblock_handlers (self);
 
-      begin = ide_source_snippet_get_mark_begin (snippet);
-      end = ide_source_snippet_get_mark_end (snippet);
+      begin = ide_snippet_get_mark_begin (snippet);
+      end = ide_snippet_get_mark_end (snippet);
       ide_source_view_invalidate_range_mark (self, begin, end);
     }
 
@@ -1060,7 +1059,7 @@ ide_source_view__buffer_delete_range_cb (IdeSourceView *self,
                                          GtkTextBuffer *buffer)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
 
   IDE_ENTRY;
 
@@ -1073,11 +1072,11 @@ ide_source_view__buffer_delete_range_cb (IdeSourceView *self,
       GtkTextMark *end_mark;
 
       ide_source_view_block_handlers (self);
-      ide_source_snippet_before_delete_range (snippet, buffer, begin, end);
+      ide_snippet_before_delete_range (snippet, buffer, begin, end);
       ide_source_view_unblock_handlers (self);
 
-      begin_mark = ide_source_snippet_get_mark_begin (snippet);
-      end_mark = ide_source_snippet_get_mark_end (snippet);
+      begin_mark = ide_snippet_get_mark_begin (snippet);
+      end_mark = ide_snippet_get_mark_end (snippet);
       ide_source_view_invalidate_range_mark (self, begin_mark, end_mark);
     }
 
@@ -1091,7 +1090,7 @@ ide_source_view__buffer_delete_range_after_cb (IdeSourceView *self,
                                                GtkTextBuffer *buffer)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
 
   IDE_ENTRY;
 
@@ -1101,7 +1100,7 @@ ide_source_view__buffer_delete_range_after_cb (IdeSourceView *self,
   ide_source_view_block_handlers (self);
 
   if (NULL != (snippet = g_queue_peek_head (priv->snippets)))
-    ide_source_snippet_after_delete_range (snippet, buffer, begin, end);
+    ide_snippet_after_delete_range (snippet, buffer, begin, end);
 
   ide_source_view_unblock_handlers (self);
 
@@ -1115,7 +1114,7 @@ ide_source_view__buffer_mark_set_cb (IdeSourceView *self,
                                      GtkTextBuffer *buffer)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
   GtkTextMark *insert;
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
@@ -1129,7 +1128,7 @@ ide_source_view__buffer_mark_set_cb (IdeSourceView *self,
     {
       ide_source_view_block_handlers (self);
       while (NULL != (snippet = g_queue_peek_head (priv->snippets)) &&
-             !ide_source_snippet_insert_set (snippet, mark))
+             !ide_snippet_insert_set (snippet, mark))
         ide_source_view_pop_snippet (self);
       ide_source_view_unblock_handlers (self);
     }
@@ -2003,7 +2002,7 @@ ide_source_view_key_press_event (GtkWidget   *widget,
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
   GtkTextBuffer *buffer;
   GtkTextMark *insert;
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
   gboolean ret = FALSE;
   guint change_sequence;
 
@@ -2079,7 +2078,7 @@ ide_source_view_key_press_event (GtkWidget   *widget,
           if ((event->state & GDK_SHIFT_MASK) == 0)
             {
               ide_source_view_block_handlers (self);
-              if (!ide_source_snippet_move_next (snippet))
+              if (!ide_snippet_move_next (snippet))
                 ide_source_view_pop_snippet (self);
               ide_source_view_scroll_to_insert (self);
               ide_source_view_unblock_handlers (self);
@@ -2089,7 +2088,7 @@ ide_source_view_key_press_event (GtkWidget   *widget,
           /* Fallthrough */
         case GDK_KEY_ISO_Left_Tab:
           ide_source_view_block_handlers (self);
-          ide_source_snippet_move_previous (snippet);
+          ide_snippet_move_previous (snippet);
           ide_source_view_scroll_to_insert (self);
           ide_source_view_unblock_handlers (self);
           ret = TRUE;
@@ -3626,22 +3625,22 @@ ide_source_view_real_push_selection (IdeSourceView *self)
 
 static void
 ide_source_view_real_push_snippet (IdeSourceView           *self,
-                                   IdeSourceSnippet        *snippet,
+                                   IdeSnippet        *snippet,
                                    const GtkTextIter       *location)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
   IdeContext *ide_context;
-  IdeSourceSnippetContext *context;
+  IdeSnippetContext *context;
   IdeFile *file;
   GFile *gfile = NULL;
   g_autoptr(GFile) gparentfile = NULL;
 
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
-  g_assert (IDE_IS_SOURCE_SNIPPET (snippet));
+  g_assert (IDE_IS_SNIPPET (snippet));
   g_assert (location != NULL);
 
-  context = ide_source_snippet_get_context (snippet);
+  context = ide_snippet_get_context (snippet);
 
   if (priv->buffer != NULL)
     {
@@ -3656,9 +3655,9 @@ ide_source_view_real_push_snippet (IdeSourceView           *self,
           gparentfile = g_file_get_parent(gfile);
           dirname = g_file_get_path (gparentfile);
           path = g_file_get_path (gfile);
-          ide_source_snippet_context_add_variable (context, "filename", name);
-          ide_source_snippet_context_add_variable (context, "dirname", dirname);
-          ide_source_snippet_context_add_variable (context, "path", path);
+          ide_snippet_context_add_variable (context, "filename", name);
+          ide_snippet_context_add_variable (context, "dirname", dirname);
+          ide_snippet_context_add_variable (context, "path", path);
         }
 
       if ((ide_context = ide_buffer_get_context (priv->buffer)))
@@ -3673,13 +3672,13 @@ ide_source_view_real_push_snippet (IdeSourceView           *self,
             {
               g_autofree gchar *relative_path = NULL;
               relative_path = g_file_get_relative_path (workdir, gfile);
-              ide_source_snippet_context_add_variable (context, "relative_path", relative_path);
+              ide_snippet_context_add_variable (context, "relative_path", relative_path);
             }
           if (workdir && gparentfile)
             {
               g_autofree gchar *relative_dirname = NULL;
               relative_dirname = g_file_get_relative_path (workdir, gparentfile);
-              ide_source_snippet_context_add_variable (context, "relative_dirname", relative_dirname);
+              ide_snippet_context_add_variable (context, "relative_dirname", relative_dirname);
             }
 
           if ((vcs_config = ide_vcs_get_config (vcs)))
@@ -3692,9 +3691,9 @@ ide_source_view_real_push_snippet (IdeSourceView           *self,
 
               if (!dzl_str_empty0 (g_value_get_string (&value)))
                 {
-                  ide_source_snippet_context_add_shared_variable (context, "author", g_value_get_string 
(&value));
-                  ide_source_snippet_context_add_shared_variable (context, "fullname", g_value_get_string 
(&value));
-                  ide_source_snippet_context_add_shared_variable (context, "username", g_value_get_string 
(&value));
+                  ide_snippet_context_add_shared_variable (context, "author", g_value_get_string (&value));
+                  ide_snippet_context_add_shared_variable (context, "fullname", g_value_get_string (&value));
+                  ide_snippet_context_add_shared_variable (context, "username", g_value_get_string (&value));
                 }
 
               g_value_reset (&value);
@@ -3702,7 +3701,7 @@ ide_source_view_real_push_snippet (IdeSourceView           *self,
               ide_vcs_config_get_config (vcs_config, IDE_VCS_CONFIG_EMAIL, &value);
 
               if (!dzl_str_empty0 (g_value_get_string (&value)))
-                ide_source_snippet_context_add_shared_variable (context, "email", g_value_get_string 
(&value));
+                ide_snippet_context_add_shared_variable (context, "email", g_value_get_string (&value));
 
               g_value_unset (&value);
               g_object_unref (vcs_config);
@@ -3920,7 +3919,7 @@ ide_source_view_real_sort (IdeSourceView *self,
 static void
 ide_source_view_draw_snippet_background (IdeSourceView    *self,
                                          cairo_t          *cr,
-                                         IdeSourceSnippet *snippet,
+                                         IdeSnippet *snippet,
                                          gint              width)
 {
   GtkTextBuffer *buffer;
@@ -3934,12 +3933,12 @@ ide_source_view_draw_snippet_background (IdeSourceView    *self,
   g_assert (GTK_IS_TEXT_VIEW (text_view));
   g_assert (IDE_IS_SOURCE_VIEW (self));
   g_assert (cr);
-  g_assert (IDE_IS_SOURCE_SNIPPET (snippet));
+  g_assert (IDE_IS_SNIPPET (snippet));
 
   buffer = gtk_text_view_get_buffer (text_view);
 
-  mark_begin = ide_source_snippet_get_mark_begin (snippet);
-  mark_end = ide_source_snippet_get_mark_end (snippet);
+  mark_begin = ide_snippet_get_mark_begin (snippet);
+  mark_end = ide_snippet_get_mark_end (snippet);
 
   if (!mark_begin || !mark_end)
     return;
@@ -3977,7 +3976,7 @@ ide_source_view_draw_snippets_background (IdeSourceView *self,
 
   for (guint i = 0; i < priv->snippets->length; i++)
     {
-      IdeSourceSnippet *snippet = g_queue_peek_nth (priv->snippets, i);
+      IdeSnippet *snippet = g_queue_peek_nth (priv->snippets, i);
 
       ide_source_view_draw_snippet_background (self,
                                                cr,
@@ -6158,7 +6157,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
   /**
    * IdeSourceView::pop-snippet:
    * @self: An #IdeSourceView
-   * @snippet: An #IdeSourceSnippet.
+   * @snippet: An #IdeSnippet.
    *
    * Pops the current snippet from the sourceview if there is one.
    */
@@ -6190,7 +6189,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
   /**
    * IdeSourceView::push-snippet:
    * @self: An #IdeSourceView
-   * @snippet: An #IdeSourceSnippet.
+   * @snippet: An #IdeSnippet.
    * @iter: (allow-none): The location for the snippet, or %NULL.
    *
    * Pushes @snippet onto the snippet stack at either @iter or the insertion
@@ -6204,7 +6203,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
                                 NULL, NULL, NULL,
                                 G_TYPE_NONE,
                                 2,
-                                IDE_TYPE_SOURCE_SNIPPET,
+                                IDE_TYPE_SNIPPET,
                                 GTK_TYPE_TEXT_ITER | G_SIGNAL_TYPE_STATIC_SCOPE);
 
   signals [REBUILD_HIGHLIGHT] =
@@ -6850,19 +6849,19 @@ void
 ide_source_view_pop_snippet (IdeSourceView *self)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippet *snippet;
+  IdeSnippet *snippet;
 
   g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
 
   if ((snippet = g_queue_pop_head (priv->snippets)))
     {
-      ide_source_snippet_finish (snippet);
+      ide_snippet_finish (snippet);
       g_signal_emit (self, signals [POP_SNIPPET], 0, snippet);
       g_object_unref (snippet);
     }
 
   if ((snippet = g_queue_peek_head (priv->snippets)))
-    ide_source_snippet_unpause (snippet);
+    ide_snippet_unpause (snippet);
 
   ide_source_view_invalidate_window (self);
 }
@@ -6881,19 +6880,19 @@ ide_source_view_clear_snippets (IdeSourceView *self)
 /**
  * ide_source_view_push_snippet:
  * @self: An #IdeSourceView
- * @snippet: An #IdeSourceSnippet.
+ * @snippet: An #IdeSnippet.
  * @location: (allow-none): A location for the snippet or %NULL.
  *
  * Pushes a new snippet onto the source view.
  */
 void
 ide_source_view_push_snippet (IdeSourceView     *self,
-                              IdeSourceSnippet  *snippet,
+                              IdeSnippet  *snippet,
                               const GtkTextIter *location)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
-  IdeSourceSnippetContext *context;
-  IdeSourceSnippet *previous;
+  IdeSnippetContext *context;
+  IdeSnippet *previous;
   GtkTextBuffer *buffer;
   GtkTextIter iter;
   gboolean has_more_tab_stops;
@@ -6902,12 +6901,12 @@ ide_source_view_push_snippet (IdeSourceView     *self,
   guint tab_width;
 
   g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
-  g_return_if_fail (IDE_IS_SOURCE_SNIPPET (snippet));
+  g_return_if_fail (IDE_IS_SNIPPET (snippet));
   g_return_if_fail (!location ||
                     (gtk_text_iter_get_buffer (location) == (void*)priv->buffer));
 
   if ((previous = g_queue_peek_head (priv->snippets)))
-    ide_source_snippet_pause (previous);
+    ide_snippet_pause (previous);
 
   g_queue_push_head (priv->snippets, g_object_ref (snippet));
 
@@ -6918,23 +6917,23 @@ ide_source_view_push_snippet (IdeSourceView     *self,
   else
     gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
 
-  context = ide_source_snippet_get_context (snippet);
+  context = ide_snippet_get_context (snippet);
 
   insert_spaces = gtk_source_view_get_insert_spaces_instead_of_tabs (GTK_SOURCE_VIEW (self));
-  ide_source_snippet_context_set_use_spaces (context, insert_spaces);
+  ide_snippet_context_set_use_spaces (context, insert_spaces);
 
   tab_width = gtk_source_view_get_tab_width (GTK_SOURCE_VIEW (self));
-  ide_source_snippet_context_set_tab_width (context, tab_width);
+  ide_snippet_context_set_tab_width (context, tab_width);
 
   line_prefix = text_iter_get_line_prefix (&iter);
-  ide_source_snippet_context_set_line_prefix (context, line_prefix);
+  ide_snippet_context_set_line_prefix (context, line_prefix);
   g_free (line_prefix);
 
   g_signal_emit (self, signals [PUSH_SNIPPET], 0, snippet, &iter);
 
   gtk_text_buffer_begin_user_action (buffer);
   ide_source_view_block_handlers (self);
-  has_more_tab_stops = ide_source_snippet_begin (snippet, buffer, &iter);
+  has_more_tab_stops = ide_snippet_begin (snippet, buffer, &iter);
   ide_source_view_scroll_to_insert (self);
   ide_source_view_unblock_handlers (self);
   gtk_text_buffer_end_user_action (buffer);
@@ -6944,8 +6943,8 @@ ide_source_view_push_snippet (IdeSourceView     *self,
       GtkTextMark *mark_begin;
       GtkTextMark *mark_end;
 
-      mark_begin = ide_source_snippet_get_mark_begin (snippet);
-      mark_end = ide_source_snippet_get_mark_end (snippet);
+      mark_begin = ide_snippet_get_mark_begin (snippet);
+      mark_end = ide_snippet_get_mark_end (snippet);
 
       if (mark_begin != NULL && mark_end != NULL)
         {
@@ -7652,9 +7651,9 @@ _ide_source_view_get_scroll_mark (IdeSourceView *self)
  *
  * Gets the current snippet if there is one, otherwise %NULL.
  *
- * Returns: (transfer none) (nullable): An #IdeSourceSnippet or %NULL.
+ * Returns: (transfer none) (nullable): An #IdeSnippet or %NULL.
  */
-IdeSourceSnippet *
+IdeSnippet *
 ide_source_view_get_current_snippet (IdeSourceView *self)
 {
   IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
diff --git a/src/libide/sourceview/ide-source-view.h b/src/libide/sourceview/ide-source-view.h
index f243c2f8d..fbc45d88d 100644
--- a/src/libide/sourceview/ide-source-view.h
+++ b/src/libide/sourceview/ide-source-view.h
@@ -367,7 +367,7 @@ gboolean                    ide_source_view_has_snippet               (IdeSource
 IDE_AVAILABLE_IN_ALL
 void                        ide_source_view_clear_snippets            (IdeSourceView              *self);
 IDE_AVAILABLE_IN_ALL
-IdeSourceSnippet           *ide_source_view_get_current_snippet       (IdeSourceView              *self);
+IdeSnippet                 *ide_source_view_get_current_snippet       (IdeSourceView              *self);
 IDE_AVAILABLE_IN_ALL
 guint                       ide_source_view_get_visual_column         (IdeSourceView              *self,
                                                                        const GtkTextIter          *location);
@@ -424,7 +424,7 @@ IDE_AVAILABLE_IN_ALL
 void                        ide_source_view_pop_snippet               (IdeSourceView              *self);
 IDE_AVAILABLE_IN_ALL
 void                        ide_source_view_push_snippet              (IdeSourceView              *self,
-                                                                       IdeSourceSnippet           *snippet,
+                                                                       IdeSnippet                 *snippet,
                                                                        const GtkTextIter          *location);
 IDE_AVAILABLE_IN_ALL
 void                        ide_source_view_rollback_search           (IdeSourceView              *self);
diff --git a/src/plugins/clang/ide-clang-completion-item.c b/src/plugins/clang/ide-clang-completion-item.c
index ba50f4419..66ebdcce5 100644
--- a/src/plugins/clang/ide-clang-completion-item.c
+++ b/src/plugins/clang/ide-clang-completion-item.c
@@ -270,11 +270,11 @@ get_space_before_mask (enum CXCompletionChunkKind kind)
     }
 }
 
-static IdeSourceSnippet *
+static IdeSnippet *
 ide_clang_completion_item_create_snippet (IdeClangCompletionItem *self,
                                           IdeFileSettings        *file_settings)
 {
-  g_autoptr(IdeSourceSnippet) snippet = NULL;
+  g_autoptr(IdeSnippet) snippet = NULL;
   g_autoptr(GVariant) result = NULL;
   g_autoptr(GVariant) chunks = NULL;
   GVariantIter iter;
@@ -286,7 +286,7 @@ ide_clang_completion_item_create_snippet (IdeClangCompletionItem *self,
   g_assert (!file_settings || IDE_IS_FILE_SETTINGS (file_settings));
 
   result = ide_clang_completion_item_get_result (self);
-  snippet = ide_source_snippet_new (NULL, NULL);
+  snippet = ide_snippet_new (NULL, NULL);
 
   if (file_settings != NULL)
     spaces = ide_file_settings_get_spaces_style (file_settings);
@@ -299,7 +299,7 @@ ide_clang_completion_item_create_snippet (IdeClangCompletionItem *self,
   while ((vchunk = g_variant_iter_next_value (&iter)))
     {
       enum CXCompletionChunkKind kind;
-      IdeSourceSnippetChunk *chunk;
+      IdeSnippetChunk *chunk;
       const gchar *text;
 
       if (!g_variant_lookup (vchunk, "kind", "u", &kind))
@@ -311,27 +311,27 @@ ide_clang_completion_item_create_snippet (IdeClangCompletionItem *self,
       switch (kind)
         {
         case CXCompletionChunk_TypedText:
-          chunk = ide_source_snippet_chunk_new ();
-          ide_source_snippet_chunk_set_text (chunk, text);
-          ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-          ide_source_snippet_add_chunk (snippet, chunk);
+          chunk = ide_snippet_chunk_new ();
+          ide_snippet_chunk_set_text (chunk, text);
+          ide_snippet_chunk_set_text_set (chunk, TRUE);
+          ide_snippet_add_chunk (snippet, chunk);
           g_clear_object (&chunk);
           break;
 
         case CXCompletionChunk_Text:
-          chunk = ide_source_snippet_chunk_new ();
-          ide_source_snippet_chunk_set_text (chunk, text);
-          ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-          ide_source_snippet_add_chunk (snippet, chunk);
+          chunk = ide_snippet_chunk_new ();
+          ide_snippet_chunk_set_text (chunk, text);
+          ide_snippet_chunk_set_text_set (chunk, TRUE);
+          ide_snippet_add_chunk (snippet, chunk);
           g_clear_object (&chunk);
           break;
 
         case CXCompletionChunk_Placeholder:
-          chunk = ide_source_snippet_chunk_new ();
-          ide_source_snippet_chunk_set_text (chunk, text);
-          ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-          ide_source_snippet_chunk_set_tab_stop (chunk, ++tab_stop);
-          ide_source_snippet_add_chunk (snippet, chunk);
+          chunk = ide_snippet_chunk_new ();
+          ide_snippet_chunk_set_text (chunk, text);
+          ide_snippet_chunk_set_text_set (chunk, TRUE);
+          ide_snippet_chunk_set_tab_stop (chunk, ++tab_stop);
+          ide_snippet_add_chunk (snippet, chunk);
           g_clear_object (&chunk);
           break;
 
@@ -353,31 +353,31 @@ ide_clang_completion_item_create_snippet (IdeClangCompletionItem *self,
         case CXCompletionChunk_HorizontalSpace:
           if (spaces & get_space_before_mask (kind))
             {
-              chunk = ide_source_snippet_chunk_new ();
-              ide_source_snippet_chunk_set_text (chunk, " ");
-              ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-              ide_source_snippet_add_chunk (snippet, chunk);
+              chunk = ide_snippet_chunk_new ();
+              ide_snippet_chunk_set_text (chunk, " ");
+              ide_snippet_chunk_set_text_set (chunk, TRUE);
+              ide_snippet_add_chunk (snippet, chunk);
               g_clear_object (&chunk);
             }
-          chunk = ide_source_snippet_chunk_new ();
-          ide_source_snippet_chunk_set_text (chunk, text);
-          ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-          ide_source_snippet_add_chunk (snippet, chunk);
+          chunk = ide_snippet_chunk_new ();
+          ide_snippet_chunk_set_text (chunk, text);
+          ide_snippet_chunk_set_text_set (chunk, TRUE);
+          ide_snippet_add_chunk (snippet, chunk);
           g_clear_object (&chunk);
           break;
 
         case CXCompletionChunk_VerticalSpace:
           /* insert the vertical space */
-          chunk = ide_source_snippet_chunk_new ();
-          ide_source_snippet_chunk_set_text (chunk, text);
-          ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-          ide_source_snippet_add_chunk (snippet, chunk);
+          chunk = ide_snippet_chunk_new ();
+          ide_snippet_chunk_set_text (chunk, text);
+          ide_snippet_chunk_set_text_set (chunk, TRUE);
+          ide_snippet_add_chunk (snippet, chunk);
           g_clear_object (&chunk);
           /* now perform indentation */
-          chunk = ide_source_snippet_chunk_new ();
-          ide_source_snippet_chunk_set_text (chunk, "\t");
-          ide_source_snippet_chunk_set_text_set (chunk, TRUE);
-          ide_source_snippet_add_chunk (snippet, chunk);
+          chunk = ide_snippet_chunk_new ();
+          ide_snippet_chunk_set_text (chunk, "\t");
+          ide_snippet_chunk_set_text_set (chunk, TRUE);
+          ide_snippet_add_chunk (snippet, chunk);
           g_clear_object (&chunk);
           break;
 
@@ -425,11 +425,11 @@ ide_clang_completion_item_init (IdeClangCompletionItem *self)
  * @self: an #IdeClangCompletionItem.
  * @file_settings: (nullable): an #IdeFileSettings or %NULL
  *
- * Gets the #IdeSourceSnippet to be inserted when expanding this completion item.
+ * Gets the #IdeSnippet to be inserted when expanding this completion item.
  *
- * Returns: (transfer full): An #IdeSourceSnippet.
+ * Returns: (transfer full): An #IdeSnippet.
  */
-IdeSourceSnippet *
+IdeSnippet *
 ide_clang_completion_item_get_snippet (IdeClangCompletionItem *self,
                                        IdeFileSettings        *file_settings)
 {
diff --git a/src/plugins/clang/ide-clang-completion-item.h b/src/plugins/clang/ide-clang-completion-item.h
index 6360fb0d9..302a927f9 100644
--- a/src/plugins/clang/ide-clang-completion-item.h
+++ b/src/plugins/clang/ide-clang-completion-item.h
@@ -59,7 +59,7 @@ ide_clang_completion_item_get_result (const IdeClangCompletionItem *self)
 IdeClangCompletionItem *ide_clang_completion_item_new         (GVariant               *results,
                                                                guint                   index,
                                                                const gchar            *keyword);
-IdeSourceSnippet       *ide_clang_completion_item_get_snippet (IdeClangCompletionItem *self,
+IdeSnippet             *ide_clang_completion_item_get_snippet (IdeClangCompletionItem *self,
                                                                IdeFileSettings        *file_settings);
 
 G_END_DECLS
diff --git a/src/plugins/clang/ide-clang-completion-provider.c 
b/src/plugins/clang/ide-clang-completion-provider.c
index 41fa0279d..7ba3dc3c5 100644
--- a/src/plugins/clang/ide-clang-completion-provider.c
+++ b/src/plugins/clang/ide-clang-completion-provider.c
@@ -85,7 +85,7 @@ ide_clang_completion_provider_activate_proposal (IdeCompletionProvider *provider
                                                  const GdkEventKey     *key)
 {
   IdeClangCompletionProvider *self = (IdeClangCompletionProvider *)provider;
-  g_autoptr(IdeSourceSnippet) snippet = NULL;
+  g_autoptr(IdeSnippet) snippet = NULL;
   IdeClangCompletionItem *item;
   GtkTextBuffer *buffer;
   GtkTextView *view;
@@ -121,20 +121,20 @@ ide_clang_completion_provider_activate_proposal (IdeCompletionProvider *provider
     {
       if (key->keyval == GDK_KEY_period || key->keyval == GDK_KEY_minus)
         {
-          g_autoptr(IdeSourceSnippetChunk) chunk = ide_source_snippet_chunk_new ();
+          g_autoptr(IdeSnippetChunk) chunk = ide_snippet_chunk_new ();
           if (strchr (item->return_type, '*'))
-            ide_source_snippet_chunk_set_spec (chunk, "->");
+            ide_snippet_chunk_set_spec (chunk, "->");
           else
-            ide_source_snippet_chunk_set_spec (chunk, ".");
-          ide_source_snippet_add_chunk (snippet, chunk);
+            ide_snippet_chunk_set_spec (chunk, ".");
+          ide_snippet_add_chunk (snippet, chunk);
         }
     }
 
   if (key->keyval == GDK_KEY_semicolon)
     {
-      g_autoptr(IdeSourceSnippetChunk) chunk = ide_source_snippet_chunk_new ();
-      ide_source_snippet_chunk_set_spec (chunk, ";");
-      ide_source_snippet_add_chunk (snippet, chunk);
+      g_autoptr(IdeSnippetChunk) chunk = ide_snippet_chunk_new ();
+      ide_snippet_chunk_set_spec (chunk, ";");
+      ide_snippet_add_chunk (snippet, chunk);
     }
 
   ide_source_view_push_snippet (IDE_SOURCE_VIEW (view), snippet, &begin);
diff --git a/src/plugins/ctags/ide-ctags-completion-item.c b/src/plugins/ctags/ide-ctags-completion-item.c
index dd2fddd8e..a507aa7b1 100644
--- a/src/plugins/ctags/ide-ctags-completion-item.c
+++ b/src/plugins/ctags/ide-ctags-completion-item.c
@@ -101,43 +101,43 @@ ide_ctags_completion_item_is_function (IdeCtagsCompletionItem *self)
   return self->entry->kind == IDE_CTAGS_INDEX_ENTRY_FUNCTION;
 }
 
-IdeSourceSnippet *
+IdeSnippet *
 ide_ctags_completion_item_get_snippet (IdeCtagsCompletionItem *self,
                                        IdeFileSettings        *file_settings)
 {
-  g_autoptr(IdeSourceSnippet) ret = NULL;
-  g_autoptr(IdeSourceSnippetChunk) chunk1 = NULL;
+  g_autoptr(IdeSnippet) ret = NULL;
+  g_autoptr(IdeSnippetChunk) chunk1 = NULL;
 
   g_return_val_if_fail (IDE_IS_CTAGS_COMPLETION_ITEM (self), NULL);
   g_return_val_if_fail (!file_settings || IDE_IS_FILE_SETTINGS (file_settings), NULL);
 
-  ret = ide_source_snippet_new (NULL, NULL);
+  ret = ide_snippet_new (NULL, NULL);
 
-  chunk1 = ide_source_snippet_chunk_new ();
-  ide_source_snippet_chunk_set_spec (chunk1, self->entry->name);
-  ide_source_snippet_add_chunk (ret, chunk1);
+  chunk1 = ide_snippet_chunk_new ();
+  ide_snippet_chunk_set_spec (chunk1, self->entry->name);
+  ide_snippet_add_chunk (ret, chunk1);
 
   if (ide_ctags_completion_item_is_function (self))
     {
-      g_autoptr(IdeSourceSnippetChunk) chunk2 = ide_source_snippet_chunk_new ();
-      g_autoptr(IdeSourceSnippetChunk) chunk3 = ide_source_snippet_chunk_new ();
-      g_autoptr(IdeSourceSnippetChunk) chunk4 = ide_source_snippet_chunk_new ();
+      g_autoptr(IdeSnippetChunk) chunk2 = ide_snippet_chunk_new ();
+      g_autoptr(IdeSnippetChunk) chunk3 = ide_snippet_chunk_new ();
+      g_autoptr(IdeSnippetChunk) chunk4 = ide_snippet_chunk_new ();
       IdeSpacesStyle style = IDE_SPACES_STYLE_BEFORE_LEFT_PAREN;
 
       if (file_settings != NULL)
         style = ide_file_settings_get_spaces_style (file_settings);
 
       if (style & IDE_SPACES_STYLE_BEFORE_LEFT_PAREN)
-        ide_source_snippet_chunk_set_spec (chunk2, " (");
+        ide_snippet_chunk_set_spec (chunk2, " (");
       else
-        ide_source_snippet_chunk_set_spec (chunk2, "(");
+        ide_snippet_chunk_set_spec (chunk2, "(");
 
-      ide_source_snippet_chunk_set_tab_stop (chunk3, 0);
-      ide_source_snippet_chunk_set_spec (chunk4, ")");
+      ide_snippet_chunk_set_tab_stop (chunk3, 0);
+      ide_snippet_chunk_set_spec (chunk4, ")");
 
-      ide_source_snippet_add_chunk (ret, chunk2);
-      ide_source_snippet_add_chunk (ret, chunk3);
-      ide_source_snippet_add_chunk (ret, chunk4);
+      ide_snippet_add_chunk (ret, chunk2);
+      ide_snippet_add_chunk (ret, chunk3);
+      ide_snippet_add_chunk (ret, chunk4);
     }
 
   return g_steal_pointer (&ret);
diff --git a/src/plugins/ctags/ide-ctags-completion-item.h b/src/plugins/ctags/ide-ctags-completion-item.h
index f9c714ebf..bbaa736cb 100644
--- a/src/plugins/ctags/ide-ctags-completion-item.h
+++ b/src/plugins/ctags/ide-ctags-completion-item.h
@@ -39,7 +39,7 @@ struct _IdeCtagsCompletionItem
 IdeCtagsCompletionItem *ide_ctags_completion_item_new         (IdeCtagsResults            *results,
                                                                const IdeCtagsIndexEntry   *entry);
 gboolean                ide_ctags_completion_item_is_function (IdeCtagsCompletionItem     *self);
-IdeSourceSnippet       *ide_ctags_completion_item_get_snippet (IdeCtagsCompletionItem     *self,
+IdeSnippet             *ide_ctags_completion_item_get_snippet (IdeCtagsCompletionItem     *self,
                                                                IdeFileSettings            *file_settings);
 
 G_END_DECLS
diff --git a/src/plugins/ctags/ide-ctags-completion-provider.c 
b/src/plugins/ctags/ide-ctags-completion-provider.c
index da585d1a7..4390701b2 100644
--- a/src/plugins/ctags/ide-ctags-completion-provider.c
+++ b/src/plugins/ctags/ide-ctags-completion-provider.c
@@ -350,7 +350,7 @@ ide_ctags_completion_provider_activate_proposal (IdeCompletionProvider *provider
   IdeCtagsCompletionProvider *self = (IdeCtagsCompletionProvider *)provider;
   IdeCtagsCompletionItem *item = (IdeCtagsCompletionItem *)proposal;
   g_autofree gchar *slice = NULL;
-  g_autoptr(IdeSourceSnippet) snippet = NULL;
+  g_autoptr(IdeSnippet) snippet = NULL;
   IdeFileSettings *file_settings = NULL;
   GtkTextBuffer *buffer;
   GtkTextView *view;
diff --git a/src/plugins/jedi/jedi_plugin.py b/src/plugins/jedi/jedi_plugin.py
index 052500da1..571a64791 100644
--- a/src/plugins/jedi/jedi_plugin.py
+++ b/src/plugins/jedi/jedi_plugin.py
@@ -737,22 +737,22 @@ class JediWorker(GObject.Object, Ide.Worker):
                                       None)
 
 def JediSnippet(proposal):
-    snippet = Ide.SourceSnippet()
-    snippet.add_chunk(Ide.SourceSnippetChunk(text=proposal.completion_text, text_set=True))
+    snippet = Ide.Snippet()
+    snippet.add_chunk(Ide.SnippetChunk(text=proposal.completion_text, text_set=True))
 
     # Add parameter completion for functions.
     if proposal.completion_type == _TYPE_FUNCTION:
-        snippet.add_chunk(Ide.SourceSnippetChunk(text='(', text_set=True))
+        snippet.add_chunk(Ide.SnippetChunk(text='(', text_set=True))
         params = proposal.completion_params
         if params:
             tab_stop = 0
             for param in params[:-1]:
                 tab_stop += 1
-                snippet.add_chunk(Ide.SourceSnippetChunk(text=param, text_set=True, tab_stop=tab_stop))
-                snippet.add_chunk(Ide.SourceSnippetChunk(text=', ', text_set=True))
+                snippet.add_chunk(Ide.SnippetChunk(text=param, text_set=True, tab_stop=tab_stop))
+                snippet.add_chunk(Ide.SnippetChunk(text=', ', text_set=True))
             tab_stop += 1
-            snippet.add_chunk(Ide.SourceSnippetChunk(text=params[-1], text_set=True, tab_stop=tab_stop))
-        snippet.add_chunk(Ide.SourceSnippetChunk(text=')', text_set=True))
+            snippet.add_chunk(Ide.SnippetChunk(text=params[-1], text_set=True, tab_stop=tab_stop))
+        snippet.add_chunk(Ide.SnippetChunk(text=')', text_set=True))
 
     return snippet
 
diff --git a/src/tests/test-snippet-parser.c b/src/tests/test-snippet-parser.c
index 9c09467b1..3cf774cb4 100644
--- a/src/tests/test-snippet-parser.c
+++ b/src/tests/test-snippet-parser.c
@@ -1,7 +1,7 @@
 #include <ide.h>
 #include <stdlib.h>
 
-#include "snippets/ide-source-snippet-parser.h"
+#include "snippets/ide-snippet-parser.h"
 
 gint
 main (gint   argc,
@@ -26,7 +26,7 @@ main (gint   argc,
   for (i = 1; i < argc; i++)
     {
       const gchar *filename = argv [i];
-      g_autoptr(IdeSourceSnippetParser) parser = NULL;
+      g_autoptr(IdeSnippetParser) parser = NULL;
       g_autoptr(GFile) file = NULL;
 
       if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
@@ -37,35 +37,35 @@ main (gint   argc,
 
       file = g_file_new_for_commandline_arg (filename);
 
-      parser = ide_source_snippet_parser_new ();
+      parser = ide_snippet_parser_new ();
 
-      if (!ide_source_snippet_parser_load_from_file (parser, file, &error))
+      if (!ide_snippet_parser_load_from_file (parser, file, &error))
         {
           g_printerr ("%s\n", error->message);
           return EXIT_FAILURE;
         }
 
       {
-        for (GList *iter = ide_source_snippet_parser_get_snippets (parser);
+        for (GList *iter = ide_snippet_parser_get_snippets (parser);
              iter != NULL;
              iter = iter->next)
           {
-            IdeSourceSnippet *snippet = iter->data;
+            IdeSnippet *snippet = iter->data;
 
             g_print ("=====================================\n");
             g_print ("Snippet: %s with language %s\n",
-                     ide_source_snippet_get_trigger (snippet),
-                     ide_source_snippet_get_language (snippet));
+                     ide_snippet_get_trigger (snippet),
+                     ide_snippet_get_language (snippet));
 
-            for (guint j = 0; j < ide_source_snippet_get_n_chunks (snippet); j++)
+            for (guint j = 0; j < ide_snippet_get_n_chunks (snippet); j++)
               {
-                IdeSourceSnippetChunk *chunk = ide_source_snippet_get_nth_chunk (snippet, j);
-                gint tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk);
+                IdeSnippetChunk *chunk = ide_snippet_get_nth_chunk (snippet, j);
+                gint tab_stop = ide_snippet_chunk_get_tab_stop (chunk);
 
                 if (tab_stop > 0)
-                  g_print ("TAB STOP %02d (%02d): %s\n", tab_stop, j, ide_source_snippet_chunk_get_spec 
(chunk));
+                  g_print ("TAB STOP %02d (%02d): %s\n", tab_stop, j, ide_snippet_chunk_get_spec (chunk));
                 else
-                  g_print ("TEXT        (%02d): %s\n", j, ide_source_snippet_chunk_get_spec (chunk));
+                  g_print ("TEXT        (%02d): %s\n", j, ide_snippet_chunk_get_spec (chunk));
               }
           }
       }


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