[geany/geany] 8385b0: Merge pull request #3137 from techee/tree_mapping

Enrico Tröger git-noreply at geany.org
Sun Apr 10 19:28:53 UTC 2022


Branch:      refs/heads/master
Author:      Enrico Tröger <enrico.troeger at uvena.de>
Committer:   GitHub <noreply at github.com>
Date:        Sun, 10 Apr 2022 19:28:53 UTC
Commit:      8385b048bf71f26100432028c7411968e5661826
             https://github.com/geany/geany/commit/8385b048bf71f26100432028c7411968e5661826

Log Message:
-----------
Merge pull request #3137 from techee/tree_mapping

Move symbol tree root mappings to tm_parser.c


Modified Paths:
--------------
    HACKING
    po/POTFILES.in
    src/editor.c
    src/keyfile.c
    src/symbols.c
    src/tagmanager/tm_ctags.c
    src/tagmanager/tm_parser.c
    src/tagmanager/tm_parser.h

Modified: HACKING
41 lines changed, 19 insertions(+), 22 deletions(-)
===================================================================
@@ -500,13 +500,13 @@ other changes should be passed on to the maintainers at
 http://scintilla.org. We normally update to a new Scintilla release
 shortly after one is made. See also scintilla/README.
 
-Tagmanager was originally taken from Anjuta 1.2.2, and parts of it
-(notably c.c) have been merged from later versions of Anjuta and
-CTags. The independent Tagmanager library itself ceased development
-before Geany was started. It's source code parsing is mostly taken from
-Exuberant CTags (see http://ctags.sf.net). If appropriate it's good to
-pass language parser changes back to the CTags project.
-
+We use an unmodified subset of universal-ctags sources
+(https://github.com/universal-ctags/ctags) to parse open documents. We
+also use the great majority of unmodified universal-ctags parsers except
+a few outliers that are maintained by us (those whose file names start
+with geany_). We normally update to the latest version of
+universal-ctags shortly after making a Geany release and keep this
+version during the rest of the development cycle.
 
 Notes
 =====
@@ -650,18 +650,13 @@ indentation after ':' is done from on_new_line_added().
 If the Scintilla lexer supports user type keyword highlighting (e.g.
 SCLEX_CPP), update document_update_tags() in document.c.
 
-Adding a TagManager parser
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+Adding a CTags parser
+^^^^^^^^^^^^^^^^^^^^^
 This assumes the filetype for Geany already exists.
 
 First write or find a CTags compatible parser, foo.c. Check this fork:
 https://github.com/universal-ctags/ctags
 
-There may be some unmerged language patches for CTags at:
-http://sf.net/projects/ctags - see the tracker.
-
-(You can also try the Anjuta project's anjuta-tags codebase.)
-
 Method
 ``````
 * Add foo.c to SRCS in Makefile.am.
@@ -673,20 +668,22 @@ In src/tagmanager/tm_parser.c:
 Add a map_FOO TMParserMapEntry mapping each kind's letter from foo.c's
 FooKinds to the appropriate TMTagType, and add the corresponding
 MAP_ENTRY(FOO) to parser_map.
-(You may want to make the symbols.c change before doing this).
 
 In src/tagmanager/tm_parser.c:
-Update tm_parser_scope_separator() and tm_parser_has_full_scope() to
-handle the new parser if applicable, by adding a TM_PARSER_FOO case entry.
+Add a group_FOO TMParserMapGroup defining root nodes of the symbol tree,
+used icons and TMTagType values grouped under the specified root.
+Multiple TMTagType values can be combined under a single root using |
+(bitwise OR).
+
+In src/tagmanager/tm_parser.c:
+Update various functions at the end of tm_parser.c to adjust Geany
+behavior to the behavior of the added parser. In particular, update
+tm_parser_scope_separator() and tm_parser_has_full_scope() so
+scope-related functionality works correctly.
 
 In filetypes.c, init_builtin_filetypes():
 Set the 2nd argument of the FT_INIT() macro for this filetype to FOO.
 
-In symbols.c:
-Unless your parser uses C-like tag type kinds, update
-add_top_level_items() for foo, calling tag_list_add_groups(). See
-get_tag_type_iter() for which tv_iters fields to use.
-
 Tests
 `````
 The tag parser tests checks if the proper tags are emitted


Modified: po/POTFILES.in
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -40,6 +40,7 @@ src/ui_utils.c
 src/utils.c
 src/vte.c
 src/win32.c
+src/tagmanager/tm_parser.c
 plugins/classbuilder.c
 plugins/htmlchars.c
 plugins/export.c


Modified: src/editor.c
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -708,7 +708,6 @@ static gboolean autocomplete_scope(GeanyEditor *editor, const gchar *root, gsize
 	gboolean scope_sep_typed = FALSE;
 	gboolean ret = FALSE;
 	const gchar *current_scope;
-	const gchar *context_sep = tm_parser_scope_separator(ft->lang);
 	gint autocomplete_suffix_len;
 
 	if (autocomplete_scope_shown)


Modified: src/keyfile.c
3 lines changed, 0 insertions(+), 3 deletions(-)
===================================================================
@@ -1458,9 +1458,6 @@ void configuration_init(void)
 
 void configuration_finalize(void)
 {
-	guint i;
-	StashGroup *group;
-
 	g_signal_handlers_disconnect_by_func(geany_object, G_CALLBACK(document_list_changed_cb), NULL);
 
 	g_ptr_array_free(pref_groups, TRUE);


Modified: src/symbols.c
630 lines changed, 46 insertions(+), 584 deletions(-)
===================================================================
@@ -73,34 +73,22 @@ typedef struct
 
 static GPtrArray *top_level_iter_names = NULL;
 
-enum
-{
-	ICON_CLASS,
-	ICON_MACRO,
-	ICON_MEMBER,
-	ICON_METHOD,
-	ICON_NAMESPACE,
-	ICON_OTHER,
-	ICON_STRUCT,
-	ICON_VAR,
-	ICON_NONE,
-	N_ICONS = ICON_NONE
-};
 
 static struct
 {
 	const gchar *icon_name;
 	GdkPixbuf *pixbuf;
 }
-symbols_icons[N_ICONS] = {
-	[ICON_CLASS]		= { "classviewer-class", NULL },
-	[ICON_MACRO]		= { "classviewer-macro", NULL },
-	[ICON_MEMBER]		= { "classviewer-member", NULL },
-	[ICON_METHOD]		= { "classviewer-method", NULL },
-	[ICON_NAMESPACE]	= { "classviewer-namespace", NULL },
-	[ICON_OTHER]		= { "classviewer-other", NULL },
-	[ICON_STRUCT]		= { "classviewer-struct", NULL },
-	[ICON_VAR]			= { "classviewer-var", NULL },
+/* keep in sync with enum in tm_parser.h */
+symbols_icons[TM_N_ICONS] = {
+	[TM_ICON_CLASS]		= { "classviewer-class", NULL },
+	[TM_ICON_MACRO]		= { "classviewer-macro", NULL },
+	[TM_ICON_MEMBER]	= { "classviewer-member", NULL },
+	[TM_ICON_METHOD]	= { "classviewer-method", NULL },
+	[TM_ICON_NAMESPACE]	= { "classviewer-namespace", NULL },
+	[TM_ICON_OTHER]		= { "classviewer-other", NULL },
+	[TM_ICON_STRUCT]	= { "classviewer-struct", NULL },
+	[TM_ICON_VAR]		= { "classviewer-var", NULL },
 };
 
 static struct
@@ -319,7 +307,7 @@ static gint compare_symbol_lines(gconstpointer a, gconstpointer b)
 static GList *get_tag_list(GeanyDocument *doc, TMTagType tag_types)
 {
 	GList *tag_names = NULL;
-	guint i, j;
+	guint i;
 	gchar **tf_strv;
 
 	g_return_val_if_fail(doc, NULL);
@@ -375,40 +363,19 @@ static GList *get_tag_list(GeanyDocument *doc, TMTagType tag_types)
 }
 
 
-/* amount of types in the symbol list (currently max. 8 are used) */
-#define MAX_SYMBOL_TYPES	(sizeof(tv_iters) / sizeof(GtkTreeIter))
+/* amount of types in the symbol list - can be increased if needed */
+#define MAX_SYMBOL_TYPES 15
 
-struct TreeviewSymbols
-{
-	GtkTreeIter		 tag_function;
-	GtkTreeIter		 tag_class;
-	GtkTreeIter		 tag_macro;
-	GtkTreeIter		 tag_member;
-	GtkTreeIter		 tag_variable;
-	GtkTreeIter		 tag_externvar;
-	GtkTreeIter		 tag_namespace;
-	GtkTreeIter		 tag_struct;
-	GtkTreeIter		 tag_interface;
-	GtkTreeIter		 tag_type;
-	GtkTreeIter		 tag_other;
-} tv_iters;
+GtkTreeIter tv_iters[MAX_SYMBOL_TYPES];
 
 
 static void init_tag_iters(void)
 {
+	guint i;
 	/* init all GtkTreeIters with -1 to make them invalid to avoid crashes when switching between
 	 * filetypes(e.g. config file to Python crashes Geany without this) */
-	tv_iters.tag_function.stamp = -1;
-	tv_iters.tag_class.stamp = -1;
-	tv_iters.tag_member.stamp = -1;
-	tv_iters.tag_macro.stamp = -1;
-	tv_iters.tag_variable.stamp = -1;
-	tv_iters.tag_externvar.stamp = -1;
-	tv_iters.tag_namespace.stamp = -1;
-	tv_iters.tag_struct.stamp = -1;
-	tv_iters.tag_interface.stamp = -1;
-	tv_iters.tag_type.stamp = -1;
-	tv_iters.tag_other.stamp = -1;
+	for (i = 0; i < MAX_SYMBOL_TYPES; i++)
+		tv_iters[i].stamp = -1;
 }
 
 
@@ -454,28 +421,24 @@ static gboolean find_toplevel_iter(GtkTreeStore *store, GtkTreeIter *iter, const
 }
 
 
-/* Adds symbol list groups in (iter*, title) pairs.
- * The list must be ended with NULL. */
-static void G_GNUC_NULL_TERMINATED
-tag_list_add_groups(GtkTreeStore *tree_store, ...)
+static void tag_list_add_groups(GtkTreeStore *tree_store, TMParserType lang)
 {
-	va_list args;
-	GtkTreeIter *iter;
+	const gchar *title;
+	guint i;
+	guint icon_id;
 
 	g_return_if_fail(top_level_iter_names);
 
-	va_start(args, tree_store);
-	for (; iter = va_arg(args, GtkTreeIter*), iter != NULL;)
+	for (i = 0; title = tm_parser_get_sidebar_info(lang, i, &icon_id); i++)
 	{
-		gchar *title = va_arg(args, gchar*);
-		guint icon_id = va_arg(args, guint);
+		GtkTreeIter *iter = &tv_iters[i];
 		GdkPixbuf *icon = NULL;
 
-		if (icon_id < N_ICONS)
+		if (icon_id < TM_N_ICONS)
 			icon = symbols_icons[icon_id].pixbuf;
 
 		g_assert(title != NULL);
-		g_ptr_array_add(top_level_iter_names, title);
+		g_ptr_array_add(top_level_iter_names, (gchar *)title);
 
 		if (!find_toplevel_iter(tree_store, iter, title))
 			gtk_tree_store_append(tree_store, iter, NULL);
@@ -484,13 +447,12 @@ tag_list_add_groups(GtkTreeStore *tree_store, ...)
 			gtk_tree_store_set(tree_store, iter, SYMBOLS_COLUMN_ICON, icon, -1);
 		gtk_tree_store_set(tree_store, iter, SYMBOLS_COLUMN_NAME, title, -1);
 	}
-	va_end(args);
 }
 
 
 static void add_top_level_items(GeanyDocument *doc)
 {
-	GeanyFiletypeID ft_id = doc->file_type->id;
+	TMParserType lang = doc->file_type->lang;
 	GtkTreeStore *tag_store = doc->priv->tag_store;
 
 	if (top_level_iter_names == NULL)
@@ -500,422 +462,7 @@ static void add_top_level_items(GeanyDocument *doc)
 
 	init_tag_iters();
 
-	switch (ft_id)
-	{
-		case GEANY_FILETYPES_DIFF:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Files"), ICON_NONE, NULL);
-			break;
-		}
-		case GEANY_FILETYPES_DOCBOOK:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Chapter"), ICON_NONE,
-				&(tv_iters.tag_class), _("Section"), ICON_NONE,
-				&(tv_iters.tag_member), _("Sect1"), ICON_NONE,
-				&(tv_iters.tag_macro), _("Sect2"), ICON_NONE,
-				&(tv_iters.tag_variable), _("Sect3"), ICON_NONE,
-				&(tv_iters.tag_struct), _("Appendix"), ICON_NONE,
-				&(tv_iters.tag_other), _("Other"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_HASKELL:
-			tag_list_add_groups(tag_store,
-				&tv_iters.tag_namespace, _("Module"), ICON_NONE,
-				&tv_iters.tag_type, _("Types"), ICON_NONE,
-				&tv_iters.tag_macro, _("Type constructors"), ICON_NONE,
-				&tv_iters.tag_function, _("Functions"), ICON_METHOD,
-				NULL);
-			break;
-		case GEANY_FILETYPES_COBOL:
-			tag_list_add_groups(tag_store,
-				&tv_iters.tag_class, _("Program"), ICON_CLASS,
-				&tv_iters.tag_function, _("File"), ICON_METHOD,
-				&tv_iters.tag_interface, _("Divisions"), ICON_NAMESPACE,
-				&tv_iters.tag_namespace, _("Sections"), ICON_NAMESPACE,
-				&tv_iters.tag_macro, _("Paragraph"), ICON_OTHER,
-				&tv_iters.tag_struct, _("Group"), ICON_STRUCT,
-				&tv_iters.tag_variable, _("Data"), ICON_VAR,
-				&tv_iters.tag_externvar, _("Copies"), ICON_NAMESPACE,
-				NULL);
-			break;
-		case GEANY_FILETYPES_CONF:
-			tag_list_add_groups(tag_store,
-				&tv_iters.tag_namespace, _("Sections"), ICON_OTHER,
-				&tv_iters.tag_macro, _("Keys"), ICON_VAR,
-				NULL);
-			break;
-		case GEANY_FILETYPES_GDSCRIPT:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_member), _("Methods"), ICON_MACRO,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_externvar), _("Imports"), ICON_NAMESPACE,
-				&(tv_iters.tag_type), _("Enums"), ICON_STRUCT,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_NSIS:
-			tag_list_add_groups(tag_store,
-				&tv_iters.tag_namespace, _("Sections"), ICON_OTHER,
-				&tv_iters.tag_function, _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				NULL);
-			break;
-		case GEANY_FILETYPES_LATEX:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Command"), ICON_NONE,
-				&(tv_iters.tag_class), _("Environment"), ICON_NONE,
-				&(tv_iters.tag_member), _("Section"), ICON_NONE,
-				&(tv_iters.tag_macro), _("Subsection"), ICON_NONE,
-				&(tv_iters.tag_variable), _("Subsubsection"), ICON_NONE,
-				&(tv_iters.tag_struct), _("Label"), ICON_NONE,
-				&(tv_iters.tag_namespace), _("Chapter"), ICON_NONE,
-				&(tv_iters.tag_other), _("Other"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_BIBTEX:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Articles"), ICON_NONE,
-				&(tv_iters.tag_macro), _("Book Chapters"), ICON_NONE,
-				&(tv_iters.tag_class), _("Books & Conference Proceedings"), ICON_NONE,
-				&(tv_iters.tag_member), _("Conference Papers"), ICON_NONE,
-				&(tv_iters.tag_variable), _("Theses"), ICON_NONE,
-				&(tv_iters.tag_namespace), _("Strings"), ICON_NONE,
-				&(tv_iters.tag_externvar), _("Unpublished"), ICON_NONE,
-				&(tv_iters.tag_other), _("Other"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_MATLAB:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_struct), _("Structures"), ICON_STRUCT,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_ABAQUS:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_class), _("Parts"), ICON_NONE,
-				&(tv_iters.tag_member), _("Assembly"), ICON_NONE,
-				&(tv_iters.tag_namespace), _("Steps"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_R:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_other), _("Other"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_RUST:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Modules"), ICON_NAMESPACE,
-				&(tv_iters.tag_struct), _("Structures"), ICON_STRUCT,
-				&(tv_iters.tag_interface), _("Traits"), ICON_CLASS,
-				&(tv_iters.tag_class), _("Implementations"), ICON_CLASS,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_type), _("Typedefs / Enums"), ICON_STRUCT,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_macro), _("Macros"), ICON_MACRO,
-				&(tv_iters.tag_member), _("Methods"), ICON_MEMBER,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_GO:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Package"), ICON_NAMESPACE,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_struct), _("Structs"), ICON_STRUCT,
-				&(tv_iters.tag_type), _("Types"), ICON_STRUCT,
-				&(tv_iters.tag_macro), _("Constants"), ICON_MACRO,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_member), _("Members"), ICON_MEMBER,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_PERL:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Package"), ICON_NAMESPACE,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_macro), _("Labels"), ICON_NONE,
-				&(tv_iters.tag_type), _("Constants"), ICON_NONE,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_PHP:
-		case GEANY_FILETYPES_ZEPHIR:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Namespaces"), ICON_NAMESPACE,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_macro), _("Constants"), ICON_MACRO,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_struct), _("Traits"), ICON_STRUCT,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_JULIA:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_variable), _("Constants"), ICON_VAR,
-				&(tv_iters.tag_namespace), _("Modules"), ICON_NAMESPACE,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_member), _("Fields"), ICON_MEMBER,
-				&(tv_iters.tag_macro), _("Macros"), ICON_MACRO,
-				&(tv_iters.tag_struct), _("Structures"), ICON_STRUCT,
-				&(tv_iters.tag_type), _("Types"), ICON_CLASS,
-				&(tv_iters.tag_externvar), _("Unknowns"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_HTML:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Functions"), ICON_NONE,
-				&(tv_iters.tag_member), _("Anchors"), ICON_NONE,
-				&(tv_iters.tag_namespace), _("H1 Headings"), ICON_NONE,
-				&(tv_iters.tag_class), _("H2 Headings"), ICON_NONE,
-				&(tv_iters.tag_variable), _("H3 Headings"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_CSS:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_variable), _("ID Selectors"), ICON_VAR,
-				&(tv_iters.tag_struct), _("Type Selectors"), ICON_STRUCT, NULL);
-			break;
-		}
-		case GEANY_FILETYPES_REST:
-		case GEANY_FILETYPES_TXT2TAGS:
-		case GEANY_FILETYPES_ABC:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Chapter"), ICON_NONE,
-				&(tv_iters.tag_member), _("Section"), ICON_NONE,
-				&(tv_iters.tag_macro), _("Subsection"), ICON_NONE,
-				&(tv_iters.tag_variable), _("Subsubsection"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_ASCIIDOC:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Document"), ICON_NONE,
-				&(tv_iters.tag_member), _("Section Level 1"), ICON_NONE,
-				&(tv_iters.tag_macro), _("Section Level 2"), ICON_NONE,
-				&(tv_iters.tag_variable), _("Section Level 3"), ICON_NONE,
-				&(tv_iters.tag_struct), _("Section Level 4"), ICON_NONE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_RUBY:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Modules"), ICON_NAMESPACE,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_member), _("Singletons"), ICON_STRUCT,
-				&(tv_iters.tag_function), _("Methods"), ICON_METHOD,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_TCL:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Namespaces"), ICON_NAMESPACE,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_member), _("Methods"), ICON_METHOD,
-				&(tv_iters.tag_function), _("Procedures"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_PYTHON:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_member), _("Methods"), ICON_MACRO,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_externvar), _("Imports"), ICON_NAMESPACE,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_VHDL:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Package"), ICON_NAMESPACE,
-				&(tv_iters.tag_class), _("Entities"), ICON_CLASS,
-				&(tv_iters.tag_struct), _("Architectures"), ICON_STRUCT,
-				&(tv_iters.tag_type), _("Types"), ICON_OTHER,
-				&(tv_iters.tag_function), _("Functions / Procedures"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables / Signals"), ICON_VAR,
-				&(tv_iters.tag_member), _("Processes / Blocks / Components"), ICON_MEMBER,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_VERILOG:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_type), _("Events"), ICON_MACRO,
-				&(tv_iters.tag_class), _("Modules"), ICON_CLASS,
-				&(tv_iters.tag_function), _("Functions / Tasks"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_JAVA:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Package"), ICON_NAMESPACE,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_function), _("Methods"), ICON_METHOD,
-				&(tv_iters.tag_member), _("Members"), ICON_MEMBER,
-				&(tv_iters.tag_type), _("Enums"), ICON_STRUCT,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_AS:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_externvar), _("Imports"), ICON_NAMESPACE,
-				&(tv_iters.tag_namespace), _("Package"), ICON_NAMESPACE,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_member), _("Properties"), ICON_MEMBER,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_macro), _("Constants"), ICON_MACRO,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_HAXE:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_function), _("Methods"), ICON_METHOD,
-				&(tv_iters.tag_type), _("Types"), ICON_MACRO,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_BASIC:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_macro), _("Constants"), ICON_MACRO,
-				&(tv_iters.tag_struct), _("Types"), ICON_NAMESPACE,
-				&(tv_iters.tag_namespace), _("Labels"), ICON_MEMBER,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_F77:
-		case GEANY_FILETYPES_FORTRAN:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Module"), ICON_CLASS,
-				&(tv_iters.tag_struct), _("Programs"), ICON_CLASS,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_function), _("Functions / Subroutines"), ICON_METHOD,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_class), _("Types"), ICON_CLASS,
-				&(tv_iters.tag_member), _("Components"), ICON_MEMBER,
-				&(tv_iters.tag_macro), _("Blocks"), ICON_MEMBER,
-				&(tv_iters.tag_type), _("Enums"), ICON_STRUCT,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_ASM:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_namespace), _("Labels"), ICON_NAMESPACE,
-				&(tv_iters.tag_function), _("Macros"), ICON_METHOD,
-				&(tv_iters.tag_macro), _("Defines"), ICON_MACRO,
-				&(tv_iters.tag_struct), _("Types"), ICON_STRUCT,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_MAKE:
-			tag_list_add_groups(tag_store,
-				&tv_iters.tag_function, _("Targets"), ICON_METHOD,
-				&tv_iters.tag_macro, _("Macros"), ICON_MACRO,
-				NULL);
-			break;
-		case GEANY_FILETYPES_SQL:
-		{
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_namespace), _("Procedures"), ICON_NAMESPACE,
-				&(tv_iters.tag_struct), _("Indexes"), ICON_STRUCT,
-				&(tv_iters.tag_class), _("Tables"), ICON_CLASS,
-				&(tv_iters.tag_macro), _("Triggers"), ICON_MACRO,
-				&(tv_iters.tag_member), _("Views"), ICON_VAR,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				NULL);
-			break;
-		}
-		case GEANY_FILETYPES_D:
-		default:
-		{
-			if (ft_id == GEANY_FILETYPES_D)
-				tag_list_add_groups(tag_store,
-					&(tv_iters.tag_namespace), _("Module"), ICON_NONE, NULL);
-			else
-				tag_list_add_groups(tag_store,
-					&(tv_iters.tag_namespace), _("Namespaces"), ICON_NAMESPACE, NULL);
-
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_class), _("Classes"), ICON_CLASS,
-				&(tv_iters.tag_interface), _("Interfaces"), ICON_STRUCT,
-				&(tv_iters.tag_function), _("Functions"), ICON_METHOD,
-				&(tv_iters.tag_member), _("Members"), ICON_MEMBER,
-				&(tv_iters.tag_struct), _("Structs"), ICON_STRUCT,
-				&(tv_iters.tag_type), _("Typedefs / Enums"), ICON_STRUCT,
-				NULL);
-
-			if (ft_id != GEANY_FILETYPES_D)
-			{
-				tag_list_add_groups(tag_store,
-					&(tv_iters.tag_macro), _("Macros"), ICON_MACRO, NULL);
-			}
-			tag_list_add_groups(tag_store,
-				&(tv_iters.tag_variable), _("Variables"), ICON_VAR,
-				&(tv_iters.tag_externvar), _("Extern Variables"), ICON_VAR,
-				&(tv_iters.tag_other), _("Other"), ICON_OTHER, NULL);
-		}
-	}
+	tag_list_add_groups(tag_store, lang);
 }
 
 
@@ -1019,87 +566,24 @@ static const gchar *get_parent_name(const TMTag *tag)
 }
 
 
-static GtkTreeIter *get_tag_type_iter(TMTagType tag_type)
+static GtkTreeIter *get_tag_type_iter(TMParserType lang, TMTagType tag_type)
 {
-	GtkTreeIter *iter = NULL;
+	/* TODO: tm_parser_get_sidebar_group() goes through groups one by one.
+	 * If this happens to be slow for tree construction, create a lookup
+	 * table for them. */
+	gint group = tm_parser_get_sidebar_group(lang, tag_type);
 
-	switch (tag_type)
-	{
-		case tm_tag_prototype_t:
-		case tm_tag_method_t:
-		case tm_tag_function_t:
-		{
-			iter = &tv_iters.tag_function;
-			break;
-		}
-		case tm_tag_externvar_t:
-		{
-			iter = &tv_iters.tag_externvar;
-			break;
-		}
-		case tm_tag_macro_t:
-		case tm_tag_macro_with_arg_t:
-		{
-			iter = &tv_iters.tag_macro;
-			break;
-		}
-		case tm_tag_class_t:
-		{
-			iter = &tv_iters.tag_class;
-			break;
-		}
-		case tm_tag_member_t:
-		case tm_tag_field_t:
-		{
-			iter = &tv_iters.tag_member;
-			break;
-		}
-		case tm_tag_typedef_t:
-		case tm_tag_enum_t:
-		{
-			iter = &tv_iters.tag_type;
-			break;
-		}
-		case tm_tag_union_t:
-		case tm_tag_struct_t:
-		{
-			iter = &tv_iters.tag_struct;
-			break;
-		}
-		case tm_tag_interface_t:
-			iter = &tv_iters.tag_interface;
-			break;
-		case tm_tag_variable_t:
-		{
-			iter = &tv_iters.tag_variable;
-			break;
-		}
-		case tm_tag_namespace_t:
-		case tm_tag_package_t:
-		{
-			iter = &tv_iters.tag_namespace;
-			break;
-		}
-		default:
-		{
-			iter = &tv_iters.tag_other;
-		}
-	}
-	if (G_LIKELY(iter->stamp != -1))
-		return iter;
-	else
+	if (group < 0)
 		return NULL;
+
+	return &tv_iters[group];
 }
 
 
 static GdkPixbuf *get_child_icon(GtkTreeStore *tree_store, GtkTreeIter *parent)
 {
 	GdkPixbuf *icon = NULL;
 
-	if (parent == &tv_iters.tag_other)
-	{
-		return g_object_ref(symbols_icons[ICON_VAR].pixbuf);
-	}
 	/* copy parent icon */
 	gtk_tree_model_get(GTK_TREE_MODEL(tree_store), parent,
 		SYMBOLS_COLUMN_ICON, &icon, -1);
@@ -1493,10 +977,8 @@ static void update_tree_tags(GeanyDocument *doc, GList **tags)
 		TMTag *tag = item->data;
 		GtkTreeIter *parent;
 
-		parent = get_tag_type_iter(tag->type);
-		if (G_UNLIKELY(! parent))
-			geany_debug("Missing symbol-tree parent iter for type %d!", tag->type);
-		else
+		parent = get_tag_type_iter(tag->lang, tag->type);
+		if (parent)
 		{
 			gboolean expand;
 			const gchar *name;
@@ -1899,38 +1381,18 @@ static void on_goto_popup_item_activate(GtkMenuItem *item, TMTag *tag)
 }
 
 
-/* FIXME: use the same icons as in the symbols tree defined in add_top_level_items() */
 static guint get_tag_class(const TMTag *tag)
 {
-	switch (tag->type)
-	{
-		case tm_tag_prototype_t:
-		case tm_tag_method_t:
-		case tm_tag_function_t:
-			return ICON_METHOD;
-		case tm_tag_variable_t:
-		case tm_tag_externvar_t:
-			return ICON_VAR;
-		case tm_tag_macro_t:
-		case tm_tag_macro_with_arg_t:
-			return ICON_MACRO;
-		case tm_tag_class_t:
-			return ICON_CLASS;
-		case tm_tag_member_t:
-		case tm_tag_field_t:
-			return ICON_MEMBER;
-		case tm_tag_typedef_t:
-		case tm_tag_enum_t:
-		case tm_tag_union_t:
-		case tm_tag_struct_t:
-			return ICON_STRUCT;
-		case tm_tag_namespace_t:
-		case tm_tag_package_t:
-			return ICON_NAMESPACE;
-		default:
-			break;
+	gint group = tm_parser_get_sidebar_group(tag->lang, tag->type);
+
+	if (group >= 0)
+	{
+		guint icon_id;
+		if (tm_parser_get_sidebar_info(tag->lang, group, &icon_id))
+			return icon_id;
 	}
-	return ICON_STRUCT;
+
+	return TM_ICON_STRUCT;
 }
 
 


Modified: src/tagmanager/tm_ctags.c
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -69,7 +69,7 @@ static void enable_kinds_and_roles()
 {
 	TMParserType lang;
 
-	for (lang = 0; lang < countParsers(); lang++)
+	for (lang = 0; lang < (gint)countParsers(); lang++)
 	{
 		guint kind_num = countLanguageKinds(lang);
 		guint kind;


Modified: src/tagmanager/tm_parser.c
1138 lines changed, 754 insertions(+), 384 deletions(-)
===================================================================
@@ -23,6 +23,12 @@
 
 #include <string.h>
 
+#include "config.h"
+
+
+/* Only for the command-line xgettext tool to find translatable strings.
+ * The gettext() function is invoked manually using glib g_dgettext() */
+#define _(String) (String)
 
 typedef struct
 {
@@ -41,111 +47,162 @@ typedef struct
     TMTagType new_type;
 } TMSubparserMapEntry;
 
+typedef struct
+{
+    const gchar *name;
+    guint icon;
+    TMTagType  types;
+} TMParserMapGroup;
 
 static GHashTable *subparser_map = NULL;
 
-#define COMMON_C \
-	{'d', tm_tag_macro_t}, \
-	{'e', tm_tag_enumerator_t}, \
-	{'f', tm_tag_function_t}, \
-	{'g', tm_tag_enum_t}, \
-	{'m', tm_tag_member_t}, \
-	{'p', tm_tag_prototype_t}, \
-	{'s', tm_tag_struct_t}, \
-	{'t', tm_tag_typedef_t}, \
-	{'u', tm_tag_union_t}, \
-	{'v', tm_tag_variable_t}, \
-	{'x', tm_tag_externvar_t},
-
-/* Old C parser, also used by GLSL and Ferite */
-static TMParserMapEntry map_C_old_parser[] = {
-	COMMON_C
-	{'c', tm_tag_class_t},
-	{'n', tm_tag_namespace_t},
-};
 
-# define COMMON_C_NEW_PARSER \
-	{'h', tm_tag_undef_t}, \
-	{'l', tm_tag_undef_t}, \
-	{'z', tm_tag_undef_t}, \
-	{'L', tm_tag_undef_t}, \
-	{'D', tm_tag_undef_t},
+#define COMMON_C \
+	{'d', tm_tag_macro_t},       /* macro */      \
+	{'e', tm_tag_enumerator_t},  /* enumerator */ \
+	{'f', tm_tag_function_t},    /* function */   \
+	{'g', tm_tag_enum_t},        /* enum */       \
+	{'m', tm_tag_member_t},      /* member */     \
+	{'p', tm_tag_prototype_t},   /* prototype */  \
+	{'s', tm_tag_struct_t},      /* struct */     \
+	{'t', tm_tag_typedef_t},     /* typedef */    \
+	{'u', tm_tag_union_t},       /* union */      \
+	{'v', tm_tag_variable_t},    /* variable */   \
+	{'x', tm_tag_externvar_t},   /* externvar */  \
+	{'h', tm_tag_undef_t},       /* header */     \
+	{'l', tm_tag_undef_t},       /* local */      \
+	{'z', tm_tag_undef_t},       /* parameter */  \
+	{'L', tm_tag_undef_t},       /* label */      \
+	{'D', tm_tag_undef_t},       /* macroparam */
 
 static TMParserMapEntry map_C[] = {
 	COMMON_C
-	COMMON_C_NEW_PARSER
+};
+/* Used also by other languages than C - keep all the tm_tag_* here even though
+ * they aren't used by C as they might be used by some other language */
+static TMParserMapGroup group_C[] = {
+	{_("Namespaces"), TM_ICON_NAMESPACE, tm_tag_namespace_t | tm_tag_package_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_prototype_t | tm_tag_method_t | tm_tag_function_t},
+	{_("Members"), TM_ICON_MEMBER, tm_tag_member_t | tm_tag_field_t},
+	{_("Structs"), TM_ICON_STRUCT, tm_tag_union_t | tm_tag_struct_t},
+	{_("Typedefs / Enums"), TM_ICON_STRUCT, tm_tag_typedef_t | tm_tag_enum_t},
+	{_("Macros"), TM_ICON_MACRO, tm_tag_macro_t | tm_tag_macro_with_arg_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t | tm_tag_enumerator_t},
+	{_("Extern Variables"), TM_ICON_VAR, tm_tag_externvar_t},
+	{_("Other"), TM_ICON_OTHER, tm_tag_other_t},
 };
 
 static TMParserMapEntry map_CPP[] = {
 	COMMON_C
-	COMMON_C_NEW_PARSER
-
-	{'c', tm_tag_class_t},
-	{'n', tm_tag_namespace_t},
-	{'A', tm_tag_undef_t},
-	{'N', tm_tag_undef_t},
-	{'U', tm_tag_undef_t},
-	{'Z', tm_tag_undef_t},
+	{'c', tm_tag_class_t},      // class
+	{'n', tm_tag_namespace_t},  // namespace
+	{'A', tm_tag_undef_t},      // alias
+	{'N', tm_tag_undef_t},      // name
+	{'U', tm_tag_undef_t},      // using
+	{'Z', tm_tag_undef_t},      // tparam
 };
+#define group_CPP group_C
 
 static TMParserMapEntry map_JAVA[] = {
-	{'c', tm_tag_class_t},
-	{'f', tm_tag_field_t},
-	{'i', tm_tag_interface_t},
-	{'m', tm_tag_method_t},
-	{'p', tm_tag_package_t},
-	{'e', tm_tag_enumerator_t},
-	{'g', tm_tag_enum_t},
+	{'c', tm_tag_class_t},      // class
+	{'f', tm_tag_field_t},      // field
+	{'i', tm_tag_interface_t},  // interface
+	{'m', tm_tag_method_t},     // method
+	{'p', tm_tag_package_t},    // package
+	{'e', tm_tag_enumerator_t}, // enumConstant
+	{'g', tm_tag_enum_t},       // enum
+};
+static TMParserMapGroup group_JAVA[] = {
+	{_("Package"), TM_ICON_NAMESPACE, tm_tag_package_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Methods"), TM_ICON_METHOD, tm_tag_method_t},
+	{_("Members"), TM_ICON_MEMBER, tm_tag_field_t},
+	{_("Enums"), TM_ICON_STRUCT, tm_tag_enum_t},
+	{_("Other"), TM_ICON_VAR, tm_tag_enumerator_t},
 };
 
+// no scope information
 static TMParserMapEntry map_MAKEFILE[] = {
-	{'m', tm_tag_macro_t},
-	{'t', tm_tag_function_t},
-	{'I', tm_tag_undef_t},
+	{'m', tm_tag_macro_t},     // macro
+	{'t', tm_tag_function_t},  // target
+	{'I', tm_tag_undef_t},     // makefile
+};
+static TMParserMapGroup group_MAKEFILE[] = {
+	{_("Targets"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Macros"), TM_ICON_MACRO, tm_tag_macro_t},
 };
 
 static TMParserMapEntry map_PASCAL[] = {
-	{'f', tm_tag_function_t},
-	{'p', tm_tag_function_t},
+	{'f', tm_tag_function_t},  // function
+	{'p', tm_tag_function_t},  // procedure
+};
+static TMParserMapGroup group_PASCAL[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
 };
 
+// no scope information
 static TMParserMapEntry map_PERL[] = {
-	{'c', tm_tag_enum_t},
-	{'f', tm_tag_other_t},
-	{'l', tm_tag_macro_t},
-	{'p', tm_tag_package_t},
-	{'s', tm_tag_function_t},
-	{'d', tm_tag_prototype_t},
-	{'M', tm_tag_undef_t},
+	{'c', tm_tag_enum_t},       // constant
+	{'f', tm_tag_other_t},      // format
+	{'l', tm_tag_macro_t},      // label
+	{'p', tm_tag_package_t},    // package
+	{'s', tm_tag_function_t},   // subroutine
+	{'d', tm_tag_prototype_t},  // subroutineDeclaration
+	{'M', tm_tag_undef_t},      // module
+};
+static TMParserMapGroup group_PERL[] = {
+	{_("Package"), TM_ICON_NAMESPACE, tm_tag_package_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t | tm_tag_prototype_t},
+	{_("Labels"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Constants"), TM_ICON_NONE, tm_tag_enum_t},
+	{_("Other"), TM_ICON_OTHER, tm_tag_other_t},
 };
 
 static TMParserMapEntry map_PHP[] = {
-	{'c', tm_tag_class_t},
-	{'d', tm_tag_macro_t},
-	{'f', tm_tag_function_t},
-	{'i', tm_tag_interface_t},
-	{'l', tm_tag_undef_t},
-	{'n', tm_tag_namespace_t},
-	{'t', tm_tag_struct_t},
-	{'v', tm_tag_variable_t},
-	{'a', tm_tag_undef_t},
+	{'c', tm_tag_class_t},      // class
+	{'d', tm_tag_macro_t},      // define
+	{'f', tm_tag_function_t},   // function
+	{'i', tm_tag_interface_t},  // interface
+	{'l', tm_tag_undef_t},      // local
+	{'n', tm_tag_namespace_t},  // namespace
+	{'t', tm_tag_struct_t},     // trait
+	{'v', tm_tag_variable_t},   // variable
+	{'a', tm_tag_undef_t},      // alias
+};
+static TMParserMapGroup group_PHP[] = {
+	{_("Namespaces"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Constants"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Traits"), TM_ICON_STRUCT, tm_tag_struct_t},
 };
 
 static TMParserMapEntry map_PYTHON[] = {
-	{'c', tm_tag_class_t},
-	{'f', tm_tag_function_t},
-	{'m', tm_tag_method_t},
-	{'v', tm_tag_variable_t},
-	{'I', tm_tag_externvar_t},
-	{'i', tm_tag_externvar_t},
+	{'c', tm_tag_class_t},      // class
+	{'f', tm_tag_function_t},   // function
+	{'m', tm_tag_method_t},     // member
+	{'v', tm_tag_variable_t},   // variable
+	{'I', tm_tag_externvar_t},  // namespace
+	{'i', tm_tag_externvar_t},  // module
     /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
      * so we can jump to the real implementation (if known) instead of to the import statement */
-	{'x', tm_tag_externvar_t},
-	{'z', tm_tag_undef_t},
-	{'l', tm_tag_undef_t},
+	{'x', tm_tag_externvar_t},  // unknown
+	{'z', tm_tag_undef_t},      // parameter
+	{'l', tm_tag_undef_t},      // local
+};
+static TMParserMapGroup group_PYTHON[] = {
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Methods"), TM_ICON_MACRO, tm_tag_method_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Imports"), TM_ICON_NAMESPACE, tm_tag_externvar_t},
 };
 
-/* different parser than tex.c from universal-ctags */
 static TMParserMapEntry map_LATEX[] = {
 	{'f', tm_tag_function_t},
 	{'c', tm_tag_class_t},
@@ -155,66 +212,104 @@ static TMParserMapEntry map_LATEX[] = {
 	{'n', tm_tag_namespace_t},
 	{'s', tm_tag_struct_t},
 };
+static TMParserMapGroup group_LATEX[] = {
+	{_("Command"), TM_ICON_NONE, tm_tag_function_t},
+	{_("Environment"), TM_ICON_NONE, tm_tag_class_t},
+	{_("Section"), TM_ICON_NONE, tm_tag_member_t},
+	{_("Subsection"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Subsubsection"), TM_ICON_NONE, tm_tag_variable_t},
+	{_("Label"), TM_ICON_NONE, tm_tag_struct_t},
+	{_("Chapter"), TM_ICON_NONE, tm_tag_namespace_t},
+};
+
+// no scope information
 static TMParserMapEntry map_BIBTEX[] = {
-	{'a', tm_tag_function_t},
-	{'b', tm_tag_class_t},
-	{'B', tm_tag_class_t},
-	{'c', tm_tag_member_t},
-	{'i', tm_tag_macro_t},
-	{'I', tm_tag_macro_t},
-	{'j', tm_tag_member_t},
-	{'m', tm_tag_other_t},
-	{'M', tm_tag_variable_t},
-	{'n', tm_tag_other_t},
-	{'p', tm_tag_variable_t},
-	{'P', tm_tag_class_t},
-	{'s', tm_tag_namespace_t},
-	{'t', tm_tag_other_t},
-	{'u', tm_tag_externvar_t},
+	{'a', tm_tag_function_t},   // article
+	{'b', tm_tag_class_t},      // book
+	{'B', tm_tag_class_t},      // booklet
+	{'c', tm_tag_member_t},     // conference
+	{'i', tm_tag_macro_t},      // inbook
+	{'I', tm_tag_macro_t},      // incollection
+	{'j', tm_tag_member_t},     // inproceedings
+	{'m', tm_tag_other_t},      // manual
+	{'M', tm_tag_variable_t},   // mastersthesis
+	{'n', tm_tag_other_t},      // misc
+	{'p', tm_tag_variable_t},   // phdthesis
+	{'P', tm_tag_class_t},      // proceedings
+	{'s', tm_tag_namespace_t},  // string
+	{'t', tm_tag_other_t},      // techreport
+	{'u', tm_tag_externvar_t},  // unpublished
+};
+static TMParserMapGroup group_BIBTEX[] = {
+	{_("Articles"), TM_ICON_NONE, tm_tag_function_t},
+	{_("Book Chapters"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Books & Conference Proceedings"), TM_ICON_NONE, tm_tag_class_t},
+	{_("Conference Papers"), TM_ICON_NONE, tm_tag_member_t},
+	{_("Theses"), TM_ICON_NONE, tm_tag_variable_t},
+	{_("Strings"), TM_ICON_NONE, tm_tag_namespace_t},
+	{_("Unpublished"), TM_ICON_NONE, tm_tag_externvar_t},
+	{_("Other"), TM_ICON_NONE, tm_tag_other_t},
 };
 
 static TMParserMapEntry map_ASM[] = {
-	{'d', tm_tag_macro_t},
-	{'l', tm_tag_namespace_t},
-	{'m', tm_tag_function_t},
-	{'t', tm_tag_struct_t},
-	{'s', tm_tag_undef_t},
+	{'d', tm_tag_macro_t},      // define
+	{'l', tm_tag_namespace_t},  // label
+	{'m', tm_tag_function_t},   // macro
+	{'t', tm_tag_struct_t},     // type
+	{'s', tm_tag_undef_t},      // section
+};
+static TMParserMapGroup group_ASM[] = {
+	{_("Labels"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Macros"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Defines"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Types"), TM_ICON_STRUCT, tm_tag_struct_t},
 };
 
-/* not in universal-ctags */
 static TMParserMapEntry map_CONF[] = {
-	{'s', tm_tag_namespace_t},
-	{'k', tm_tag_macro_t},
+	{'s', tm_tag_namespace_t},  // section
+	{'k', tm_tag_macro_t},      // key
+};
+static TMParserMapGroup group_CONF[] = {
+	{_("Sections"), TM_ICON_OTHER, tm_tag_namespace_t},
+	{_("Keys"), TM_ICON_VAR, tm_tag_macro_t},
 };
 
 static TMParserMapEntry map_SQL[] = {
-	{'c', tm_tag_undef_t},
-	{'d', tm_tag_prototype_t},
-	{'f', tm_tag_function_t},
-	{'E', tm_tag_field_t},
-	{'l', tm_tag_undef_t},
-	{'L', tm_tag_undef_t},
-	{'P', tm_tag_package_t},
-	{'p', tm_tag_namespace_t},
-	{'r', tm_tag_undef_t},
-	{'s', tm_tag_undef_t},
-	{'t', tm_tag_class_t},
-	{'T', tm_tag_macro_t},
-	{'v', tm_tag_variable_t},
-	{'i', tm_tag_struct_t},
-	{'e', tm_tag_undef_t},
-	{'U', tm_tag_undef_t},
-	{'R', tm_tag_undef_t},
-	{'D', tm_tag_undef_t},
-	{'V', tm_tag_member_t},
-	{'n', tm_tag_undef_t},
-	{'x', tm_tag_undef_t},
-	{'y', tm_tag_undef_t},
-	{'z', tm_tag_undef_t},
-	{'C', tm_tag_undef_t},
-};
-
-/* not in universal-ctags */
+	{'c', tm_tag_undef_t},      // cursor
+	{'d', tm_tag_prototype_t},  // prototype
+	{'f', tm_tag_function_t},   // function
+	{'E', tm_tag_field_t},      // field
+	{'l', tm_tag_undef_t},      // local
+	{'L', tm_tag_undef_t},      // label
+	{'P', tm_tag_package_t},    // package
+	{'p', tm_tag_namespace_t},  // procedure
+	{'r', tm_tag_undef_t},      // record
+	{'s', tm_tag_undef_t},      // subtype
+	{'t', tm_tag_class_t},      // table
+	{'T', tm_tag_macro_t},      // trigger
+	{'v', tm_tag_variable_t},   // variable
+	{'i', tm_tag_struct_t},     // index
+	{'e', tm_tag_undef_t},      // event
+	{'U', tm_tag_undef_t},      // publication
+	{'R', tm_tag_undef_t},      // service
+	{'D', tm_tag_undef_t},      // domain
+	{'V', tm_tag_member_t},     // view
+	{'n', tm_tag_undef_t},      // synonym
+	{'x', tm_tag_undef_t},      // mltable
+	{'y', tm_tag_undef_t},      // mlconn
+	{'z', tm_tag_undef_t},      // mlprop
+	{'C', tm_tag_undef_t},      // ccflag
+};
+static TMParserMapGroup group_SQL[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t | tm_tag_prototype_t},
+	{_("Procedures"), TM_ICON_NAMESPACE, tm_tag_namespace_t | tm_tag_package_t},
+	{_("Indexes"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Tables"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Triggers"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Views"), TM_ICON_VAR, tm_tag_field_t | tm_tag_member_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+};
+
 static TMParserMapEntry map_DOCBOOK[] = {
 	{'f', tm_tag_function_t},
 	{'c', tm_tag_class_t},
@@ -223,70 +318,119 @@ static TMParserMapEntry map_DOCBOOK[] = {
 	{'v', tm_tag_variable_t},
 	{'s', tm_tag_struct_t},
 };
+static TMParserMapGroup group_DOCBOOK[] = {
+	{_("Chapter"), TM_ICON_NONE, tm_tag_function_t},
+	{_("Section"), TM_ICON_NONE, tm_tag_class_t},
+	{_("Sect1"), TM_ICON_NONE, tm_tag_member_t},
+	{_("Sect2"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Sect3"), TM_ICON_NONE, tm_tag_variable_t},
+	{_("Appendix"), TM_ICON_NONE, tm_tag_struct_t},
+};
 
+// no scope information
 static TMParserMapEntry map_ERLANG[] = {
-	{'d', tm_tag_macro_t},
-	{'f', tm_tag_function_t},
-	{'m', tm_tag_undef_t},
-	{'r', tm_tag_struct_t},
-	{'t', tm_tag_typedef_t},
+	{'d', tm_tag_macro_t},     // macro
+	{'f', tm_tag_function_t},  // function
+	{'m', tm_tag_undef_t},     // module
+	{'r', tm_tag_struct_t},    // record
+	{'t', tm_tag_typedef_t},   // type
+};
+static TMParserMapGroup group_ERLANG[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Structs"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Typedefs / Enums"), TM_ICON_STRUCT, tm_tag_typedef_t},
+	{_("Macros"), TM_ICON_MACRO, tm_tag_macro_t},
 };
 
+// no scope information
 static TMParserMapEntry map_CSS[] = {
-	{'c', tm_tag_class_t},
-	{'s', tm_tag_struct_t},
-	{'i', tm_tag_variable_t},
+	{'c', tm_tag_class_t},     // class
+	{'s', tm_tag_struct_t},    // selector
+	{'i', tm_tag_variable_t},  // id
+};
+static TMParserMapGroup group_CSS[] = {
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("ID Selectors"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Type Selectors"), TM_ICON_STRUCT, tm_tag_struct_t},
 };
 
 static TMParserMapEntry map_RUBY[] = {
-	{'c', tm_tag_class_t},
-	{'f', tm_tag_method_t},
-	{'m', tm_tag_namespace_t},
-	{'S', tm_tag_member_t},
-	{'C', tm_tag_undef_t},
-	{'A', tm_tag_undef_t},
-	{'a', tm_tag_undef_t},
-	{'L', tm_tag_undef_t},
+	{'c', tm_tag_class_t},      // class
+	{'f', tm_tag_method_t},     // method
+	{'m', tm_tag_namespace_t},  // module
+	{'S', tm_tag_member_t},     // singletonMethod
+	{'C', tm_tag_undef_t},      // constant
+	{'A', tm_tag_undef_t},      // accessor
+	{'a', tm_tag_undef_t},      // alias
+	{'L', tm_tag_undef_t},      // library
+};
+static TMParserMapGroup group_RUBY[] = {
+	{_("Modules"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Singletons"), TM_ICON_STRUCT, tm_tag_member_t},
+	{_("Methods"), TM_ICON_METHOD, tm_tag_method_t},
 };
 
 static TMParserMapEntry map_TCL[] = {
-	{'c', tm_tag_class_t},
-	{'m', tm_tag_member_t},
-	{'p', tm_tag_function_t},
-	{'n', tm_tag_namespace_t},
+	{'c', tm_tag_class_t},      // class
+	{'m', tm_tag_member_t},     // method
+	{'p', tm_tag_function_t},   // procedure
+	{'n', tm_tag_namespace_t},  // module
+};
+static TMParserMapGroup group_TCL[] = {
+	{_("Namespaces"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Methods"), TM_ICON_METHOD, tm_tag_member_t},
+	{_("Procedures"), TM_ICON_OTHER, tm_tag_function_t},
 };
 
 static TMParserMapEntry map_SH[] = {
-	{'a', tm_tag_undef_t},
-	{'f', tm_tag_function_t},
-	{'s', tm_tag_undef_t},
-	{'h', tm_tag_undef_t},
+	{'a', tm_tag_undef_t},     // alias
+	{'f', tm_tag_function_t},  // function
+	{'s', tm_tag_undef_t},     // script
+	{'h', tm_tag_undef_t},     // heredoc
+};
+static TMParserMapGroup group_SH[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
 };
 
 static TMParserMapEntry map_D[] = {
-	{'c', tm_tag_class_t},
-	{'e', tm_tag_enumerator_t},
-	{'f', tm_tag_function_t},
-	{'g', tm_tag_enum_t},
-	{'i', tm_tag_interface_t},
-	{'m', tm_tag_member_t},
-	{'n', tm_tag_namespace_t},
-	{'p', tm_tag_prototype_t},
-	{'s', tm_tag_struct_t},
-	{'t', tm_tag_typedef_t},
-	{'u', tm_tag_union_t},
-	{'v', tm_tag_variable_t},
-	{'x', tm_tag_externvar_t},
+	{'c', tm_tag_class_t},       // class
+	{'e', tm_tag_enumerator_t},  // enumerator
+	{'f', tm_tag_function_t},    // function
+	{'g', tm_tag_enum_t},        // enum
+	{'i', tm_tag_interface_t},   // interface
+	{'m', tm_tag_member_t},      // member
+	{'n', tm_tag_namespace_t},   // namespace
+	{'p', tm_tag_prototype_t},   // prototype
+	{'s', tm_tag_struct_t},      // struct
+	{'t', tm_tag_typedef_t},     // typedef
+	{'u', tm_tag_union_t},       // union
+	{'v', tm_tag_variable_t},    // variable
+	{'x', tm_tag_externvar_t},   // externvar
+};
+static TMParserMapGroup group_D[] = {
+	{_("Module"), TM_ICON_NONE, tm_tag_namespace_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t | tm_tag_prototype_t},
+	{_("Members"), TM_ICON_MEMBER, tm_tag_member_t},
+	{_("Structs"), TM_ICON_STRUCT, tm_tag_struct_t | tm_tag_union_t},
+	{_("Typedefs / Enums"), TM_ICON_STRUCT, tm_tag_typedef_t | tm_tag_enum_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t | tm_tag_enumerator_t},
+	{_("Extern Variables"), TM_ICON_VAR, tm_tag_externvar_t},
 };
 
 static TMParserMapEntry map_DIFF[] = {
-	{'m', tm_tag_function_t},
-	{'n', tm_tag_function_t},
-	{'d', tm_tag_function_t},
-	{'h', tm_tag_undef_t},
+	{'m', tm_tag_function_t},  // modifiedFile
+	{'n', tm_tag_function_t},  // newFile
+	{'d', tm_tag_function_t},  // deletedFile
+	{'h', tm_tag_undef_t},     // hunk
+};
+static TMParserMapGroup group_DIFF[] = {
+	{_("Files"), TM_ICON_NONE, tm_tag_function_t},
 };
 
-/* different parser than in universal-ctags */
 static TMParserMapEntry map_VHDL[] = {
 	{'c', tm_tag_variable_t},
 	{'t', tm_tag_typedef_t},
@@ -304,333 +448,509 @@ static TMParserMapEntry map_VHDL[] = {
 	{'b', tm_tag_member_t},
 	{'A', tm_tag_typedef_t},
 };
+static TMParserMapGroup group_VHDL[] = {
+	{_("Package"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Entities"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Architectures"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Types"), TM_ICON_OTHER, tm_tag_typedef_t},
+	{_("Functions / Procedures"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Variables / Signals"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Processes / Blocks / Components"), TM_ICON_MEMBER, tm_tag_member_t},
+};
 
 static TMParserMapEntry map_LUA[] = {
-	{'f', tm_tag_function_t},
-	{'X', tm_tag_undef_t},
+	{'f', tm_tag_function_t},  // function
+	{'X', tm_tag_undef_t},     // unknown
+};
+static TMParserMapGroup group_LUA[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
 };
 
 static TMParserMapEntry map_JAVASCRIPT[] = {
-	{'f', tm_tag_function_t},
-	{'c', tm_tag_class_t},
-	{'m', tm_tag_method_t},
-	{'p', tm_tag_member_t},
-	{'C', tm_tag_macro_t},
-	{'v', tm_tag_variable_t},
-	{'g', tm_tag_function_t},
-	{'G', tm_tag_undef_t},
-	{'S', tm_tag_undef_t},
-	{'M', tm_tag_undef_t},
+	{'f', tm_tag_function_t},  // function
+	{'c', tm_tag_class_t},     // class
+	{'m', tm_tag_method_t},    // method
+	{'p', tm_tag_member_t},    // property
+	{'C', tm_tag_macro_t},     // constant
+	{'v', tm_tag_variable_t},  // variable
+	{'g', tm_tag_function_t},  // generator
+	{'G', tm_tag_undef_t},     // getter
+	{'S', tm_tag_undef_t},     // setter
+	{'M', tm_tag_undef_t},     // field
+};
+static TMParserMapGroup group_JAVASCRIPT[] = {
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t | tm_tag_method_t},
+	{_("Members"), TM_ICON_MEMBER, tm_tag_member_t},
+	{_("Macros"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
 };
 
+// no scope information
 static TMParserMapEntry map_HASKELL[] = {
-	{'t', tm_tag_typedef_t},
-	{'c', tm_tag_macro_t},
-	{'f', tm_tag_function_t},
-	{'m', tm_tag_namespace_t},
+	{'t', tm_tag_typedef_t},    // type
+	{'c', tm_tag_macro_t},      // constructor
+	{'f', tm_tag_function_t},   // function
+	{'m', tm_tag_namespace_t},  // module
+};
+static TMParserMapGroup group_HASKELL[] = {
+	{_("Module"), TM_ICON_NONE, tm_tag_namespace_t},
+	{_("Types"), TM_ICON_NONE, tm_tag_typedef_t},
+	{_("Type constructors"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
 };
 
 static TMParserMapEntry map_CSHARP[] = {
-	{'c', tm_tag_class_t},
-	{'d', tm_tag_macro_t},
-	{'e', tm_tag_enumerator_t},
-	{'E', tm_tag_undef_t},
-	{'f', tm_tag_field_t},
-	{'g', tm_tag_enum_t},
-	{'i', tm_tag_interface_t},
-	{'l', tm_tag_undef_t},
-	{'m', tm_tag_method_t},
-	{'n', tm_tag_namespace_t},
-	{'p', tm_tag_undef_t},
-	{'s', tm_tag_struct_t},
-	{'t', tm_tag_typedef_t},
+	{'c', tm_tag_class_t},       // class
+	{'d', tm_tag_macro_t},       // macro
+	{'e', tm_tag_enumerator_t},  // enumerator
+	{'E', tm_tag_undef_t},       // event
+	{'f', tm_tag_field_t},       // field
+	{'g', tm_tag_enum_t},        // enum
+	{'i', tm_tag_interface_t},   // interface
+	{'l', tm_tag_undef_t},       // local
+	{'m', tm_tag_method_t},      // method
+	{'n', tm_tag_namespace_t},   // namespace
+	{'p', tm_tag_undef_t},       // property
+	{'s', tm_tag_struct_t},      // struct
+	{'t', tm_tag_typedef_t},     // typedef
 };
+#define group_CSHARP group_C
 
+// no scope information
 static TMParserMapEntry map_FREEBASIC[] = {
-	{'c', tm_tag_macro_t},
-	{'f', tm_tag_function_t},
-	{'l', tm_tag_namespace_t},
-	{'t', tm_tag_struct_t},
-	{'v', tm_tag_variable_t},
-	{'g', tm_tag_externvar_t},
+	{'c', tm_tag_macro_t},      // constant
+	{'f', tm_tag_function_t},   // function
+	{'l', tm_tag_namespace_t},  // label
+	{'t', tm_tag_struct_t},     // type
+	{'v', tm_tag_variable_t},   // variable
+	{'g', tm_tag_externvar_t},  // enum
+};
+static TMParserMapGroup group_FREEBASIC[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t | tm_tag_externvar_t},
+	{_("Constants"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Types"), TM_ICON_NAMESPACE, tm_tag_struct_t},
+	{_("Labels"), TM_ICON_MEMBER, tm_tag_namespace_t},
 };
 
+// no scope information
 static TMParserMapEntry map_HAXE[] = {
-	{'m', tm_tag_method_t},
-	{'c', tm_tag_class_t},
-	{'e', tm_tag_enum_t},
-	{'v', tm_tag_variable_t},
-	{'i', tm_tag_interface_t},
-	{'t', tm_tag_typedef_t},
+	{'m', tm_tag_method_t},     // method
+	{'c', tm_tag_class_t},      // class
+	{'e', tm_tag_enum_t},       // enum
+	{'v', tm_tag_variable_t},   // variable
+	{'i', tm_tag_interface_t},  // interface
+	{'t', tm_tag_typedef_t},    // typedef
+};
+static TMParserMapGroup group_HAXE[] = {
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Methods"), TM_ICON_METHOD, tm_tag_method_t},
+	{_("Types"), TM_ICON_MACRO, tm_tag_typedef_t | tm_tag_enum_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
 };
 
 static TMParserMapEntry map_REST[] = {
-	{'c', tm_tag_namespace_t},
-	{'s', tm_tag_member_t},
-	{'S', tm_tag_macro_t},
-	{'t', tm_tag_variable_t},
-	{'C', tm_tag_undef_t},
-	{'T', tm_tag_undef_t},
-	{'d', tm_tag_undef_t},
+	{'c', tm_tag_namespace_t},  // chapter
+	{'s', tm_tag_member_t},     // section
+	{'S', tm_tag_macro_t},      // subsection
+	{'t', tm_tag_variable_t},   // subsubsection
+	{'C', tm_tag_undef_t},      // citation
+	{'T', tm_tag_undef_t},      // target
+	{'d', tm_tag_undef_t},      // substdef
+};
+static TMParserMapGroup group_REST[] = {
+	{_("Chapter"), TM_ICON_NONE, tm_tag_namespace_t},
+	{_("Section"), TM_ICON_NONE, tm_tag_member_t},
+	{_("Subsection"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Subsubsection"), TM_ICON_NONE, tm_tag_variable_t},
 };
 
+// no scope information
 static TMParserMapEntry map_HTML[] = {
-	{'a', tm_tag_member_t},
-	{'c', tm_tag_undef_t},
-	{'h', tm_tag_namespace_t},
-	{'i', tm_tag_class_t},
-	{'j', tm_tag_variable_t},
-	{'C', tm_tag_undef_t},
-	{'I', tm_tag_undef_t},
-	{'J', tm_tag_undef_t},
+	{'a', tm_tag_member_t},     // anchor
+	{'c', tm_tag_undef_t},      // class
+	{'h', tm_tag_namespace_t},  // heading1
+	{'i', tm_tag_class_t},      // heading2
+	{'j', tm_tag_variable_t},   // heading3
+	{'C', tm_tag_undef_t},      // stylesheet
+	{'I', tm_tag_undef_t},      // id
+	{'J', tm_tag_undef_t},      // script
+};
+static TMParserMapGroup group_HTML[] = {
+	{_("Functions"), TM_ICON_NONE, tm_tag_function_t},  // javascript functions from subparser
+	{_("Anchors"), TM_ICON_NONE, tm_tag_member_t},
+	{_("H1 Headings"), TM_ICON_NONE, tm_tag_namespace_t},
+	{_("H2 Headings"), TM_ICON_NONE, tm_tag_class_t},
+	{_("H3 Headings"), TM_ICON_NONE, tm_tag_variable_t},
 };
 
 static TMSubparserMapEntry subparser_HTML_javascript_map[] = {
 	{tm_tag_function_t, tm_tag_function_t},
 };
 
 static TMParserMapEntry map_F77[] = {
-	{'b', tm_tag_undef_t},
-	{'c', tm_tag_macro_t},
-	{'e', tm_tag_undef_t},
-	{'f', tm_tag_function_t},
-	{'i', tm_tag_interface_t},
-	{'k', tm_tag_member_t},
-	{'l', tm_tag_undef_t},
-	{'L', tm_tag_undef_t},
-	{'m', tm_tag_namespace_t},
-	{'n', tm_tag_undef_t},
-	{'p', tm_tag_struct_t},
-	{'s', tm_tag_method_t},
-	{'t', tm_tag_class_t},
-	{'v', tm_tag_variable_t},
-	{'E', tm_tag_enum_t},
-	{'N', tm_tag_enumerator_t},
+	{'b', tm_tag_undef_t},       // blockData
+	{'c', tm_tag_macro_t},       // common
+	{'e', tm_tag_undef_t},       // entry
+	{'f', tm_tag_function_t},    // function
+	{'i', tm_tag_interface_t},   // interface
+	{'k', tm_tag_member_t},      // component
+	{'l', tm_tag_undef_t},       // label
+	{'L', tm_tag_undef_t},       // local
+	{'m', tm_tag_namespace_t},   // module
+	{'n', tm_tag_undef_t},       // namelist
+	{'p', tm_tag_struct_t},      // program
+	{'s', tm_tag_method_t},      // subroutine
+	{'t', tm_tag_class_t},       // type
+	{'v', tm_tag_variable_t},    // variable
+	{'E', tm_tag_enum_t},        // enum
+	{'N', tm_tag_enumerator_t},  // enumerator
+};
+static TMParserMapGroup group_F77[] = {
+	{_("Module"), TM_ICON_CLASS, tm_tag_namespace_t},
+	{_("Programs"), TM_ICON_CLASS, tm_tag_struct_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Functions / Subroutines"), TM_ICON_METHOD, tm_tag_function_t | tm_tag_method_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t | tm_tag_enumerator_t},
+	{_("Types"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Components"), TM_ICON_MEMBER, tm_tag_member_t},
+	{_("Blocks"), TM_ICON_MEMBER, tm_tag_macro_t},
+	{_("Enums"), TM_ICON_STRUCT, tm_tag_enum_t},
 };
 
 #define map_FORTRAN map_F77
+#define group_FORTRAN group_F77
 
-/* different parser than in universal-ctags */
 static TMParserMapEntry map_MATLAB[] = {
-	{'f', tm_tag_function_t},
-	{'s', tm_tag_struct_t},
+	{'f', tm_tag_function_t},  // function
+	{'s', tm_tag_struct_t},    // struct
+};
+static TMParserMapGroup group_MATLAB[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Structures"), TM_ICON_STRUCT, tm_tag_struct_t},
 };
 
 #define map_CUDA map_C
+#define group_CUDA group_C
 
-/* not in universal-ctags */
 static TMParserMapEntry map_VALA[] = {
-	{'c', tm_tag_class_t},
-	{'d', tm_tag_macro_t},
-	{'e', tm_tag_enumerator_t},
-	{'f', tm_tag_field_t},
-	{'g', tm_tag_enum_t},
-	{'i', tm_tag_interface_t},
-	{'l', tm_tag_undef_t},
-	{'m', tm_tag_method_t},
-	{'n', tm_tag_namespace_t},
-	{'p', tm_tag_undef_t},
-	{'S', tm_tag_undef_t},
-	{'s', tm_tag_struct_t},
+	{'c', tm_tag_class_t},       // class
+	{'d', tm_tag_macro_t},       // macro
+	{'e', tm_tag_enumerator_t},  // enumerator
+	{'f', tm_tag_field_t},       // field
+	{'g', tm_tag_enum_t},        // enum
+	{'i', tm_tag_interface_t},   // interface
+	{'l', tm_tag_undef_t},       // local
+	{'m', tm_tag_method_t},      // method
+	{'n', tm_tag_namespace_t},   // namespace
+	{'p', tm_tag_undef_t},       // property
+	{'S', tm_tag_undef_t},       // signal
+	{'s', tm_tag_struct_t},      // struct
 };
+#define group_VALA group_C
 
-/* not in universal-ctags */
 static TMParserMapEntry map_ACTIONSCRIPT[] = {
-	{'f', tm_tag_function_t},
-	{'c', tm_tag_class_t},
-	{'i', tm_tag_interface_t},
-	{'P', tm_tag_package_t},
-	{'m', tm_tag_method_t},
-	{'p', tm_tag_member_t},
-	{'v', tm_tag_variable_t},
-	{'l', tm_tag_variable_t},
-	{'C', tm_tag_macro_t},
-	{'I', tm_tag_externvar_t},
-	{'x', tm_tag_other_t},
+	{'f', tm_tag_function_t},   // function
+	{'c', tm_tag_class_t},      // class
+	{'i', tm_tag_interface_t},  // interface
+	{'P', tm_tag_package_t},    // package
+	{'m', tm_tag_method_t},     // method
+	{'p', tm_tag_member_t},     // property
+	{'v', tm_tag_variable_t},   // variable
+	{'l', tm_tag_variable_t},   // localvar
+	{'C', tm_tag_macro_t},      // constant
+	{'I', tm_tag_externvar_t},  // import
+	{'x', tm_tag_other_t},      // mxtag
+};
+static TMParserMapGroup group_ACTIONSCRIPT[] = {
+	{_("Imports"), TM_ICON_NAMESPACE, tm_tag_externvar_t},
+	{_("Package"), TM_ICON_NAMESPACE, tm_tag_package_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t| tm_tag_method_t},
+	{_("Properties"), TM_ICON_MEMBER, tm_tag_member_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Constants"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Other"), TM_ICON_OTHER, tm_tag_other_t},
 };
 
 static TMParserMapEntry map_NSIS[] = {
-	{'s', tm_tag_namespace_t},
-	{'f', tm_tag_function_t},
-	{'v', tm_tag_variable_t},
-	{'d', tm_tag_undef_t},
-	{'m', tm_tag_undef_t},
-	{'S', tm_tag_undef_t},
-	{'p', tm_tag_undef_t},
-	{'l', tm_tag_undef_t},
-	{'i', tm_tag_undef_t},
+	{'s', tm_tag_namespace_t},  // section
+	{'f', tm_tag_function_t},   // function
+	{'v', tm_tag_variable_t},   // variable
+	{'d', tm_tag_undef_t},      // definition
+	{'m', tm_tag_undef_t},      // macro
+	{'S', tm_tag_undef_t},      // sectionGroup
+	{'p', tm_tag_undef_t},      // macroparam
+	{'l', tm_tag_undef_t},      // langstr
+	{'i', tm_tag_undef_t},      // script
+};
+static TMParserMapGroup group_NSIS[] = {
+	{_("Sections"), TM_ICON_OTHER, tm_tag_namespace_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
 };
 
-/* not in universal-ctags */
 static TMParserMapEntry map_MARKDOWN[] = {
 	{'v', tm_tag_variable_t},
 };
+static TMParserMapGroup group_MARKDOWN[] = {
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+};
 
 static TMParserMapEntry map_TXT2TAGS[] = {
-	{'s', tm_tag_member_t},
+	{'s', tm_tag_member_t},  // section
 };
+#define group_TXT2TAGS group_REST
 
+// no scope information
 static TMParserMapEntry map_ABC[] = {
-	{'s', tm_tag_member_t},
+	{'s', tm_tag_member_t},  // section
 };
+#define group_ABC group_REST
 
 static TMParserMapEntry map_VERILOG[] = {
-	{'c', tm_tag_variable_t},
-	{'e', tm_tag_typedef_t},
-	{'f', tm_tag_function_t},
-	{'m', tm_tag_class_t},
-	{'n', tm_tag_variable_t},
-	{'p', tm_tag_variable_t},
-	{'r', tm_tag_variable_t},
-	{'t', tm_tag_function_t},
-	{'b', tm_tag_undef_t},
-	{'i', tm_tag_undef_t},
+	{'c', tm_tag_variable_t},  // constant
+	{'e', tm_tag_typedef_t},   // event
+	{'f', tm_tag_function_t},  // function
+	{'m', tm_tag_class_t},     // module
+	{'n', tm_tag_variable_t},  // net
+	{'p', tm_tag_variable_t},  // port
+	{'r', tm_tag_variable_t},  // register
+	{'t', tm_tag_function_t},  // task
+	{'b', tm_tag_undef_t},     // block
+	{'i', tm_tag_undef_t},     // instance
+};
+static TMParserMapGroup group_VERILOG[] = {
+	{_("Events"), TM_ICON_MACRO, tm_tag_typedef_t},
+	{_("Modules"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Functions / Tasks"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
 };
 
 static TMParserMapEntry map_R[] = {
-	{'f', tm_tag_function_t},
-	{'l', tm_tag_other_t},
-	{'s', tm_tag_other_t},
-	{'g', tm_tag_undef_t},
-	{'v', tm_tag_undef_t},
-	{'z', tm_tag_undef_t},
-	{'c', tm_tag_undef_t},
-	{'L', tm_tag_undef_t},
-	{'d', tm_tag_undef_t},
-	{'n', tm_tag_undef_t},
+	{'f', tm_tag_function_t},  // function
+	{'l', tm_tag_other_t},     // library
+	{'s', tm_tag_other_t},     // source
+	{'g', tm_tag_undef_t},     // globalVar
+	{'v', tm_tag_undef_t},     // functionVar
+	{'z', tm_tag_undef_t},     // parameter
+	{'c', tm_tag_undef_t},     // vector
+	{'L', tm_tag_undef_t},     // list
+	{'d', tm_tag_undef_t},     // dataframe
+	{'n', tm_tag_undef_t},     // nameattr
+};
+static TMParserMapGroup group_R[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Other"), TM_ICON_NONE, tm_tag_other_t},
 };
 
 static TMParserMapEntry map_COBOL[] = {
-	{'d', tm_tag_variable_t},
-	{'D', tm_tag_interface_t},
-	{'f', tm_tag_function_t},
-	{'g', tm_tag_struct_t},
-	{'p', tm_tag_macro_t},
-	{'P', tm_tag_class_t},
-	{'s', tm_tag_namespace_t},
-	{'S', tm_tag_externvar_t},
+	{'f', tm_tag_function_t},   // fd
+	{'g', tm_tag_struct_t},     // group
+	{'P', tm_tag_class_t},      // program
+	{'s', tm_tag_namespace_t},  // section
+	{'D', tm_tag_interface_t},  // division
+	{'p', tm_tag_macro_t},      // paragraph
+	{'d', tm_tag_variable_t},   // data
+	{'S', tm_tag_externvar_t},  // sourcefile
+};
+static TMParserMapGroup group_COBOL[] = {
+	{_("Program"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("File"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Divisions"), TM_ICON_NAMESPACE, tm_tag_interface_t},
+	{_("Sections"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Paragraph"), TM_ICON_OTHER, tm_tag_macro_t},
+	{_("Group"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Data"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Copies"), TM_ICON_NAMESPACE, tm_tag_externvar_t},
 };
 
 static TMParserMapEntry map_OBJC[] = {
-	{'i', tm_tag_interface_t},
-	{'I', tm_tag_undef_t},
-	{'P', tm_tag_undef_t},
-	{'m', tm_tag_method_t},
-	{'c', tm_tag_class_t},
-	{'v', tm_tag_variable_t},
-	{'E', tm_tag_field_t},
-	{'f', tm_tag_function_t},
-	{'p', tm_tag_undef_t},
-	{'t', tm_tag_typedef_t},
-	{'s', tm_tag_struct_t},
-	{'e', tm_tag_enum_t},
-	{'M', tm_tag_macro_t},
-	{'C', tm_tag_undef_t},
+	{'i', tm_tag_interface_t},  // interface
+	{'I', tm_tag_undef_t},      // implementation
+	{'P', tm_tag_undef_t},      // protocol
+	{'m', tm_tag_method_t},     // method
+	{'c', tm_tag_class_t},      // class
+	{'v', tm_tag_variable_t},   // var
+	{'E', tm_tag_field_t},      // field
+	{'f', tm_tag_function_t},   // function
+	{'p', tm_tag_undef_t},      // property
+	{'t', tm_tag_typedef_t},    // typedef
+	{'s', tm_tag_struct_t},     // struct
+	{'e', tm_tag_enum_t},       // enum
+	{'M', tm_tag_macro_t},      // macro
+	{'C', tm_tag_undef_t},      // category
 };
+#define group_OBJC group_C
 
 static TMParserMapEntry map_ASCIIDOC[] = {
-	{'c', tm_tag_namespace_t},
-	{'s', tm_tag_member_t},
-	{'S', tm_tag_macro_t},
-	{'t', tm_tag_variable_t},
-	{'T', tm_tag_struct_t},
-	{'u', tm_tag_undef_t},
-	{'a', tm_tag_undef_t},
+	{'c', tm_tag_namespace_t},  //chapter
+	{'s', tm_tag_member_t},     //section
+	{'S', tm_tag_macro_t},      //subsection
+	{'t', tm_tag_variable_t},   //subsubsection
+	{'T', tm_tag_struct_t},     //l4subsection
+	{'u', tm_tag_undef_t},      //l5subsection
+	{'a', tm_tag_undef_t},      //anchor
+};
+static TMParserMapGroup group_ASCIIDOC[] = {
+	{_("Document"), TM_ICON_NONE, tm_tag_namespace_t},
+	{_("Section Level 1"), TM_ICON_NONE, tm_tag_member_t},
+	{_("Section Level 2"), TM_ICON_NONE, tm_tag_macro_t},
+	{_("Section Level 3"), TM_ICON_NONE, tm_tag_variable_t},
+	{_("Section Level 4"), TM_ICON_NONE, tm_tag_struct_t},
 };
 
+// no scope information
 static TMParserMapEntry map_ABAQUS[] = {
-	{'p', tm_tag_class_t},
-	{'a', tm_tag_member_t},
-	{'s', tm_tag_interface_t},
+	{'p', tm_tag_class_t},      // part
+	{'a', tm_tag_member_t},     // assembly
+	{'s', tm_tag_interface_t},  // step
+};
+static TMParserMapGroup group_ABAQUS[] = {
+	{_("Parts"), TM_ICON_NONE, tm_tag_class_t},
+	{_("Assembly"), TM_ICON_NONE, tm_tag_member_t},
+	{_("Steps"), TM_ICON_NONE, tm_tag_interface_t},
 };
 
 static TMParserMapEntry map_RUST[] = {
-	{'n', tm_tag_namespace_t},
-	{'s', tm_tag_struct_t},
-	{'i', tm_tag_interface_t},
-	{'c', tm_tag_class_t},
-	{'f', tm_tag_function_t},
-	{'g', tm_tag_enum_t},
-	{'t', tm_tag_typedef_t},
-	{'v', tm_tag_variable_t},
-	{'M', tm_tag_macro_t},
-	{'m', tm_tag_field_t},
-	{'e', tm_tag_enumerator_t},
-	{'P', tm_tag_method_t},
+	{'n', tm_tag_namespace_t},   // module
+	{'s', tm_tag_struct_t},      // struct
+	{'i', tm_tag_interface_t},   // interface
+	{'c', tm_tag_class_t},       // implementation
+	{'f', tm_tag_function_t},    // function
+	{'g', tm_tag_enum_t},        // enum
+	{'t', tm_tag_typedef_t},     // typedef
+	{'v', tm_tag_variable_t},    // variable
+	{'M', tm_tag_macro_t},       // macro
+	{'m', tm_tag_field_t},       // field
+	{'e', tm_tag_enumerator_t},  // enumerator
+	{'P', tm_tag_method_t},      // method
+};
+static TMParserMapGroup group_RUST[] = {
+	{_("Modules"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Structures"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Traits)"), TM_ICON_CLASS, tm_tag_interface_t},
+	{_("Implementations"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t | tm_tag_method_t},
+	{_("Typedefs / Enums"), TM_ICON_STRUCT, tm_tag_typedef_t | tm_tag_enum_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t | tm_tag_enumerator_t},
+	{_("Macros"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Methods"), TM_ICON_MEMBER, tm_tag_field_t},
 };
 
 static TMParserMapEntry map_GO[] = {
-	{'p', tm_tag_namespace_t},
-	{'f', tm_tag_function_t},
-	{'c', tm_tag_macro_t},
-	{'t', tm_tag_typedef_t},
-	{'v', tm_tag_variable_t},
-	{'s', tm_tag_struct_t},
-	{'i', tm_tag_interface_t},
-	{'m', tm_tag_member_t},
-	{'M', tm_tag_undef_t},
-	{'n', tm_tag_undef_t},
-	{'u', tm_tag_undef_t},
-	{'P', tm_tag_undef_t},
-	{'a', tm_tag_undef_t},
-	{'R', tm_tag_undef_t},
+	{'p', tm_tag_namespace_t},  // package
+	{'f', tm_tag_function_t},   // func
+	{'c', tm_tag_macro_t},      // const
+	{'t', tm_tag_typedef_t},    // type
+	{'v', tm_tag_variable_t},   // var
+	{'s', tm_tag_struct_t},     // struct
+	{'i', tm_tag_interface_t},  // interface
+	{'m', tm_tag_member_t},     // member
+	{'M', tm_tag_undef_t},      // anonMember
+	{'n', tm_tag_undef_t},      // methodSpec
+	{'u', tm_tag_undef_t},      // unknown
+	{'P', tm_tag_undef_t},      // packageName
+	{'a', tm_tag_undef_t},      // talias
+	{'R', tm_tag_undef_t},      // receiver
+};
+static TMParserMapGroup group_GO[] = {
+	{_("Package"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Interfaces"), TM_ICON_STRUCT, tm_tag_interface_t},
+	{_("Structs"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Types"), TM_ICON_STRUCT, tm_tag_typedef_t},
+	{_("Constants"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Members"), TM_ICON_MEMBER, tm_tag_member_t},
 };
 
 static TMParserMapEntry map_JSON[] = {
-	{'o', tm_tag_member_t},
-	{'a', tm_tag_member_t},
-	{'n', tm_tag_member_t},
-	{'s', tm_tag_member_t},
-	{'b', tm_tag_member_t},
-	{'z', tm_tag_member_t},
+	{'o', tm_tag_member_t},  // object
+	{'a', tm_tag_member_t},  // array
+	{'n', tm_tag_member_t},  // number
+	{'s', tm_tag_member_t},  // string
+	{'b', tm_tag_member_t},  // boolean
+	{'z', tm_tag_member_t},  // null
+};
+static TMParserMapGroup group_JSON[] = {
+	{_("Members"), TM_ICON_MEMBER, tm_tag_member_t},
 };
 
 /* Zephir, same as PHP */
 #define map_ZEPHIR map_PHP
+#define group_ZEPHIR group_PHP
 
-/* not in universal-ctags */
 static TMParserMapEntry map_POWERSHELL[] = {
-	{'f', tm_tag_function_t},
-	{'v', tm_tag_variable_t},
+	{'f', tm_tag_function_t},  // function
+	{'v', tm_tag_variable_t},  // variable
+};
+static TMParserMapGroup group_POWERSHELL[] = {
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
 };
 
 static TMParserMapEntry map_JULIA[] = {
-	{'c', tm_tag_variable_t},
-	{'f', tm_tag_function_t},
-	{'g', tm_tag_member_t},
-	{'m', tm_tag_macro_t},
-	{'n', tm_tag_namespace_t},
-	{'s', tm_tag_struct_t},
-	{'t', tm_tag_typedef_t},
+	{'c', tm_tag_variable_t},   // constant
+	{'f', tm_tag_function_t},   // function
+	{'g', tm_tag_member_t},     // field
+	{'m', tm_tag_macro_t},      // macro
+	{'n', tm_tag_namespace_t},  // module
+	{'s', tm_tag_struct_t},     // struct
+	{'t', tm_tag_typedef_t},    // type
     /* defined as externvar to get those excluded as forward type in symbols.c:goto_tag()
      * so we can jump to the real implementation (if known) instead of to the import statement */
-	{'x', tm_tag_externvar_t},
+	{'x', tm_tag_externvar_t},  // unknown
+};
+static TMParserMapGroup group_JULIA[] = {
+	{_("Constants"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Modules"), TM_ICON_NAMESPACE, tm_tag_namespace_t},
+	{_("Functions"), TM_ICON_METHOD, tm_tag_function_t},
+	{_("Fields"), TM_ICON_MEMBER, tm_tag_member_t},
+	{_("Macros"), TM_ICON_MACRO, tm_tag_macro_t},
+	{_("Structures"), TM_ICON_STRUCT, tm_tag_struct_t},
+	{_("Types"), TM_ICON_CLASS, tm_tag_typedef_t},
+	{_("Unknowns"), TM_ICON_OTHER, tm_tag_externvar_t},
 };
 
 static TMParserMapEntry map_CPREPROCESSOR[] = {
-	{'d', tm_tag_undef_t},
-	{'h', tm_tag_undef_t},
-	{'D', tm_tag_undef_t},
+	{'d', tm_tag_undef_t},  // macro
+	{'h', tm_tag_undef_t},  // header
+	{'D', tm_tag_undef_t},  // parameter
 };
+#define group_CPREPROCESSOR group_C
+
 static TMParserMapEntry map_GDSCRIPT[] = {
-	{'c', tm_tag_class_t},
-	{'m', tm_tag_method_t},
-	{'v', tm_tag_variable_t},
-	{'C', tm_tag_variable_t},
-	{'g', tm_tag_enum_t},
-	{'e', tm_tag_variable_t},
-	{'z', tm_tag_other_t},
-	{'l', tm_tag_other_t},
-	{'s', tm_tag_variable_t},
+	{'c', tm_tag_class_t},     // class
+	{'m', tm_tag_method_t},    // method
+	{'v', tm_tag_variable_t},  // variable
+	{'C', tm_tag_variable_t},  // const
+	{'g', tm_tag_enum_t},      // enum
+	{'e', tm_tag_variable_t},  // enumerator
+	{'z', tm_tag_other_t},     // parameter
+	{'l', tm_tag_other_t},     // local
+	{'s', tm_tag_variable_t},  // signal
+};
+static TMParserMapGroup group_GDSCRIPT[] = {
+	{_("Classes"), TM_ICON_CLASS, tm_tag_class_t},
+	{_("Methods"), TM_ICON_MACRO, tm_tag_method_t},
+	{_("Variables"), TM_ICON_VAR, tm_tag_variable_t},
+	{_("Enums"), TM_ICON_STRUCT, tm_tag_enum_t},
+	{_("Other"), TM_ICON_OTHER, tm_tag_other_t},
 };
 
 typedef struct
 {
     TMParserMapEntry *entries;
     guint size;
+    TMParserMapGroup *groups;
+    guint group_num;
 } TMParserMap;
 
-#define MAP_ENTRY(lang) [TM_PARSER_##lang] = {map_##lang, G_N_ELEMENTS(map_##lang)}
+#define MAP_ENTRY(lang) [TM_PARSER_##lang] = {map_##lang, G_N_ELEMENTS(map_##lang), group_##lang, G_N_ELEMENTS(group_##lang)}
 
 /* keep in sync with TM_PARSER_* definitions in the header */
 static TMParserMap parser_map[] = {
@@ -725,6 +1045,46 @@ gchar tm_parser_get_tag_kind(TMTagType type, TMParserType lang)
 }
 
 
+gint tm_parser_get_sidebar_group(TMParserType lang, TMTagType type)
+{
+	TMParserMap *map;
+	guint i;
+
+	if (lang >= TM_PARSER_COUNT)
+		return -1;
+
+	map = &parser_map[lang];
+	for (i = 0; i < map->group_num; i++)
+	{
+		if (map->groups[i].types & type)
+			return i;
+	}
+	return -1;
+}
+
+
+const gchar *tm_parser_get_sidebar_info(TMParserType lang, gint group, guint *icon)
+{
+	TMParserMap *map;
+	TMParserMapGroup *grp;
+
+	if (lang >= TM_PARSER_COUNT)
+		return NULL;
+
+	map = &parser_map[lang];
+	if (group >= (gint)map->group_num)
+		return NULL;
+
+	grp = &map->groups[group];
+	*icon = grp->icon;
+#ifdef GETTEXT_PACKAGE
+	return g_dgettext(GETTEXT_PACKAGE, grp->name);
+#else
+	return grp->name;
+#endif
+}
+
+
 static void add_subparser(TMParserType lang, TMParserType sublang, TMSubparserMapEntry *map, guint map_size)
 {
 	guint i;
@@ -796,6 +1156,8 @@ void tm_parser_verify_type_mappings(void)
 		const gchar *kinds = tm_ctags_get_lang_kinds(lang);
 		TMParserMap *map = &parser_map[lang];
 		gchar presence_map[256];
+		TMTagType lang_types = 0;
+		TMTagType group_types = 0;
 		guint i;
 
 		if (! map->entries || map->size < 1)
@@ -832,6 +1194,7 @@ void tm_parser_verify_type_mappings(void)
 					kinds[i], tm_ctags_get_lang_name(lang));
 
 			presence_map[(unsigned char) map->entries[i].kind]++;
+			lang_types |= map->entries[i].type;
 		}
 
 		for (i = 0; i < sizeof(presence_map); i++)
@@ -840,6 +1203,13 @@ void tm_parser_verify_type_mappings(void)
 				g_error("Duplicate tag type '%c' found for %s",
 					(gchar)i, tm_ctags_get_lang_name(lang));
 		}
+
+		for (i = 0; i < map->group_num; i++)
+			group_types |= map->groups[i].types;
+
+		if ((group_types & lang_types) != lang_types)
+			g_warning("Not all tag types mapped to symbol tree groups for %s",
+				tm_ctags_get_lang_name(lang));
 	}
 }
 


Modified: src/tagmanager/tm_parser.h
18 lines changed, 18 insertions(+), 0 deletions(-)
===================================================================
@@ -115,13 +115,31 @@ enum
 	TM_PARSER_COUNT
 };
 
+/* keep in sync with icon names in symbols.c */
+enum
+{
+	TM_ICON_CLASS,
+	TM_ICON_MACRO,
+	TM_ICON_MEMBER,
+	TM_ICON_METHOD,
+	TM_ICON_NAMESPACE,
+	TM_ICON_OTHER,
+	TM_ICON_STRUCT,
+	TM_ICON_VAR,
+	TM_ICON_NONE,
+	TM_N_ICONS = TM_ICON_NONE
+};
 
 void tm_parser_verify_type_mappings(void);
 
 TMTagType tm_parser_get_tag_type(gchar kind, TMParserType lang);
 
 gchar tm_parser_get_tag_kind(TMTagType type, TMParserType lang);
 
+gint tm_parser_get_sidebar_group(TMParserType lang, TMTagType type);
+
+const gchar *tm_parser_get_sidebar_info(TMParserType lang, gint group, guint *icon);
+
 TMTagType tm_parser_get_subparser_type(TMParserType lang, TMParserType sublang, TMTagType type);
 
 gint tm_parser_scope_autocomplete_suffix(TMParserType lang, const gchar *str);



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list