Unbreak the ctags plugin and make it useful.
Parse all file types supported by ctags. Categorize definitions and treat structs and enums like classes.
This commit is contained in:
parent
01326d8ede
commit
5982e95566
@ -2,6 +2,7 @@
|
||||
* ctags-doc.c
|
||||
*
|
||||
* Copyright (C) 2004-2007 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
* Copyright (C) 2008 by Christian Dywan <christian@twotoasts.de>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -123,6 +124,7 @@ _moo_ctags_doc_plugin_get_store (MooCtagsDocPlugin *plugin)
|
||||
static void
|
||||
get_iter_for_class (GtkTreeStore *store,
|
||||
GtkTreeIter *class_iter,
|
||||
const char *type,
|
||||
const char *name,
|
||||
GHashTable *classes)
|
||||
{
|
||||
@ -133,7 +135,7 @@ get_iter_for_class (GtkTreeStore *store,
|
||||
GtkTreeIter iter;
|
||||
char *label;
|
||||
|
||||
label = g_strdup_printf ("class %s", name);
|
||||
label = g_strdup_printf ("<b>%s</b> %s", type, name);
|
||||
|
||||
gtk_tree_store_append (store, &iter, NULL);
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_LABEL, label, -1);
|
||||
@ -152,17 +154,44 @@ process_list_simple (GSList *entries,
|
||||
GtkTreeStore *store)
|
||||
{
|
||||
GHashTable *classes;
|
||||
GtkTreeIter funcs_iter;
|
||||
gboolean funcs_added = FALSE;
|
||||
|
||||
gtk_tree_store_append (store, &funcs_iter, NULL);
|
||||
gtk_tree_store_set (store, &funcs_iter,
|
||||
MOO_CTAGS_VIEW_COLUMN_LABEL, "Functions",
|
||||
-1);
|
||||
|
||||
classes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
|
||||
(GDestroyNotify) gtk_tree_iter_free);
|
||||
|
||||
GtkTreeIter funcs_iter;
|
||||
gboolean funcs_added = FALSE;
|
||||
gtk_tree_store_append (store, &funcs_iter, NULL);
|
||||
gtk_tree_store_set (store, &funcs_iter,
|
||||
MOO_CTAGS_VIEW_COLUMN_LABEL, "<b>Functions</b>",
|
||||
-1);
|
||||
|
||||
GtkTreeIter macros_iter;
|
||||
gboolean macros_added = FALSE;
|
||||
gtk_tree_store_append (store, ¯os_iter, NULL);
|
||||
gtk_tree_store_set (store, ¯os_iter,
|
||||
MOO_CTAGS_VIEW_COLUMN_LABEL, "<b>Macros</b>",
|
||||
-1);
|
||||
|
||||
GtkTreeIter types_iter;
|
||||
gboolean types_added = FALSE;
|
||||
gtk_tree_store_append (store, &types_iter, NULL);
|
||||
gtk_tree_store_set (store, &types_iter,
|
||||
MOO_CTAGS_VIEW_COLUMN_LABEL, "<b>Types</b>",
|
||||
-1);
|
||||
|
||||
GtkTreeIter vars_iter;
|
||||
gboolean vars_added = FALSE;
|
||||
gtk_tree_store_append (store, &vars_iter, NULL);
|
||||
gtk_tree_store_set (store, &vars_iter,
|
||||
MOO_CTAGS_VIEW_COLUMN_LABEL, "<b>Variables</b>",
|
||||
-1);
|
||||
|
||||
GtkTreeIter other_iter;
|
||||
gboolean other_added = FALSE;
|
||||
gtk_tree_store_append (store, &other_iter, NULL);
|
||||
gtk_tree_store_set (store, &other_iter,
|
||||
MOO_CTAGS_VIEW_COLUMN_LABEL, "<b>Other</b>",
|
||||
-1);
|
||||
|
||||
while (entries)
|
||||
{
|
||||
MooCtagsEntry *entry;
|
||||
@ -170,24 +199,36 @@ process_list_simple (GSList *entries,
|
||||
entry = entries->data;
|
||||
entries = entries->next;
|
||||
|
||||
if (entry->klass || !strcmp (entry->kind, "c"))
|
||||
if (entry->klass || !strcmp (entry->kind, "c") ||
|
||||
!strcmp (entry->kind, "s") || !strcmp (entry->kind, "m") ||
|
||||
!strcmp (entry->kind, "g") || !strcmp (entry->kind, "e"))
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter parent_iter;
|
||||
|
||||
gchar* type = NULL;
|
||||
if (!strcmp (entry->kind, "c"))
|
||||
type = g_strdup ("class");
|
||||
else if (!strcmp (entry->kind, "g") || !strcmp (entry->kind, "e"))
|
||||
type = g_strdup ("enum");
|
||||
else if (!strcmp (entry->kind, "s") || !strcmp (entry->kind, "m"))
|
||||
type = g_strdup ("struct");
|
||||
else
|
||||
type = g_strdup (entry->kind);
|
||||
|
||||
get_iter_for_class (store, &parent_iter,
|
||||
type,
|
||||
entry->klass ? entry->klass : entry->name,
|
||||
classes);
|
||||
g_free (type);
|
||||
|
||||
if (entry->klass)
|
||||
if (entry->klass || !strcmp (entry->kind, "m") || !strcmp (entry->kind, "e"))
|
||||
{
|
||||
gtk_tree_store_append (store, &iter, &parent_iter);
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_tree_store_set (store, &parent_iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
}
|
||||
}
|
||||
else if (!strcmp (entry->kind, "f"))
|
||||
{
|
||||
@ -196,10 +237,46 @@ process_list_simple (GSList *entries,
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
funcs_added = TRUE;
|
||||
}
|
||||
else if (!strcmp (entry->kind, "d"))
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_store_append (store, &iter, ¯os_iter);
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
macros_added = TRUE;
|
||||
}
|
||||
else if (!strcmp (entry->kind, "v"))
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_store_append (store, &iter, &vars_iter);
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
vars_added = TRUE;
|
||||
}
|
||||
else if (!strcmp (entry->kind, "t") || !strcmp (entry->kind, "g"))
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_store_append (store, &iter, &types_iter);
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
types_added = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_store_append (store, &iter, &other_iter);
|
||||
gtk_tree_store_set (store, &iter, MOO_CTAGS_VIEW_COLUMN_ENTRY, entry, -1);
|
||||
other_added = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!funcs_added)
|
||||
gtk_tree_store_remove (store, &funcs_iter);
|
||||
if (!macros_added)
|
||||
gtk_tree_store_remove (store, ¯os_iter);
|
||||
if (!vars_added)
|
||||
gtk_tree_store_remove (store, &vars_iter);
|
||||
if (!types_added)
|
||||
gtk_tree_store_remove (store, &types_iter);
|
||||
if (!other_added)
|
||||
gtk_tree_store_remove (store, &other_iter);
|
||||
|
||||
g_hash_table_destroy (classes);
|
||||
}
|
||||
@ -226,9 +303,9 @@ _moo_ctags_language_find_for_name (const char *lang_name)
|
||||
if (!langs_hash)
|
||||
{
|
||||
static MooCtagsLanguage langs[] = {
|
||||
{ "c", "--fields=afksS --c-kinds=cf --language-force=c -I G_BEGIN_DECLS,G_END_DECLS", process_list_c },
|
||||
{ "c++", "--fields=afksS --c-kinds=cf --language-force=c++ -I G_BEGIN_DECLS,G_END_DECLS", process_list_c },
|
||||
{ "python", "--fields=afksS --c-kinds=cf --language-force=python", process_list_python },
|
||||
{ "c", "--language-force=c -I G_BEGIN_DECLS,G_END_DECLS", process_list_c },
|
||||
{ "c++", " --language-force=c++ -I G_BEGIN_DECLS,G_END_DECLS", process_list_c },
|
||||
{ "python", "--language-force=python", process_list_python },
|
||||
};
|
||||
|
||||
langs_hash = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
@ -247,8 +324,13 @@ process_entries (MooCtagsDocPlugin *plugin,
|
||||
GSList *list,
|
||||
MooCtagsLanguage *lang)
|
||||
{
|
||||
g_return_if_fail (lang != NULL || lang->process_list != NULL);
|
||||
lang->process_list (list, plugin->priv->store);
|
||||
if (lang)
|
||||
{
|
||||
g_return_if_fail (lang->process_list != NULL);
|
||||
lang->process_list (list, plugin->priv->store);
|
||||
}
|
||||
else
|
||||
process_list_simple (list, plugin->priv->store);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -271,6 +353,8 @@ moo_ctags_doc_plugin_update (MooCtagsDocPlugin *plugin)
|
||||
|
||||
if (filename && ctags_lang && (list = moo_ctags_parse_file (filename, ctags_lang->opts)))
|
||||
process_entries (plugin, list, ctags_lang);
|
||||
else if(filename && (list = moo_ctags_parse_file (filename, NULL)))
|
||||
process_entries (plugin, list, NULL);
|
||||
|
||||
g_slist_foreach (list, (GFunc) _moo_ctags_entry_unref, NULL);
|
||||
g_slist_free (list);
|
||||
@ -309,6 +393,7 @@ _moo_ctags_entry_unref (MooCtagsEntry *entry)
|
||||
{
|
||||
g_free (entry->name);
|
||||
g_free (entry->klass);
|
||||
g_free (entry->signature);
|
||||
_moo_free (MooCtagsEntry, entry);
|
||||
}
|
||||
}
|
||||
@ -329,12 +414,17 @@ moo_ctags_entry_new (const tagEntry *te)
|
||||
entry->line = (int) te->address.lineNumber - 1;
|
||||
entry->kind = _moo_intern_string (te->kind);
|
||||
entry->klass = NULL;
|
||||
entry->signature = NULL;
|
||||
entry->file_scope = te->fileScope != 0;
|
||||
|
||||
for (i = 0; i < te->fields.count; ++i)
|
||||
{
|
||||
if (!strcmp (te->fields.list[i].key, "class"))
|
||||
if (!strcmp (te->fields.list[i].key, "class") ||
|
||||
!strcmp (te->fields.list[i].key, "struct") ||
|
||||
!strcmp (te->fields.list[i].key, "enum"))
|
||||
entry->klass = g_strdup (te->fields.list[i].value);
|
||||
if (!strcmp (te->fields.list[i].key, "signature"))
|
||||
entry->signature = g_strdup (te->fields.list[i].value);
|
||||
}
|
||||
|
||||
return entry;
|
||||
@ -362,6 +452,8 @@ _moo_ctags_read_tags (const char *filename)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tagsSetSortType (file, TAG_UNSORTED);
|
||||
|
||||
while (tagsNext (file, &tentry) == TagSuccess)
|
||||
{
|
||||
MooCtagsEntry *e = moo_ctags_entry_new (&tentry);
|
||||
@ -375,90 +467,6 @@ _moo_ctags_read_tags (const char *filename)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static MooCtagsEntry *
|
||||
parse_line (const char *line,
|
||||
const char *end)
|
||||
{
|
||||
MooCtagsEntry *entry;
|
||||
char **tokens;
|
||||
|
||||
tokens = _moo_ascii_strnsplit (line, end - line, 4);
|
||||
|
||||
if (!tokens || g_strv_length (tokens) != 4)
|
||||
{
|
||||
g_strfreev (tokens);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry = _moo_new (MooCtagsEntry);
|
||||
entry->ref_count = 1;
|
||||
|
||||
entry->name = g_strdup (tokens[0]);
|
||||
entry->line = strtol (tokens[2], NULL, 10);
|
||||
entry->kind = _moo_intern_string (tokens[1]);
|
||||
|
||||
g_strfreev (tokens);
|
||||
return entry;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
_moo_ctags_parse_output (char *output)
|
||||
{
|
||||
GSList *list = NULL;
|
||||
char *endl;
|
||||
|
||||
while ((endl = strchr (output, '\n')))
|
||||
{
|
||||
MooCtagsEntry *entry;
|
||||
if ((entry = parse_line (output, endl)))
|
||||
list = g_slist_prepend (list, entry);
|
||||
output = endl + 1;
|
||||
}
|
||||
|
||||
return g_slist_reverse (list);
|
||||
}
|
||||
|
||||
GSList *
|
||||
_moo_ctags_parse_file (const char *filename,
|
||||
G_GNUC_UNUSED const char *type)
|
||||
{
|
||||
GError *error = NULL;
|
||||
const char *argv[4];
|
||||
int exit_status;
|
||||
GSList *list = NULL;
|
||||
char *output;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
argv[0] = "ctags";
|
||||
argv[1] = "-x";
|
||||
argv[2] = filename;
|
||||
argv[3] = NULL;
|
||||
|
||||
if (!g_spawn_sync (NULL, (char**) argv, NULL, G_SPAWN_SEARCH_PATH,
|
||||
NULL, NULL, &output, NULL, &exit_status, &error))
|
||||
{
|
||||
g_warning ("%s: could not run ctags command: %s", G_STRFUNC, error->message);
|
||||
g_error_free (error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (exit_status != 0)
|
||||
{
|
||||
g_warning ("%s: ctags command returned an error", G_STRFUNC);
|
||||
goto out;
|
||||
}
|
||||
|
||||
list = _moo_ctags_parse_output (output);
|
||||
|
||||
out:
|
||||
g_free (output);
|
||||
return list;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static char *
|
||||
get_tmp_file (void)
|
||||
{
|
||||
@ -496,7 +504,14 @@ moo_ctags_parse_file (const char *filename,
|
||||
if (!(tags_file = get_tmp_file ()))
|
||||
return NULL;
|
||||
|
||||
cmd_line = g_string_new ("ctags ");
|
||||
// -u unsorted
|
||||
// --fields
|
||||
// a access of class members
|
||||
// f file-restricted scoping
|
||||
// k kind of tag as a single letter
|
||||
// s scope of definition
|
||||
// S signature or prototype
|
||||
cmd_line = g_string_new ("ctags -u --fields=afksS ");
|
||||
|
||||
if (opts && opts[0])
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ struct _MooCtagsEntry
|
||||
const char *kind;
|
||||
int line;
|
||||
char *klass;
|
||||
char *signature;
|
||||
guint file_scope : 1;
|
||||
};
|
||||
|
||||
|
@ -188,9 +188,9 @@ ctags_plugin_deinit (CtagsPlugin *plugin)
|
||||
}
|
||||
|
||||
|
||||
MOO_PLUGIN_DEFINE_INFO (ctags, "Ctags", "Shows functions in open document\n"
|
||||
"(does not quite work yet)",
|
||||
"Yevgen Muntyan <muntyan@tamu.edu>",
|
||||
MOO_PLUGIN_DEFINE_INFO (ctags, "Ctags", "Shows functions in the open document",
|
||||
"Yevgen Muntyan <muntyan@tamu.edu>\n"
|
||||
"Christian Dywan <christian@twotoasts.de>",
|
||||
MOO_VERSION, NULL)
|
||||
MOO_WIN_PLUGIN_DEFINE (Ctags, ctags)
|
||||
MOO_PLUGIN_DEFINE_FULL (Ctags, ctags,
|
||||
|
@ -97,11 +97,19 @@ data_func (G_GNUC_UNUSED GtkTreeViewColumn *column,
|
||||
-1);
|
||||
|
||||
if (label)
|
||||
g_object_set (cell, "text", label, NULL);
|
||||
g_object_set (cell, "markup", label, NULL);
|
||||
else if (entry)
|
||||
g_object_set (cell, "text", entry->name, NULL);
|
||||
{
|
||||
gchar* markup;
|
||||
/*if (entry->signature)
|
||||
markup = g_strdup_printf ("%s %s", entry->name, entry->signature);
|
||||
else
|
||||
*/markup = g_strdup (entry->name);
|
||||
g_object_set (cell, "markup", markup, NULL);
|
||||
g_free (markup);
|
||||
}
|
||||
else
|
||||
g_object_set (cell, "text", NULL, NULL);
|
||||
g_object_set (cell, "markup", NULL, NULL);
|
||||
|
||||
g_free (label);
|
||||
_moo_ctags_entry_unref (entry);
|
||||
@ -117,7 +125,11 @@ _moo_ctags_view_init (MooCtagsView *view)
|
||||
MooCtagsViewPrivate);
|
||||
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
|
||||
g_object_set (view, "show-expanders", FALSE, "level-indentation", 6, NULL);
|
||||
g_object_set (view, "show-expanders", FALSE,
|
||||
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||
"level-indentation", 6,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
column = gtk_tree_view_column_new_with_attributes (NULL, cell, NULL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user