TL;DR "support" because this is not about supporting the fancy new stuff, but just not breaking on a universal-ctags generated tag file. I'd just like to tell mg enough of the file format to ignore the extensions over plain tag files.
The diff is mostly from troglobit' mg: https://github.com/troglobit/mg/commit/64cd07ecf5c521d50966eca8ba04026e7c9f3be8 The documentation about the universal-ctags extension over tags files is documented in utags(5) after you install the universal-ctags package. Tags file entries follows this scheme: {tagname}<tab>{tagfile}<tab>{tagaddress} where tagaddress is an ex command (could be anything, I haven't checked how vi(1) actually implements it, but mg assumes it's a search and just does that. Works most of the times). To store extra metadata about the tag itself, the address is put a comment in the tagaddress. For example, here's how the main() entry would look like. Not the type information after ;" % uctags *.c % g ^main tags tags:526: main main.c /^main(int argc, char **argv)$/;" f typeref:typename:int Similarly, universal-ctags introduced support for some meta-tag using some dummy entries under the !_TAG_ "namespace" (e.g. !_TAG_FILE_FORMAT, !_TAG_FILE_SORTED, ...) So, the idea is to just ignore tags starting with !_TAG_ and ignore comments. As simple as that :-) Index: tags.c =================================================================== RCS file: /home/cvs/src/usr.bin/mg/tags.c,v retrieving revision 1.27 diff -u -p -r1.27 tags.c --- tags.c 29 Mar 2023 19:09:04 -0000 1.27 +++ tags.c 27 Sep 2023 16:21:42 -0000 @@ -281,6 +281,10 @@ loadtags(const char *fn) } while ((l = fparseln(fd, NULL, NULL, "\\\\\0", FPARSELN_UNESCCONT | FPARSELN_UNESCREST)) != NULL) { + if (!strncmp(l, "!_TAG_", 6)) { + free(l); + continue; + } if (addctag(l) == FALSE) { fclose(fd); return (FALSE); @@ -340,7 +344,7 @@ int addctag(char *s) { struct ctag *t = NULL; - char *l; + char *l, *c; if ((t = malloc(sizeof(struct ctag))) == NULL) { dobeep(); @@ -357,6 +361,15 @@ addctag(char *s) *l++ = '\0'; if (*l == '\0') goto cleanup; + + /* + * Newer universal ctags format abuse vi comments in the + * pattern to store extra metadata. Since we don't support it + * remove it so the pattern is not mangled. + */ + if ((c = strstr(l, ";\"")) != NULL) + *c = '\0'; + t->pat = strip(l, strlen(l)); if (RB_INSERT(tagtree, &tags, t) != NULL) { free(t);