# # cmake.ctags --- multitable regex parser for CMake's files # # Copyright (c) 2018, 128 Technology, Inc. # # Author: Hadriel Kaplan (hadrielk@yahoo.com) # # This source code is released for free distribution under the terms of the # GNU General Public License version 2 or (at your option) any later version. # # # Overview: # # This universal-ctags optlib option file defines the parser for tagging # CMake files. It supports tagging the following: # # - cmake function and macro names # - build target, executable, and library target names # - cmake variables and options # - cmake project names # # Caveats: # # Names that are ${} references to variables are not tagged. # # For example, given the following: # # set(PROJECT_NAME_STR ${PROJECT_NAME}) # add_executable( ${PROJECT_NAME_STR} ... ) # add_custom_target( ${PROJECT_NAME_STR}_tests ... ) # add_library( sharedlib ... ) # # the variable 'PROJECT_NAME_STR' and target 'sharedlib' will both be tagged, # but the other targets will not be. # # # References: # # - https://cmake.org/cmake/help/latest/manual/cmake-language.7.html # --langdef=CMake --map-CMake=+.cmake --map-CMake=+(CMakeLists.txt) # # Kinds # --kinddef-CMake=f,function,functions --kinddef-CMake=m,macro,macros --kinddef-CMake=t,target,targets --kinddef-CMake=v,variable,variable definitions --kinddef-CMake=D,option,options specified with -D --kinddef-CMake=p,project,projects # # Tables # --_tabledef-CMake=main --_tabledef-CMake=variable --_tabledef-CMake=variableScoped --_tabledef-CMake=function --_tabledef-CMake=macro --_tabledef-CMake=target --_tabledef-CMake=option --_tabledef-CMake=project # # comment # --_tabledef-CMake=commentBegin --_tabledef-CMake=commentMultiline --_mtable-regex-CMake=commentBegin/\[\[//{tjump=commentMultiline} --_mtable-regex-CMake=commentBegin/[^\n]*[ \t\n]*//{tleave} --_mtable-regex-CMake=commentMultiline/\]\][ \t\n]*//{tleave} --_mtable-regex-CMake=commentMultiline/.[^]]*// --_tabledef-CMake=skipComment --_mtable-regex-CMake=skipComment/#//{tenter=commentBegin} # # Utilities # --_tabledef-CMake=skipWhiteSpace --_tabledef-CMake=skipToName --_tabledef-CMake=nextToken --_mtable-regex-CMake=skipWhiteSpace/[ \t\n]+// --_mtable-extend-CMake=skipToName+skipWhiteSpace --_mtable-extend-CMake=skipToName+skipComment --_mtable-regex-CMake=nextToken/[^ \t\n]+[ \t\n]*// # # main # # This first regex entry may seem odd - it's purely for improving performance, by # matching tokens with leading characters that could not possibly match a later regex, # and just skipping the whole token (and trailing whitespace). This one regex line # improved performance by an order of magnitude. --_mtable-regex-CMake=main/[^sSfFmMaAoOpP# \t\n][^ #\t\n]*[ \t\n]+// --_mtable-extend-CMake=main+skipComment --_mtable-regex-CMake=main/set[ \t]*\(//{icase}{tenter=variable} --_mtable-regex-CMake=main/function[ \t]*\(//{icase}{tenter=function} --_mtable-regex-CMake=main/macro[ \t]*\(//{icase}{tenter=macro} --_mtable-regex-CMake=main/add_(custom_target|executable|library)[ \t]*\(//{icase}{tenter=target} --_mtable-regex-CMake=main/option[ \t]*\(//{icase}{tenter=option} --_mtable-regex-CMake=main/project[ \t]*\(//{icase}{tenter=project} --_mtable-extend-CMake=main+nextToken --_mtable-extend-CMake=main+skipWhiteSpace # # For performance reasons, this is a separate table from 'main', mostly to avoid # matching tokens starting with 'e' in the main table - such tokens are very # common in CMake, due to 'endif()' and such # --_tabledef-CMake=inFunction --_mtable-regex-CMake=inFunction/([^eEsSfFmMaAoO# \t\n]|[eE][^nN]|[eE][nN][^dD]|[eE][nN][dD][^fF#])[^ #\t\n]*[ \t\n]+// --_mtable-extend-CMake=inFunction+skipComment --_mtable-regex-CMake=inFunction/set[ \t]*\(//{icase}{tenter=variableScoped} --_mtable-regex-CMake=inFunction/function[ \t]*\(//{icase}{tenter=function} --_mtable-regex-CMake=inFunction/macro[ \t]*\(//{icase}{tenter=macro} --_mtable-regex-CMake=inFunction/endfunction[ \t]*\([^)]*\)//{icase}{tleave}{scope=pop} --_mtable-regex-CMake=inFunction/add_(custom_target|executable|library)[ \t]*\(//{icase}{tenter=target} --_mtable-regex-CMake=inFunction/option[ \t]*\(//{icase}{tenter=option} --_mtable-extend-CMake=inFunction+nextToken --_mtable-extend-CMake=inFunction+skipWhiteSpace # # Each of the following basically work the same way, and only differ in the # exact pattern allowed to be their name, and the Kind they add. Note that they # capture a required trailing '[ \t\n\)]' or '#', to verify the full name token # matched the name's pattern, but then we advanceTo=2start for the next round, # so that we don't go past a potential '#' comment token but instead match it # again in the main table as a comment. The odds of a comment '#' immediately # following the name is very low, so we split it into its own check and do it # last in each table - this improves real-world performance ~10%, because in # the common case we can capture the whitespace at the same time as the name, # and not have to skip it again in the 'main' table. # # # variable # --_mtable-regex-CMake=variable/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/v/{tleave} --_mtable-extend-CMake=variable+skipToName --_mtable-regex-CMake=variable/([A-Za-z0-9_.-]+)(#)/\1/v/{tleave}{_advanceTo=2start} # when a variable is defined inside a function, we reference its scope unless it # has a PARENT_SCOPE argument; unfortunately the regex for this can backtrack a # lot and the current ctags regex engine doesn't do lazy or atomic/possessive # captures to avoid it, but in practice this should be ok --_tabledef-CMake=inVariable --_mtable-regex-CMake=inVariable/[^")]+(("(\\"|[^"])*")([^")]+("(\\"|[^"])*"))*)[ \t\n]PARENT_SCOPE[# \t\n)]//{tjump=variable}{_advanceTo=0start} --_mtable-regex-CMake=inVariable/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/v/{tleave}{scope=ref} --_mtable-regex-CMake=inVariable/([A-Za-z0-9_.-]+)(#)/\1/v/{tleave}{scope=ref}{_advanceTo=2start} --_mtable-regex-CMake=variableScoped/[A-Za-z0-9_.-]+[# \t\n\)]//{tjump=inVariable}{_advanceTo=0start} --_mtable-extend-CMake=variableScoped+skipToName # # function # --_mtable-regex-CMake=function/([A-Za-z_][A-Za-z0-9_]*)([# \t\n\)])/\1/f/{_advanceTo=2start}{tjump=inFunction}{scope=push} --_mtable-extend-CMake=function+skipToName # # macro: unlike functions, technically macros don't create scopes for any # variables set in them - the scope is whatever it is when the macro is invoked. # So we're not going to push a scope nor go into the 'inFunction' table. # --_mtable-regex-CMake=macro/([A-Za-z_][A-Za-z0-9_]*)[ \t\n\)]+/\1/m/{tleave} --_mtable-extend-CMake=macro+skipToName --_mtable-regex-CMake=macro/([A-Za-z_][A-Za-z0-9_]*)(#)/\1/m/{tleave}{_advanceTo=2start} # # target # --_mtable-regex-CMake=target/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/t/{tleave} --_mtable-extend-CMake=target+skipToName --_mtable-regex-CMake=target/([A-Za-z0-9_.-]+)(#)/\1/t/{tleave}{_advanceTo=2start} # # option # --_mtable-regex-CMake=option/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/D/{tleave} --_mtable-extend-CMake=option+skipToName --_mtable-regex-CMake=option/([A-Za-z0-9_.-]+)(#)/\1/D/{tleave}{_advanceTo=2start} # # project # --_mtable-regex-CMake=project/([A-Za-z0-9_.-]+)([# \t\n\)])/\1/p/{tleave}{_advanceTo=2start} --_mtable-extend-CMake=project+skipToName