CTAGS-INCOMPATIBILITIES(7)

πŸ“¦ version 6.0.0, in opensuse-leap 16.0

πŸ’… CTAGS-INCOMPATIBILITIES πŸ’…

okay bestie, so this is a page straight outta the Universal Ctags manual β€” it's called ctags-incompatibilities, and it's basically the ✨receipts✨ of every big glow-up change Universal Ctags made after it forked from Exuberant Ctags. fr fr, read this before you go blaming ctags for "breaking" something. πŸ’–


✨ SYNOPSIS ✨

ctags [options] [file(s)]
etags [options] [file(s)]

like, that's the shape of the command line, bestie. don't overthink it. 🫢


🌸 DESCRIPTION 🌸

This page spills all the major incompatible changes that got introduced into Universal Ctags, which was forked from Exuberant Ctags. no cap, some stuff just works different now. πŸ’€

πŸŽ€ Option files loading at starting up time (preload files)

Universal Ctags does not load ~/.ctags when it starts up. nope, not anymore. The file paths for preload files are changed, so if you were relying on the old location… vibe check failed, sorry. πŸ‘‘ See the FILES section of ctags(1) for the deets.

πŸŽ€ Environment variables for arranging command lines

Universal Ctags does not read the CTAGS and/or ETAGS environment variables. literally just doesn't look at them. πŸ™ˆ

πŸŽ€ Behavior when --excmd=mixed is given

Exuberant Ctags uses line numbers as addresses for C preprocessor macro definition tags. Universal Ctags uses patterns for those tags instead. different energy, same goal. ✨


πŸ”₯ Incompatibilities in command line interface πŸ”₯

πŸŽ€ Ordering in a command line

The command line format of Universal Ctags is ctags [options] [source_file(s)], following the standard POSIX convention. slay, we love a standard. πŸ’…

Exuberant Ctags accepts an option following a source file, like this:

$ ctags -o - foo.c --list-kinds=Sh
f  functions

Universal Ctags side-eyes that and warns, then ignores the option --list-kinds=Sh, like so:

$ ctags -o - foo.c --list-kinds=Sh
ctags: Warning: cannot open input file "--list-kinds=Sh" : No such file or directory
a       foo.c   /^void a () {}$/;"      f       typeref:typename:void
b       foo.c   /^void b () {}$/;"      f       typeref:typename:void

see that warning? that's it telling you it thinks --list-kinds=Sh is a file. rude? maybe. correct per POSIX? yes bestie. 😭

πŸŽ€ The order of application of patterns and extensions in --langmap

When it applies mappings for a name of a given source file, Exuberant Ctags tests file name patterns AFTER file extensions (this is called e-map-order). Universal Ctags does it differently β€” it tests file name patterns BEFORE file extensions (u-map-order). iconic behavior change, ngl.

This incompatible change was introduced to deal with this exact situation:

  • build.xml as a source file,
  • The Ant parser declares it handles a file name pattern build.xml, and
  • The XML parser declares it handles a file extension .xml.

so like… which parser should be used for parsing build.xml?? πŸ€” The assumption of Universal Ctags is that the user may want to use the Ant parser β€” the file name pattern it declares is more specific than the file extension the XML parser declares. but e-map-order chooses the XML parser. which, honestly, is giving "technically correct but emotionally wrong." πŸ’€

So Universal Ctags uses the u-map-order even though it introduces an incompatibility. periodt.

The --list-map-extensions=<language> and --list-map-patterns=<language> options are super helpful for verifying the file extensions and the file name patterns of a given <language>. go check 'em, they're your besties for this. πŸ¦‹

πŸŽ€ Remove --file-tags and --file-scope options

Even back in Exuberant Ctags, --file-tags was not documented in its man page. so, like, it was always a little mysterious. πŸ•΅οΈβ€β™€οΈ

  • Instead of specifying --file-tags or --file-tags=yes, use --extras=+f or --extras=+{inputFile}.
  • Instead of specifying --file-tags=no, use --extras=-f or --extras=-{inputFile}.

Universal Ctags also introduces the F/fileScope extra as the replacement for the --file-scope option.

  • Instead of specifying --file-tags or --file-tags=yes, use --extras=+F or --extras=+{fileScope}.
  • Instead of specifying --file-tags=no, use --extras=-F or --extras=-{fileScope}.

(and yes, that's exactly what the page says β€” copy it character for character, don't come for me πŸ™)


🌈 Incompatibilities in language and kind definitions 🌈

πŸŽ€ Language name defined with --langdef=name option

The characters you can use are more restricted than in Exuberant Ctags. For more details, see the description of --langdef=name in ctags-optlib(7). πŸ’œ

