[geany/geany] 3f8733: Move symbol tree root mappings to tm_parser.c

Jiří Techet git-noreply at geany.org
Sun Apr 10 12:34:15 UTC 2022


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Sun, 10 Apr 2022 12:34:15 UTC
Commit:      3f8733f083e72be58e00ab2dde1e2584fe276cc5
             https://github.com/geany/geany/commit/3f8733f083e72be58e00ab2dde1e2584fe276cc5

Log Message:
-----------
Move symbol tree root mappings to tm_parser.c

There are several problems with the current mapping done in symbols.c:

1. All other language-specific mappings are done in tm_parser.c now
and this is the only thing that is done elsewhere. Having all the
mappings at one place makes things much clearer and makes tm_parser.c
the only place to play with when introducing new parser or when
updating a parser to a new upstream version.

2. The mapping is extremely confusing. First, there are several
hard-coded iterator names in TreeviewSymbols which don't cover all
tag types but which are just a subset of them. Then, there is
get_tag_type_iter() which is another mapping that groups certain
tag types to TreeViewSymbols members. So when looking at mappings
defined in add_top_level_items(), it isn't clear by just looking
at it how tag types of certain languages get mapped to their
roots without also having a look at get_tag_type_iter().

3. Since the groupings in get_tag_type_iter() are hard-coded,
some tag types have to be grouped together whether it makes sense
for the given language or not. For instance, for C we have
"Typedefs / Enums" grouped together because get_tag_type_iter()
returns the same root for tm_tag_typedef_t and tm_tag_enum_t
and even if we wanted to change this for C, we would affect
other languages too because this mapping is the same for all
languages.

4. Because of the hard-coded grouping of some tag types, we have to
make a decision whether we want something to show as we want in the
symbol tree or whether we map a ctags kind to tag type that is
semantically close to the construct in the given language. For
instance, we could separate "Typedefs / Enums" to separate roots
in the symbol tree by e.g. mapping typedefs to tm_tag_typedef_t
and enums to tm_tag_field_t which have separate roots but then
enum is represented by tm_tag_field_t which would confuse some
more advanced Geany features like scope completion.

5. In addition, the hard-coded grouping effectively reduces
the number of roots to 11 which may not be enough for some languages.

6. Tag icons for autocompletion popup are hard-coded in
get_tag_class() and may differ from the icons used by the symbol
tree. This isn't fixable easily with the current way of mapping.

This patch tries to solve these problems by moving root symbol
tree mappings to tm_parser.c (so all the mappings are at one
place) together with more flexible and easier to maintain
way of mapping definition.

For instance, consider kind mappings for the HAXE programming
language which until now looked this way.

static TMParserMapEntry map_HAXE[] = {
	{'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
};

In addition, after this patch, tm_parser.c contains also the
following mapping for the symbol tree roots:

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},
};

This declaration says that there are 5 roots with the given
names, icons attached to these roots, and, finally, the TM types
which will appear under these roots. Notice that there may be
multiple types under a single root which can be OR-ed using |
because TM types are bit fields. This definition gives us enough
flexibility to overcome the problems mentioned above and by having
everything at one place, we can manage TM languages much more
easily.

There isn't anything particularly interesting about the rest of
the patch - there are 2 auciliary functions in th_parser.c/h:

- tm_parser_get_sidebar_group(): returns index of a group for
  the provided language and TM tag type
- tm_parser_get_sidebar_info(): returns root name and icon
  for the provided language and group index

Inside symbols.c tv_iters was converted to an array of size
MAX_SYMBOL_TYPES of GtkTreeIter instead of the previous struct
of hard-coded roots and the rest of the code is updated to use
this array and the above 2 functions to get the mappings.


Modified Paths:
--------------
    src/symbols.c
    src/tagmanager/tm_parser.c
    src/tagmanager/tm_parser.h

Modified: src/symbols.c
628 lines changed, 45 insertions(+), 583 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
@@ -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_parser.c
1120 lines changed, 736 insertions(+), 384 deletions(-)
===================================================================
@@ -24,6 +24,8 @@
 #include <string.h>
 
 
+#define _(String) (String)
+
 typedef struct
 {
     const gchar kind;
@@ -41,111 +43,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 +208,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 +314,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 +444,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 +1041,42 @@ 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;
+	return grp->name;
+}
+
+
 static void add_subparser(TMParserType lang, TMParserType sublang, TMSubparserMapEntry *map, guint map_size)
 {
 	guint i;


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