[Question] Defining new regex-based tags with scope defined by built-in `ctags` kinds
Actually, to add scope to regex-based tags, it is needed to do something as follows:
--regex-LANG=/(top)/\1/t,top/{scope=set}
--regex-LANG=/(sub)/\1/s,sub/{scope=ref}
so that scope field will be added to all found sub tags (top tags will be considered as their parent scope).
Question is, what if for LANG a built-in tag kind for top is already defined? How could I use the already available kind instead of redefining it via regex + {scope=set}?
For example, I would like to define some tags for the case XXX statement inside of C functions. Each case tag should belong to the function, used as scope kind. But I have not idea on how to define the scope, without having to re-define the function kind.
There is no way to look up scopes recorded by a built-in code from a regex code NOW.
As usual, I have an idea of integrating the two worlds: {scope=intervalTree}.
$ cat /tmp/input.c
int f(void)
{
return 0;
}
$ ./ctags --fields=+'{line}{end}' -o - /tmp/input.c
f /tmp/input.c /^int f(void)$/;" f line:1 typeref:typename:int end:4
In some languages, ctags has the ability to record "line:" and "end:". ctags has a red-black tree (rbtree) implementation derived from Linux. The interval tree (https://en.wikipedia.org/wiki/Interval_tree) can be implemented based on the rbtree. (https://www.youtube.com/watch?v=LRLHBxMFpHM).
We can put all tags extracted by built-in code into the interval tree. The interval tree can answer a question like "the narrowest tag includes line N".
We can use https://github.com/markfasheh/interval-tree/tree/master.
The initial implementation of the flag {scope=interval} works.
$ cat -n case.c
1 int
2 main(void)
3 {
4 switch (x) {
5 case A:
6 break;
7 case B:
8 break;
9 }
10 return 0;
11 }
12
13 int
14 foo(void)
15 {
16
17 /* NO switch/case here */
18
19 }
20
21 int
22 bar(void)
23 {
24 switch (x) {
25 case C:
26 break;
27 case D:
28 break;
29 }
30 return 0;
31 }
$ cat case.ctags
--kinddef-C=L,caseLabel,case labels
--_tabledef-C=init
--_mtable-regex-C=init/case +([a-zA-Z0-9]+)[^\n]*/\1/L/{scope=interval}
--_mtable-regex-C=init/.//
$ ./ctags --quiet --options=NONE --sort=no --options=case.ctags -o - ./case.c
main ./case.c /^main(void)$/;" f typeref:typename:int
foo ./case.c /^foo(void)$/;" f typeref:typename:int
bar ./case.c /^bar(void)$/;" f typeref:typename:int
A ./case.c /^ case A:$/;" T function:main
B ./case.c /^ case B:$/;" T function:main
C ./case.c /^ case C:$/;" T function:bar
D ./case.c /^ case D:$/;" T function:bar
The scopes for case labels are extracted well.
Superb. Adding scope information for a custom regex-based tag, referencing the tag kinds already internally parsed by ctags, would be a great addition in my opinion.
Has this feature already been added in the latest ctags binary, or there is a way to try it?
Superb. Adding scope information for a custom regex-based tag, referencing the tag kinds already internally parsed by ctags, would be a great addition in my opinion.
Yes. This is a great addition. I myself need this feature.
Has this feature already been added in the latest ctags binary, or there is a way to try it?
See #3678. You must specify {scope=_intervaltab} and {postrun}. The flags work with only C/C++/CUDA parsers.
I will NOT merge the branch in soon.
I must reconsider the consistency between {scope=_intervaltab} and the other {scope=...} flags. I have to update ctags-optlib(7) man page. When updating the man page, I may need your help.