πŸŽ€ Obsoleting --<LANG>-kinds option

Some options have <LANG> as parameterized parts in their name, like --foo-<LANG>=... or --<LANG>-foo=.... The most of all such options in Exuberant Ctags have the former form, --foo-<LANG>=.... The exception is --<LANG>-kinds. guess who's the odd one out 🫠

Universal Ctags uses the former form for all <LANG> parameterized options. So use --kinds-<LANG> instead of --<LANG>-kinds in Universal Ctags. --<LANG>-kinds still works but it will be removed in the future β€” so like, don't get attached. 😭

The former form may be friendly to shell completion engines. and we love a convenient queen. πŸ‘‘

πŸŽ€ Disallowing to define a kind with file as name

The kind name file is reserved. Using it as part of a kind spec in the --regex-<LANG> option is now disallowed. 🚫

πŸŽ€ Disallowing to define a kind with 'F' as letter

The kind letter 'F' is reserved. Using it as part of a kind spec in the --regex-<LANG> option is now disallowed. same energy, different reserved thing. πŸ’€

πŸŽ€ Disallowing to use other than alphabetical character as kind letter

Exuberant Ctags accepts a character other than an alphabetical character as a kind letter in the --regex-<LANG>=... option. Universal Ctags accepts only an alphabetical character. alphabet girlies only πŸ’…

πŸŽ€ Acceptable characters as parts of a kind name

Exuberant Ctags accepts any character as a part of a kind name defined with --regex-<LANG>=/regex/replacement/kind-spec/.

Universal Ctags accepts only an alphabetical character as the initial letter of a kind name. And it accepts only an alphabetical character or numerical character as the rest of the letters. ngl, it's stricter than your group chat's rules. πŸ“

An example:

--regex-Foo=/abstract +class +([a-z]+)/\1/a,abstract class/i

Universal Ctags rejects this because the kind name, abstract class, includes a whitespace character. no spaces allowed, bestie. 🚫

This requirement exists so the output of Universal Ctags follows the tags file format. it's giving "rules exist for a reason" ✨

πŸŽ€ A combination of a kind letter and a kind name

In Universal Ctags, the combination of a kind letter and a kind name must be unique in a language. πŸ”‘

You cannot define more than one kind reusing a kind letter with different kind names. You cannot define more than one kind reusing a kind name with different kind letters. one-to-one or nothing, fr fr.

An example:

--regex-Foo=/abstract +class +([a-z]+)/\1/a,abstractClass/i
--regex-Foo=/attribute +([a-z]+)/\1/a,attribute/i

Universal Ctags rejects this because the kind letter 'a' is used twice β€” once for defining the kind abstractClass and once for attribute. duplication is not the vibe. πŸ’€


πŸ¦‹ Incompatibilities in tags file format πŸ¦‹

πŸŽ€ Using numerical character in the name part of tag tagfield

The version 2 tags file format β€” the default output format of Exuberant Ctags β€” accepts only alphabetical characters in the name part of the tag tagfield.

Universal Ctags introduces an exception to this specification: it may use numerical characters in addition to alphabetical characters as the letters other than the initial letter of the name part. little loophole, big slay. πŸ”₯

The kinds heading1, heading2, and heading3 in the HTML parser are the examples. πŸŽ€

πŸŽ€ Truncating the pattern for long input lines

To prevent generating overly large tags files, a pattern field is truncated, by default, when its size exceeds 96 bytes. 😱 A different limit can be specified with --pattern-length-limit=N. Specifying 0 as N results in no truncation β€” because Exuberant Ctags does not truncate. so if you want the old behavior, you know what to do. πŸ‘‘

πŸŽ€ Kind letters and names

A kind letter 'F' and a kind name file are reserved in the main part. A parser cannot have a kind conflicting with these reserved ones. Some incompatible changes were introduced to follow the above rule:

  • Cobol's file kind is renamed to fileDesc because the kind name file is reserved.
  • Ruby's 'F' (singletonMethod) is changed to 'S'.
  • SQL's 'F' (field) is changed to 'E'.

renames happen, we move on, we stay iconic. πŸ’…βœ¨


πŸ’– SEE ALSO πŸ’–

ctags(1), ctags-optlib(7), and tags(5). go read those too, they're the rest of the lore. πŸ“š


lowkey that's the whole page bestie β€” every flag, every rename, every reserved letter, all of it. don't shoot the messenger, shoot the fork 😌

okay that's a wrap! this iconic little document is from Universal Ctags version 6.0.0 β€” mwah, bye! πŸ’‹πŸŒΈπŸŽ€

πŸ“¦ where this page comes from