static gint ide_source_snippet_get_index (IdeSourceSnippet *self, GtkTextIter *iter) { gint offset; gint run; gint i; g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0); g_return_val_if_fail (iter, 0); offset = ide_source_snippet_get_offset (self, iter); for (i = 0; i < self->runs->len; i++) { run = g_array_index (self->runs, gint, i); offset -= run; if (offset <= 0) { /* * HACK: This is the central part of the hack by using offsets * instead of textmarks (which gives us lots of gravity grief). * We guess which snippet it is based on the current chunk. */ if ((i + 1) == self->current_chunk) return (i + 1); return i; } } return (self->runs->len - 1); }
gint ide_source_snippet_get_tab_stop (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), -1); return self->tab_stop; }
const gchar * ide_source_snippet_get_trigger (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL); return self->trigger; }
/** * ide_source_snippet_get_mark_end: * * Returns: (transfer none): */ GtkTextMark * ide_source_snippet_get_mark_end (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL); return self->mark_end; }
void ide_source_snippet_get_chunk_range (IdeSourceSnippet *self, IdeSourceSnippetChunk *chunk, GtkTextIter *begin, GtkTextIter *end) { IdeSourceSnippetChunk *item; guint i; g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); g_return_if_fail (IDE_IS_SOURCE_SNIPPET_CHUNK (chunk)); for (i = 0; i < self->chunks->len; i++) { item = g_ptr_array_index (self->chunks, i); if (item == chunk) { ide_source_snippet_get_nth_chunk_range (self, i, begin, end); return; } } g_warning (_("Chunk does not belong to snippet.")); }
void ide_source_snippet_before_insert_text (IdeSourceSnippet *self, GtkTextBuffer *buffer, GtkTextIter *iter, gchar *text, gint len) { gint utf8_len; gint n; g_return_if_fail (IDE_IS_SOURCE_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); utf8_len = g_utf8_strlen (text, len); g_array_index (self->runs, gint, n) += utf8_len; #if 0 g_print ("I: "); for (n = 0; n < self->runs->len; n++) g_print ("%d ", g_array_index (self->runs, gint, n)); g_print ("\n"); #endif }
const gchar * ide_source_snippet_get_description (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL); return self->description; }
guint ide_source_snippet_get_n_chunks (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0); return self->chunks->len; }
static void ide_source_snippet_update_context (IdeSourceSnippet *self) { IdeSourceSnippetContext *context; IdeSourceSnippetChunk *chunk; const gchar *text; gchar key[12]; guint i; gint tab_stop; g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); context = ide_source_snippet_get_context (self); ide_source_snippet_context_emit_changed (context); for (i = 0; i < self->chunks->len; i++) { chunk = g_ptr_array_index (self->chunks, i); tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk); if (tab_stop > 0) { if ((text = ide_source_snippet_chunk_get_text (chunk))) { g_snprintf (key, sizeof key, "%d", tab_stop); key[sizeof key - 1] = '\0'; ide_source_snippet_context_add_variable (context, key, text); } } } ide_source_snippet_context_emit_changed (context); }
const gchar * ide_source_snippet_get_language (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL); return self->language; }
void ide_source_snippet_after_delete_range (IdeSourceSnippet *self, GtkTextBuffer *buffer, GtkTextIter *begin, GtkTextIter *end) { GtkTextMark *here; g_return_if_fail (IDE_IS_SOURCE_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); 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); #if 0 ide_source_snippet_context_dump (self->snippet_context); #endif }
static void ide_source_snippet_get_nth_chunk_range (IdeSourceSnippet *self, gint n, GtkTextIter *begin, GtkTextIter *end) { gint run; gint i; g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); g_return_if_fail (n >= 0); g_return_if_fail (begin); g_return_if_fail (end); gtk_text_buffer_get_iter_at_mark (self->buffer, begin, self->mark_begin); for (i = 0; i < n; i++) { run = g_array_index (self->runs, gint, i); gtk_text_iter_forward_chars (begin, run); } gtk_text_iter_assign (end, begin); run = g_array_index (self->runs, gint, n); gtk_text_iter_forward_chars (end, run); }
/** * ide_source_snippet_copy: * * Returns: (transfer full): An #IdeSourceSnippet. */ IdeSourceSnippet * ide_source_snippet_copy (IdeSourceSnippet *self) { IdeSourceSnippetChunk *chunk; IdeSourceSnippet *ret; gint i; g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL); ret = g_object_new (IDE_TYPE_SOURCE_SNIPPET, "trigger", self->trigger, "language", self->language, "description", self->description, NULL); for (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); g_object_unref (chunk); } return ret; }
void ide_source_snippet_before_delete_range (IdeSourceSnippet *self, GtkTextBuffer *buffer, GtkTextIter *begin, GtkTextIter *end) { IdeSourceSnippetChunk *chunk; gchar *new_text; gint *run; gint len; gint n; gint i; gint lower_bound = -1; gint upper_bound = -1; g_return_if_fail (IDE_IS_SOURCE_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); self->current_chunk = n; while (len && n < self->runs->len) { if (lower_bound == -1 || n < lower_bound) lower_bound = n; if (n > upper_bound) upper_bound = n; run = &g_array_index (self->runs, gint, n); if (len > *run) { len -= *run; *run = 0; n++; continue; } *run -= len; len = 0; break; } for (i = lower_bound; i <= upper_bound; i++) { chunk = g_ptr_array_index (self->chunks, i); 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); g_free (new_text); } #if 0 g_print ("D: "); for (n = 0; n < self->runs->len; n++) g_print ("%d ", g_array_index (self->runs, gint, n)); g_print ("\n"); #endif }
gboolean ide_source_snippet_begin (IdeSourceSnippet *self, GtkTextBuffer *buffer, GtkTextIter *iter) { IdeSourceSnippetContext *context; IdeSourceSnippetChunk *chunk; const gchar *text; gboolean ret; gint len; gint i; g_return_val_if_fail (IDE_IS_SOURCE_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); g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), FALSE); g_return_val_if_fail (iter, FALSE); self->inserted = TRUE; context = ide_source_snippet_get_context (self); ide_source_snippet_update_context (self); ide_source_snippet_context_emit_changed (context); ide_source_snippet_update_context (self); self->buffer = g_object_ref (buffer); self->mark_begin = gtk_text_buffer_create_mark (buffer, NULL, iter, TRUE); g_object_add_weak_pointer (G_OBJECT (self->mark_begin), (gpointer *) &self->mark_begin); gtk_text_buffer_begin_user_action (buffer); for (i = 0; i < self->chunks->len; i++) { chunk = g_ptr_array_index (self->chunks, i); if ((text = ide_source_snippet_chunk_get_text (chunk))) { len = g_utf8_strlen (text, -1); g_array_append_val (self->runs, len); gtk_text_buffer_insert (buffer, iter, text, -1); } } self->mark_end = gtk_text_buffer_create_mark (buffer, NULL, iter, FALSE); g_object_add_weak_pointer (G_OBJECT (self->mark_end), (gpointer *) &self->mark_end); g_object_ref (self->mark_begin); g_object_ref (self->mark_end); gtk_text_buffer_end_user_action (buffer); ret = ide_source_snippet_move_next (self); return ret; }
GtkSourceCompletionProposal * ide_source_snippet_completion_item_new (IdeSourceSnippet *snippet) { g_return_val_if_fail (!snippet || IDE_IS_SOURCE_SNIPPET (snippet), NULL); return g_object_new (IDE_TYPE_SOURCE_SNIPPET_COMPLETION_ITEM, "snippet", snippet, NULL); }
/** * ide_source_snippet_get_nth_chunk: * * Returns: (transfer none): */ IdeSourceSnippetChunk * ide_source_snippet_get_nth_chunk (IdeSourceSnippet *self, guint n) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0); if (n < self->chunks->len) return g_ptr_array_index (self->chunks, n); return NULL; }
void ide_source_snippet_set_trigger (IdeSourceSnippet *self, const gchar *trigger) { g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); if (self->trigger != trigger) { g_free (self->trigger); self->trigger = g_strdup (trigger); } }
void ide_source_snippet_set_language (IdeSourceSnippet *self, const gchar *language) { g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); if (self->language != language) { g_free (self->language); self->language = g_strdup (language); } }
void ide_source_snippet_set_description (IdeSourceSnippet *self, const gchar *description) { g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); if (self->description != description) { g_free (self->description); self->description = g_strdup (description); } }
void ide_source_snippets_add (IdeSourceSnippets *snippets, IdeSourceSnippet *snippet) { const gchar *trigger; g_return_if_fail (IDE_IS_SOURCE_SNIPPETS (snippets)); g_return_if_fail (IDE_IS_SOURCE_SNIPPET (snippet)); trigger = ide_source_snippet_get_trigger (snippet); trie_insert (snippets->snippets, trigger, g_object_ref (snippet)); }
static void ide_source_snippet_select_chunk (IdeSourceSnippet *self, gint n) { GtkTextIter begin; GtkTextIter end; g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); g_return_if_fail (n >= 0); g_return_if_fail (n < self->runs->len); ide_source_snippet_get_nth_chunk_range (self, n, &begin, &end); gtk_text_buffer_select_range (self->buffer, &begin, &end); self->current_chunk = n; }
static gboolean copy_into (Trie *trie, const gchar *key, gpointer value, gpointer user_data) { IdeSourceSnippet *snippet = value; Trie *dest = user_data; g_assert (dest); g_assert (IDE_IS_SOURCE_SNIPPET (snippet)); trie_insert (dest, key, g_object_ref (snippet)); return FALSE; }
static gint ide_source_snippet_get_offset (IdeSourceSnippet *self, GtkTextIter *iter) { GtkTextIter begin; gint ret; g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), 0); g_return_val_if_fail (iter, 0); gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin); ret = gtk_text_iter_get_offset (iter) - gtk_text_iter_get_offset (&begin); ret = MAX (0, ret); return ret; }
void ide_source_snippet_add_chunk (IdeSourceSnippet *self, IdeSourceSnippetChunk *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 (!self->inserted); g_ptr_array_add (self->chunks, g_object_ref (chunk)); ide_source_snippet_chunk_set_context (chunk, self->snippet_context); tab_stop = ide_source_snippet_chunk_get_tab_stop (chunk); self->max_tab_stop = MAX (self->max_tab_stop, tab_stop); }
static void ide_source_snippet_replace_chunk_text (IdeSourceSnippet *self, gint n, const gchar *text) { GtkTextIter begin; GtkTextIter end; g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); g_return_if_fail (n >= 0); g_return_if_fail (text); ide_source_snippet_get_nth_chunk_range (self, n, &begin, &end); gtk_text_buffer_delete (self->buffer, &begin, &end); gtk_text_buffer_insert (self->buffer, &end, text, -1); g_array_index (self->runs, gint, n) = g_utf8_strlen (text, -1); }
gboolean ide_source_snippet_insert_set (IdeSourceSnippet *self, GtkTextMark *mark) { GtkTextIter iter; g_return_val_if_fail (IDE_IS_SOURCE_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)) return FALSE; self->current_chunk = ide_source_snippet_get_index (self, &iter); return TRUE; }
static gboolean ide_source_snippet_within_bounds (IdeSourceSnippet *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 (iter, FALSE); gtk_text_buffer_get_iter_at_mark (self->buffer, &begin, self->mark_begin); gtk_text_buffer_get_iter_at_mark (self->buffer, &end, self->mark_end); ret = ((gtk_text_iter_compare (&begin, iter) <= 0) && (gtk_text_iter_compare (&end, iter) >= 0)); return ret; }
static void ide_source_snippet_rewrite_updated_chunks (IdeSourceSnippet *self) { IdeSourceSnippetChunk *chunk; const gchar *text; gchar *real_text; gint i; g_return_if_fail (IDE_IS_SOURCE_SNIPPET (self)); for (i = 0; i < self->chunks->len; i++) { chunk = g_ptr_array_index (self->chunks, i); text = ide_source_snippet_chunk_get_text (chunk); real_text = ide_source_snippet_get_nth_text (self, i); if (!!g_strcmp0 (text, real_text)) ide_source_snippet_replace_chunk_text (self, i, text); g_free (real_text); } }
/** * ide_source_snippet_get_context: * * Returns: (transfer none): */ IdeSourceSnippetContext * ide_source_snippet_get_context (IdeSourceSnippet *self) { g_return_val_if_fail (IDE_IS_SOURCE_SNIPPET (self), NULL); if (!self->snippet_context) { IdeSourceSnippetChunk *chunk; guint i; self->snippet_context = ide_source_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); } } return self->snippet_context; }