ctags regex for multiple declarations in one line
-
10-06-2021 - |
質問
I'm writing a .ctags file for a custom language... Like most languages, it allows for multiple variable declarations in one line.. i.e.:
int a, b, c;
I have a basic regex which recognizes 'a':
--regex-mylang=/^[ \t]*int[ \t]*([a-zA-Z_0-9]+)/\1/v,variable/
How do I modify this to have it match 'b' and 'c', as well? I can't find anything in ctags documentation that deals with multiple matches in a single line.
解決
After going through this for a few hours, I'm convinced it can't be done. No matter what, the regular expression will only expand to one tag per line. Even if you put \1 \2 \3 ... as the expansion, that would just cause a tag consisting of multiple matches, instead of one tag per match.
It parses the C example correctly because inside the ctags source code it uses an actual code parser, not a regexp.
他のヒント
The latest Universal-ctags can capture them.
[jet@localhost]/tmp% cat input.x
int a, b, c;
[jet@localhost]/tmp% cat x.ctags
--langdef=X
--map-X=.x
--kinddef-X=v,var,variables
--_tabledef-X=main
--_tabledef-X=vardef
--_mtable-regex-X=main/int[ \t]+//{tenter=vardef}
--_mtable-regex-X=main/.//
--_mtable-regex-X=vardef/([a-zA-Z0-9]+)/\1/v/
--_mtable-regex-X=vardef/;//{tleave}
--_mtable-regex-X=vardef/.//
[jet@localhost]/tmp% u-ctags --options=x.ctags -o - ./input.x
a ./input.x /^int a, b, c;$/;" v
b ./input.x /^int a, b, c;$/;" v
c ./input.x /^int a, b, c;$/;" v
See http://docs.ctags.io/en/latest/optlib.html#byte-oriented-pattern-matching-with-multiple-regex-tables for more details.
You're trying to do parsing with a regex, which is not generally possible. Parsing requires the equivalent of storing information on a stack, but a regular expression can embody only a finite number of different states.
it can be partialy done with the Universal Ctags and with the help of {_multiline=N}
and {scope}
flag. The N
is group number which position is saved in generated tags
file.
For more information look here: docs/optlib.rst
Configuration: mylang.ctags
--langmap=mylang:.txt
--regex-mylang=/^[[:blank:]]*(int)[[:blank:]]/\1/{placeholder}{scope=set}{_multiline=1}
--regex-mylang=/(;)/\1/{placeholder}{scope=clear}
--regex-mylang=/[[:blank:]]*([[:alnum:]]+)[[:blank:]]*,?/\1/v,variable/{_multiline=1}{scope=ref}
Test file: test.txt
void main() {
int a, b, c, d;
}
Generate tags with: ctags --options=mylang.ctags test.txt
Generated tags
file:
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
!_TAG_PROGRAM_VERSION 0.0.0 /cb4476eb/
a test.txt /^ int a, b, c, d;$/;" v
b test.txt /^ int a, b, c, d;$/;" v
c test.txt /^ int a, b, c, d;$/;" v
d test.txt /^ int a, b, c, d;$/;" v
int test.txt /^ int a, b, c, d;$/;" v
main test.txt /^void main() {$/;" v
void test.txt /^void main() {$/;" v
--regex-perl=/^\s*?use\s+(\w+[\w\:]*?\w*?)/\1/u,use,uses/
--regex-perl=/^\s*?require\s+(\w+[\w\:]*?\w*?)/\1/r,require,requires/
--regex-perl=/^\s*?has\s+['"]?(\w+)['"]?/\1/a,attribute,attributes/
--regex-perl=/^\s*?\*(\w+)\s*?=/\1/a,aliase,aliases/
--regex-perl=/->helper\(\s?['"]?(\w+)['"]?/\1/h,helper,helpers/
--regex-perl=/^\s*?our\s*?[\$@%](\w+)/\1/o,our,ours/
--regex-perl=/^=head1\s+(.+)/\1/p,pod,Plain Old Documentation/
--regex-perl=/^=head2\s+(.+)/-- \1/p,pod,Plain Old Documentation/
--regex-perl=/^=head[3-5]\s+(.+)/---- \1/p,pod,Plain Old Documentation/