[gnome-builder] ctags: Implement a generic ctags highlighter
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] ctags: Implement a generic ctags highlighter
- Date: Thu, 21 May 2015 23:03:52 +0000 (UTC)
commit e05c5381d23b458757b42bcfc46daa7e657117f2
Author: Dimitris Zenios <dimitris zenios gmail com>
Date: Fri May 22 01:13:50 2015 +0300
ctags: Implement a generic ctags highlighter
libide/Makefile.am | 2 +
libide/ctags/ide-ctags-highlighter.c | 232 ++++++++++++++++++++++++++++++++++
libide/ctags/ide-ctags-highlighter.h | 41 ++++++
libide/ctags/ide-ctags-service.c | 23 ++++
libide/ctags/ide-ctags-service.h | 4 +-
libide/ide-language.c | 27 ++++
6 files changed, 328 insertions(+), 1 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index b0e2b8c..f6141b1 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -229,6 +229,8 @@ libide_1_0_la_SOURCES = \
ctags/ide-ctags-completion-item.h \
ctags/ide-ctags-completion-provider.c \
ctags/ide-ctags-completion-provider.h \
+ ctags/ide-ctags-highlighter.c \
+ ctags/ide-ctags-highlighter.h \
ctags/ide-ctags-index.c \
ctags/ide-ctags-index.h \
ctags/ide-ctags-service.c \
diff --git a/libide/ctags/ide-ctags-highlighter.c b/libide/ctags/ide-ctags-highlighter.c
new file mode 100644
index 0000000..c06f920
--- /dev/null
+++ b/libide/ctags/ide-ctags-highlighter.c
@@ -0,0 +1,232 @@
+/* ide-ctags-highlighter.c
+ *
+ * Copyright (C) 2015 Christian Hergert <dimitris zenios gmail 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 <glib/gi18n.h>
+
+#include "ide-ctags-highlighter.h"
+#include "ide-debug.h"
+
+struct _IdeCtagsHighlighter
+{
+ IdeHighlighter parent_instance;
+ GPtrArray *indexes;
+};
+
+G_DEFINE_TYPE (IdeCtagsHighlighter, ide_ctags_highlighter, IDE_TYPE_HIGHLIGHTER)
+
+static inline gboolean
+accepts_char (gunichar ch)
+{
+ return (ch == '_' || g_unichar_isalnum (ch));
+}
+
+static gboolean
+select_next_word (GtkTextIter *begin,
+ GtkTextIter *end)
+{
+ g_assert (begin);
+ g_assert (end);
+
+ *end = *begin;
+
+ while (!accepts_char (gtk_text_iter_get_char (begin)))
+ if (!gtk_text_iter_forward_char (begin))
+ return FALSE;
+
+ *end = *begin;
+
+ while (accepts_char (gtk_text_iter_get_char (end)))
+ if (!gtk_text_iter_forward_char (end))
+ return !gtk_text_iter_equal (begin, end);
+
+ return TRUE;
+}
+
+static const gchar *
+get_tag_from_kind (IdeCtagsIndexEntryKind kind)
+{
+ switch (kind)
+ {
+ case IDE_CTAGS_INDEX_ENTRY_FUNCTION:
+ return IDE_CTAGS_HIGHLIGHTER_FUNCTION_NAME;
+
+ case IDE_CTAGS_INDEX_ENTRY_ENUMERATOR:
+ case IDE_CTAGS_INDEX_ENTRY_ENUMERATION_NAME:
+ return IDE_CTAGS_HIGHLIGHTER_ENUM_NAME;
+
+ case IDE_CTAGS_INDEX_ENTRY_TYPEDEF:
+ case IDE_CTAGS_INDEX_ENTRY_STRUCTURE:
+ return IDE_CTAGS_HIGHLIGHTER_TYPE;
+
+ case IDE_CTAGS_INDEX_ENTRY_ANCHOR:
+ case IDE_CTAGS_INDEX_ENTRY_CLASS_NAME:
+ case IDE_CTAGS_INDEX_ENTRY_DEFINE:
+ case IDE_CTAGS_INDEX_ENTRY_FILE_NAME:
+ case IDE_CTAGS_INDEX_ENTRY_MEMBER:
+ case IDE_CTAGS_INDEX_ENTRY_PROTOTYPE:
+ case IDE_CTAGS_INDEX_ENTRY_UNION:
+ case IDE_CTAGS_INDEX_ENTRY_VARIABLE:
+
+ default:
+ return NULL;
+ }
+}
+
+static const gchar *get_tag (IdeCtagsHighlighter *self,const gchar *word)
+{
+ const IdeCtagsIndexEntry *entries;
+ gsize n_entries;
+ gsize i;
+
+ for (i = 0; i < self->indexes->len; i++)
+ {
+ IdeCtagsIndex *item = g_ptr_array_index (self->indexes, i);
+ entries = ide_ctags_index_lookup_prefix (item, word, &n_entries);
+ if ((entries == NULL) || (n_entries == 0))
+ continue;
+
+ return get_tag_from_kind (entries[0].kind);
+ }
+ return NULL;
+}
+
+static void
+ide_ctags_highlighter_real_update (IdeHighlighter *highlighter,
+ IdeHighlightCallback callback,
+ const GtkTextIter *range_begin,
+ const GtkTextIter *range_end,
+ GtkTextIter *location)
+{
+ GtkTextBuffer *text_buffer;
+ GtkSourceBuffer *source_buffer;
+ IdeBuffer *buffer;
+ GtkTextIter begin;
+ GtkTextIter end;
+
+ g_assert (IDE_IS_CTAGS_HIGHLIGHTER (highlighter));
+ g_assert (callback != NULL);
+ g_assert (range_begin != NULL);
+ g_assert (range_end != NULL);
+ g_assert (location != NULL);
+
+ if (!(text_buffer = gtk_text_iter_get_buffer (range_begin)) ||
+ !IDE_IS_BUFFER (text_buffer) ||
+ !(source_buffer = GTK_SOURCE_BUFFER (text_buffer)) ||
+ !(buffer = IDE_BUFFER (text_buffer)))
+ return;
+
+ begin = end = *location = *range_begin;
+
+ while (gtk_text_iter_compare (&begin, range_end) < 0)
+ {
+ if (!select_next_word (&begin, &end))
+ goto completed;
+
+ if (gtk_text_iter_compare (&begin, range_end) >= 0)
+ goto completed;
+
+ g_assert (!gtk_text_iter_equal (&begin, &end));
+
+ if (!gtk_source_buffer_iter_has_context_class (source_buffer, &begin, "string") &&
+ !gtk_source_buffer_iter_has_context_class (source_buffer, &begin, "path") &&
+ !gtk_source_buffer_iter_has_context_class (source_buffer, &begin, "comment"))
+ {
+ const gchar *tag;
+ gchar *word;
+
+ word = gtk_text_iter_get_slice (&begin, &end);
+ tag = get_tag (IDE_CTAGS_HIGHLIGHTER (highlighter), word);
+ g_free (word);
+
+ if (tag != NULL)
+ {
+ if (callback (&begin, &end, tag) == IDE_HIGHLIGHT_STOP)
+ {
+ *location = end;
+ return;
+ }
+ }
+ }
+
+ begin = end;
+ }
+
+completed:
+ *location = *range_end;
+}
+
+void
+ide_ctags_highlighter_add_index (IdeCtagsHighlighter *self,
+ IdeCtagsIndex *index)
+{
+ GFile *file;
+ gsize i;
+
+ IDE_ENTRY;
+
+ g_return_if_fail (IDE_IS_CTAGS_HIGHLIGHTER (self));
+ g_return_if_fail (!index || IDE_IS_CTAGS_INDEX (index));
+ g_return_if_fail (self->indexes != NULL);
+
+ file = ide_ctags_index_get_file (index);
+
+ for (i = 0; i < self->indexes->len; i++)
+ {
+ IdeCtagsIndex *item = g_ptr_array_index (self->indexes, i);
+ GFile *item_file = ide_ctags_index_get_file (item);
+
+ if (g_file_equal (item_file, file))
+ {
+ g_ptr_array_remove_index_fast (self->indexes, i);
+ g_ptr_array_add (self->indexes, g_object_ref (index));
+
+ IDE_EXIT;
+ }
+ }
+
+ g_ptr_array_add (self->indexes, g_object_ref (index));
+
+ IDE_EXIT;
+}
+
+static void
+ide_ctags_highlighter_finalize (GObject *object)
+{
+ IdeCtagsHighlighter *self = (IdeCtagsHighlighter *)object;
+
+ g_clear_pointer (&self->indexes, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (ide_ctags_highlighter_parent_class)->finalize (object);
+}
+
+static void
+ide_ctags_highlighter_class_init (IdeCtagsHighlighterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ IdeHighlighterClass *highlighter_class = IDE_HIGHLIGHTER_CLASS (klass);
+
+ object_class->finalize = ide_ctags_highlighter_finalize;
+ highlighter_class->update = ide_ctags_highlighter_real_update;
+
+}
+
+static void
+ide_ctags_highlighter_init (IdeCtagsHighlighter *self)
+{
+ self->indexes = g_ptr_array_new_with_free_func (g_object_unref);
+}
diff --git a/libide/ctags/ide-ctags-highlighter.h b/libide/ctags/ide-ctags-highlighter.h
new file mode 100644
index 0000000..f1db144
--- /dev/null
+++ b/libide/ctags/ide-ctags-highlighter.h
@@ -0,0 +1,41 @@
+/* ide-ctags-highlighter.h
+ *
+ * Copyright (C) 2015 Dimitris Zenios <dimitris zenios gmail 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/>.
+ */
+
+#ifndef IDE_CTAGS_HIGHLIGHTER_H
+#define IDE_CTAGS_HIGHLIGHTER_H
+
+#include "ide-highlighter.h"
+#include "ide-ctags-index.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_CTAGS_HIGHLIGHTER (ide_ctags_highlighter_get_type())
+
+#define IDE_CTAGS_HIGHLIGHTER_TYPE "c:type"
+#define IDE_CTAGS_HIGHLIGHTER_FUNCTION_NAME "def:function"
+#define IDE_CTAGS_HIGHLIGHTER_ENUM_NAME "def:constant"
+
+G_DECLARE_FINAL_TYPE (IdeCtagsHighlighter, ide_ctags_highlighter,
+ IDE, CTAGS_HIGHLIGHTER, IdeHighlighter)
+
+void ide_ctags_highlighter_add_index (IdeCtagsHighlighter *self,
+ IdeCtagsIndex *index);
+
+G_END_DECLS
+
+#endif /* IDE_CTAGS_HIGHLIGHTER_H */
diff --git a/libide/ctags/ide-ctags-service.c b/libide/ctags/ide-ctags-service.c
index a273344..612a57a 100644
--- a/libide/ctags/ide-ctags-service.c
+++ b/libide/ctags/ide-ctags-service.c
@@ -32,12 +32,14 @@
#include "ide-global.h"
#include "ide-project.h"
#include "ide-vcs.h"
+#include "ide-ctags-highlighter.h"
struct _IdeCtagsService
{
IdeService parent_instance;
GtkSourceCompletionProvider *provider;
+ IdeHighlighter *highlighter;
EggTaskCache *indexes;
GCancellable *cancellable;
IdeCtagsBuilder *builder;
@@ -124,6 +126,7 @@ ide_ctags_service_tags_loaded_cb (GObject *object,
g_assert (IDE_IS_CTAGS_INDEX (index));
ide_ctags_completion_provider_add_index (IDE_CTAGS_COMPLETION_PROVIDER (self->provider), index);
+ ide_ctags_highlighter_add_index (IDE_CTAGS_HIGHLIGHTER (self->highlighter), index);
IDE_EXIT;
}
@@ -288,6 +291,20 @@ ide_ctags_service_mine (IdeCtagsService *self)
g_task_run_in_thread (task, ide_ctags_service_miner);
}
+IdeHighlighter *
+ide_ctags_service_get_highlighter (IdeCtagsService *self)
+{
+ g_return_val_if_fail (IDE_IS_CTAGS_SERVICE (self), NULL);
+
+ if (!self->miner_ran)
+ {
+ self->miner_ran = TRUE;
+ ide_ctags_service_mine (self);
+ }
+
+ return self->highlighter;
+}
+
GtkSourceCompletionProvider *
ide_ctags_service_get_provider (IdeCtagsService *self)
{
@@ -365,6 +382,7 @@ ide_ctags_service_finalize (GObject *object)
g_clear_object (&self->indexes);
g_clear_object (&self->provider);
+ g_clear_object (&self->highlighter);
g_clear_object (&self->cancellable);
G_OBJECT_CLASS (ide_ctags_service_parent_class)->finalize (object);
@@ -390,6 +408,11 @@ ide_ctags_service_init (IdeCtagsService *self)
self->provider = g_object_new (IDE_TYPE_CTAGS_COMPLETION_PROVIDER,
NULL);
+ self->highlighter = g_object_new (IDE_TYPE_CTAGS_HIGHLIGHTER,
+ "context",ide_object_get_context (IDE_OBJECT (self)),
+ NULL);
+
+
self->indexes = egg_task_cache_new ((GHashFunc)g_file_hash,
(GEqualFunc)g_file_equal,
g_object_ref,
diff --git a/libide/ctags/ide-ctags-service.h b/libide/ctags/ide-ctags-service.h
index 3f335c7..e6bfcd0 100644
--- a/libide/ctags/ide-ctags-service.h
+++ b/libide/ctags/ide-ctags-service.h
@@ -22,6 +22,7 @@
#include <gtksourceview/gtksource.h>
#include "ide-service.h"
+#include "ide-highlighter.h"
G_BEGIN_DECLS
@@ -29,7 +30,8 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (IdeCtagsService, ide_ctags_service, IDE, CTAGS_SERVICE, IdeService)
-GtkSourceCompletionProvider *ide_ctags_service_get_provider (IdeCtagsService *self);
+GtkSourceCompletionProvider *ide_ctags_service_get_provider (IdeCtagsService *self);
+IdeHighlighter *ide_ctags_service_get_highlighter (IdeCtagsService *self);
G_END_DECLS
diff --git a/libide/ide-language.c b/libide/ide-language.c
index 56d85c9..d284659 100644
--- a/libide/ide-language.c
+++ b/libide/ide-language.c
@@ -173,6 +173,32 @@ ide_language_real_get_diagnostician (IdeLanguage *self)
return gDiagnostician;
}
+static IdeHighlighter *
+ide_language_real_get_highlighter (IdeLanguage *self)
+{
+ IdeLanguagePrivate *priv = ide_language_get_instance_private (self);
+
+ g_assert (IDE_IS_LANGUAGE (self));
+
+ if (ide_str_equal0 (priv->id, "c") ||
+ ide_str_equal0 (priv->id, "cpp") ||
+ ide_str_equal0 (priv->id, "chdr") ||
+ ide_str_equal0 (priv->id, "python") ||
+ ide_str_equal0 (priv->id, "js") ||
+ ide_str_equal0 (priv->id, "css") ||
+ ide_str_equal0 (priv->id, "html"))
+ {
+ IdeCtagsService *service;
+ IdeContext *context;
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+ service = ide_context_get_service_typed (context, IDE_TYPE_CTAGS_SERVICE);
+ return ide_ctags_service_get_highlighter (service);
+ }
+
+ return NULL;
+}
+
/**
* ide_language_get_highlighter:
*
@@ -372,6 +398,7 @@ ide_language_class_init (IdeLanguageClass *klass)
klass->get_completion_providers = ide_language_real_get_completion_providers;
klass->get_diagnostician = ide_language_real_get_diagnostician;
+ klass->get_highlighter = ide_language_real_get_highlighter;
gParamSpecs [PROP_DIAGNOSTICIAN] =
g_param_spec_object ("diagnostician",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]