forked from ma6174/vim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tagsrch.cnx
executable file
·718 lines (565 loc) · 33 KB
/
tagsrch.cnx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
*tagsrch.txt* For Vim version 7.3. 最近更新: 2009年4月
VIM 参考手册 by Bram Moolenaar
译者: Willis
http://vimcdoc.sf.net
标签和特殊搜索 *tags-and-searches*
用户手册 |29.1| 有这部分内容的介绍。
1. 跳转到标签 |tag-commands|
2. 标签栈 |tag-stack|
3. 标签匹配表 |tag-matchlist|
4. 标签细节 |tag-details|
5. 标签文件格式 |tags-file-format|
6. 头文件搜索 |include-search|
==============================================================================
1. 跳转到标签 *tag-commands*
*tag* *tags*
标签是出现在 "tags" 文件的一个标识符。它是一种能够跳转的标记。例如,在 C 程序
里,每个函数名都可以是一个标签。在使用标签文件之前,"tags" 文件由 ctags 这样的
程序生成。
使用 ":tag" 命令移动光标到标签上。使用 CTRL-] 命令,光标所在的关键字就可用作标
签。如果光标不在关键字上,则使用最右侧的一个关键字。
":tag" 命令对 C 程序十分有效。如果你看到一个函数的调用而想知道该函数的作用,把
光标移动到函数名上,并按 CTRL-]。它会把你带到该函数的定义上。简单的,按 CTRL-T
就可以回去。同时,也请阅读下面关于标签栈的描述。
*:ta* *:tag* *E426* *E429*
:[count]ta[g][!] {ident}
根据 tags 文件的信息,跳转到 {ident} 的定义上。
把 {ident} 放在堆栈上。[!] 见 |tag-!|。
{ident} 可以是个正规表达式。见 |tag-regexp|。
如果有 {ident} 的多个匹配,则跳转到它们中的第 [count]
个。如果 [count] 被省略,则跳转到第一个。要跳转到其它
匹配的标签,参见 |tag-matchlist|。
g<LeftMouse> *g<LeftMouse>*
<C-LeftMouse> *<C-LeftMouse>* *CTRL-]*
CTRL-] 跳转到光标所在的关键字的定义。和 ":tag {ident}" 相同,
只不过 {ident} 是光标之下或者之后的关键字。
如果有 {ident} 的多个匹配,则跳转到它们中的第 [count]
个。如果没有 [count],跳转到第一个。 要跳转到其它匹配
的标签,参见 |tag-matchlist|。
{Vi: 光标之后的标识符}
*v_CTRL-]*
{Visual}CTRL-] 和 ":tag {ident}" 相同,其中 {ident} 是高亮的文本。
{Vi 无此功能}
*telnet-CTRL-]*
CTRL-] 是缺省的 telnet 转义键。在你按 CTRL-] 进行标签跳转的时候,你会得到
telnet 的提示符。许多版本的 telnet 允许你改变或者屏蔽缺省的转义键。见 telnet
的手册页。你可以用 'telnet -E {Hostname}' 来屏蔽转义键,或者用 'telnet -e
{EscapeCharacter} {Hostname}' 来指定别的转义键。如果可能,用 "ssh" 来代替
"telnet" 也可解决这个问题。
*tag-priority*
如果有标签的多个匹配,使用以下的优先级:
1. "FSC" 当前文件的完整的匹配静态标签。
2. "F C" 当前文件的完整匹配全局标签。
3. "F " 其他文件的完整匹配全局标签。
4. "FS " 其他文件的完整匹配静态标签。
5. " SC" 当前文件的忽略大小写的匹配静态标签。
6. " C" 当前文件的忽略大小写匹配全局标签。
7. " " 其他文件的忽略大小写匹配全局标签。
8. " S " 其他文件的忽略大小写匹配静态标签。
注意 当前文件改变时,优先顺序多数情况下不会改变,以免使 ":tnext" 的使用引起混
淆。在使用 ":tag {ident}" 时,优先顺序才会改变。
如果 'ignorecase' 选项关闭,":tag" 命令不会查找忽略大小写的匹配。不过即使如
此,模式 (以 "/" 开始) 的匹配和 ":tselect" 还会查找这些匹配。注意 使用忽略大小
写查找就无法应用 tags 文件的二分法查找,从而减慢了查找速度。这可以用大小写合并
排序的标签文件来解决。具体解释见 'tagbsearch' 选项。
==============================================================================
2. 标签栈 *tag-stack* *tagstack* *E425*
标签栈记住你跳转过的标签,还有从哪里跳转到这些标签。只有在设置 'tagstack' 选项
的时候,标签才被压到堆栈里。
g<RightMouse> *g<RightMouse>*
<C-RightMouse> *<C-RightMouse>* *CTRL-T*
CTRL-T 跳到标签栈上第 [count] 个较早的项目 (缺省为 1)。
{Vi 无此功能}
*:po* *:pop* *E555* *E556*
:[count]po[p][!] 跳到标签栈上第 [count] 个较早的项目 (缺省为 1)。
[!] 见 |tag-!|。{Vi 无此功能}
:[count]ta[g][!] 跳到标签栈上第 [count] 个较新的项目 (缺省为 1)。
[!] 见 |tag-!|。{Vi 无此功能}
*:tags*
:tags 显示标签栈的内容。激活的项目以 '>' 标明。{Vi 无此功能}
":tags" 的输出结果类似于:
# TO tag FROM line in file/line
1 1 main 1 harddisk2:text/vim/test
> 2 2 FuncA 58 i = FuncA(10);
3 1 FuncC 357 harddisk2:text/vim/src/amiga.c
该列表显示你跳转到的标签和跳转前光标的位置。较早的项目在顶部,较新的在底部。
'>' 指向活动的项目。这是下一个 ":tag" 命令将使用的标签。CTRL-T 和 ":pop" 使用
活动项目之上的那项的位置。
"TO" 之下的那列显示匹配表的当前匹配的数目。注意 这不会因为使用 ":pop" 或者
":tag" 而改变。
记住文件名和行号可以使你回到 tag 命令之前的位置。即使你删除或者插入行,行号也
会保持正确,除非你用别的程序 (比如,另外一个 Vim 的实例) 做这些事。
对于当前文件,"file/line" 列显示该位置的文本。缩进被删除,长行也被截短,以便能
放进窗口里显示。
有若干命令可以让你跳到之前用过的标签。一些例子包括:
":pop" 或 CTRL-T 到上一个标签之前的位置
{count}CTRL-T 到第 {count} 个较早的标签之前的位置
":tag" 到更新的标签
":0tag" 到前一个使用过的标签
最明显的应用就是浏览程序的调用图。考虑下面的调用图:
main ---> FuncA ---> FuncC
---> FuncB
(解释: main 调用 FuncA 和 FuncB; FuncA 调用 FuncC)。
从 main 到 FuncA,你可以在调用 FuncA 的行上用 CTRL-]。然后再用 CTRL-] 跳到
FuncC。如果你现在想跳回到 main,你只需要按 CTRL-T 两次。然后你可以用 CTRL-] 到
FuncB。
如果你使用 ":ta {ident}" 或者 CTRL-] 命令,该标签被加在栈的当前位置。如果栈已
满 (最多可以容纳 20 项),最早的项目被删除,较早的项目则依次前移 (索引号分别减
1)。如果最近使用的项目不在底部,它其后的项目都被删除。这意味着调用图上的旧的分
支丢失了。在上面解释的命令执行以后,标签栈看起来像这样:
# TO tag FROM line in file
1 main 1 harddisk2:text/vim/test
2 FuncB 59 harddisk2:text/vim/src/main.c
*E73*
如果你试图使用标签栈,而其中没有任何内容,你会得到一个错误信息。
==============================================================================
3. 标签匹配表 *tag-matchlist* *E427* *E428*
如果有多个匹配的标签,这些命令可以用来在它们之间跳转。注意 这些命令不影响标签
栈,它保留原来的项目。
*:ts* *:tselect*
:ts[elect][!] [ident] 根据 tags 文件的信息,列出匹配 [ident] 的标签。
如果 [ident] 没有给出,使用标签栈上最后的标签名。
第一列的 '>' 指示列表的当前位置 (如果有的话)。
[ident] 可以是正规表达式模式,见 |tag-regexp|。
列表使用的优先级顺序见 |tag-priority|。
{Vi 无此功能}
示例输出:
>
nr pri kind tag file
1 F f mch_delay os_amiga.c
mch_delay(msec, ignoreinput)
> 2 F f mch_delay os_msdos.c
mch_delay(msec, ignoreinput)
3 F f mch_delay os_unix.c
mch_delay(msec, ignoreinput)
Enter nr of choice (<CR> to abort):
<
"pri" 列见 |tag-priority|。注意 这决定于当前文件,因而
":tselect xxx" 可能会输出不同的结果。
如果 tags 文件给出标签的类型。"kind" 列输出此信息。
"info" 列给出 tags 文件找到的信息。这决定于产生 tags
文件的程序。
如果列表很长,你可能会看到 |more-prompt|。如果你已经看
到要用的标签,按 'q' 并输入那个数字。
*:sts* *:stselect*
:sts[elect][!] [ident] ":tselect[!] [ident]" 并分割窗口以显示选择的标签。
{Vi 无此功能}
*g]*
g] 类似于 CTRL-],但使用 ":tselect" 而不是 ":tag"。
{Vi 无此功能}
*v_g]*
{Visual}g] 和 "g]" 相同,但使用高亮文本作为标识符。
{Vi 无此功能}
*:tj* *:tjump*
:tj[ump][!] [ident] 类似于 ":tselect",但如果只有一个匹配,直接跳转之。
{Vi 无此功能}
*:stj* *:stjump*
:stj[ump][!] [ident] ":tjump[!] [ident]" 并分割窗口以显示选择的标签。
{Vi 无此功能}
*g_CTRL-]*
g CTRL-] 类似于 CTRL-],但使用 ":tjump" 而不是 ":tag"。
{Vi 无此功能}
*v_g_CTRL-]*
{Visual}g CTRL-] 和 "g CTRL-]" 相同,但使用高亮文本作为标识符。
{Vi 无此功能}
*:tn* *:tnext*
:[count]tn[ext][!] 跳转到向下 [count] 个匹配的标签 (缺省为 1)。[!] 见
|tag-!|。{Vi 无此功能}
*:tp* *:tprevious*
:[count]tp[revious][!] 跳转到向上 [count] 个匹配的标签 (缺省为 1)。[!] 见
|tag-!|。{Vi 无此功能}
*:tN* *:tNext*
:[count]tN[ext][!] 和 ":tprevious" 相同。{Vi 无此功能}
*:tr* *:trewind*
:[count]tr[ewind][!] 跳转到第一个匹配的标签。如果给出 [count],跳到第
[count] 个匹配的标签。[!] 见 |tag-!|。{Vi 无此功能}
*:tf* *:tfirst*
:[count]tf[irst][!] 和 ":trewind" 相同。{Vi 无此功能}
*:tl* *:tlast*
:tl[ast][!] 跳到最后匹配的标签。[!] 见 |tag-!|。{Vi 无此功能}
*:lt* *:ltag*
:lt[ag][!] [ident] 跳转到标签 [ident] 上并在当前窗口的新位置列表中加入匹
配的标签。
[ident] 可以是正规表达式,见 |tag-regexp|。如果
[ident] 没有给出,使用标签栈上最后的标签名。查找标签行
的搜索模式会加上 "\V" 前缀,转义所有的特殊字符 (very
nomagic)。显示匹配标签的位置列表独立于标签栈。 [!] 见
|tag-!|。
{Vi 无此功能}
如果没有其他消息,Vim 显示跳到的是哪个匹配的标签,还有匹配标签的总数: >
tag 1 of 3 or more
" or more" 用于说明 Vim 并没有尝试完所有的 tags 文件。多用几次 ":tnext" 或者用
":tlast" 也许会找到更多。
如果因为有其他的消息使得你没看到这个消息,或者你想知道现在在哪里,以下这个命令
会再次显示本消息 (并跳转到最近一次的相同的标签): >
:0tn
<
*tag-skip-file*
如果找到一个匹配的标签,但是相应的文件却不存在,该匹配被跳过,而使用下一个匹
配。Vim 报告这一点,提醒你文件的丢失。在匹配列表的结束处,会给出错误。
*tag-preview*
标签匹配表也可用在预览窗口。命令和上面一样,除了前面有个 "p"。
{仅当编译时加入 |+quickfix| 特性才有效}
*:pts* *:ptselect*
:pts[elect][!] [ident] ":tselect[!] [ident]" 并在预览窗口显示新的标签。详情见
|:ptag|。
{Vi 无此功能}
*:ptj* *:ptjump*
:ptj[ump][!] [ident] ":tjump[!] [ident]" 并在预览窗口显示新的标签。详情见
|:ptag|。
{Vi 无此功能}
*:ptn* *:ptnext*
:[count]ptn[ext][!] 在预览窗口里 ":tnext"。见 |:ptag|。
{Vi 无此功能}
*:ptp* *:ptprevious*
:[count]ptp[revious][!] 在预览窗口里 ":tprevious"。见 |:ptag|。
{Vi 无此功能}
*:ptN* *:ptNext*
:[count]ptN[ext][!] 等价于 ":ptprevious"。
{Vi 无此功能}
*:ptr* *:ptrewind*
:[count]ptr[ewind][!] 在预览窗口中 ":trewind"。见 |:ptag|。
{Vi 无此功能}
*:ptf* *:ptfirst*
:[count]ptf[irst][!] 等价于 ":ptrewind"。
{Vi 无此功能}
*:ptl* *:ptlast*
:ptl[ast][!] 在预览窗口中见 ":tlast"。见 |:ptag|。
{Vi 无此功能}
==============================================================================
4. 标签细节 *tag-details*
*static-tag*
静态标签是为特定文件定义的标签。在 C 程序里,这可能是一个静态函数。
Vi 里跳转某个标签的同时设置当前搜索模式。这意味着在标签跳转后,"n" 命令不再查
找跳转前最后使用的模式了。Vim 没有这么做,因为我们认为这是一个错误。你仍然可以
从搜索历史里查找到标签的搜索模式。如果你真的想要从前 Vi 那样的行为,在
'cpoptions' 里设置 't' 标志位。
*tag-binary-search*
Vim 使用二分法查找标签文件,以快速查找到希望找到的标签 (如果编译时打开
|+tag_binary| 特性的话)。不过这只有在 tags 文件按 ASCII 字节值排序才有效。因
此,如果没有匹配,Vim 会按照线性查找再来一次。如果你只想要线性查找。复位
'tagbsearch' 选项。或者更好的: 对 tags 文件排序!
注意 如果不查找特定名字,标签的查找不使用二分法查找。这包括忽略大小写的查找或
不以固定字符串开始的正规表达式的查找。这样的标签搜索可能会慢很多。前者可以用大
小写合并排序来解决。详情见 'tagbsearch'。
*tag-regexp*
":tag" 和 "tselect" 命令接受正规表达式参数。|pattern| 可以看到如何使用特别的字
符。如果参数以 '/' 开始,它被认为是一个模式。如果不是,它被认为是按本义出现的
完整的标签名。
示例: >
:tag main
< 跳转到最高优先级的 "main" 标签。 >
:tag /^get
< 跳转到最后优先级的 "get" 开始的标签。 >
:tag /norm
< 列出所有包含 "norm" 的标签,例如 "id_norm"。
如果参数既能按本义匹配,也能按正规表达式匹配,本义匹配有更高的优先级。比如,
":tag /open" 在 "open_file" 和 "file_open" 之前匹配 "open"。
如果使用模式,那么忽略大小写。如果你想在模式中匹配大小写,使用 "\C"。
*tag-!*
如果当前文件里有需要的标签,就没有问题。不然,采取的行动决定于当前文件是否发生
了改变,还有是否命令之后加了 !,还有 'autowrite' 选项:
标签在 文件是 autowrite ~
当前文件里 否改变 ! 选项 行动 ~
-----------------------------------------------------------------------------
是 x x x 转到标签
否 否 x x 读入其他文件,转到标签
否 是 是 x 放弃当前文件,读入其他文件,转到标签
否 是 否 开 写入当前文件,读入其他文件,转到标签
否 是 否 关 失败
-----------------------------------------------------------------------------
- 如果标签在当前文件里,该命令总能工作。
- 如果标签在另外的文件里而当前文件没有改变。那个文件成为当前文件,并读入到缓冲
区里。
- 如果标签在另外的文件里而当前文件发生了改变。而命令后加了 !,那么当前文件的改
变被放弃,那个文件成为当前文件,并读入缓冲区。
- 如果标签在另外的文件里而当前文件发生了改变。而 'autowrite' 选项被打开,那么
当前文件的改变被保存,那个文件成为当前文件,并读入缓冲区。
- 如果标签在另外的文件里而当前文件发生了改变。而 'autowrite' 选项被关闭,那么
该命令失败。此时,如果你想保存改变,先用 ":w" 命令,再用不带参数的 ":tag"。
这是因为标签已经在堆栈上了。如果你想放弃改变,你可以用 ":tag!" 命令。
*tag-security*
注意 Vim 为了安全原因禁止某些命令。这类似于在当前目录下的 exrc/vimrc 文件里使
用了 'secure' 选项。见 |trojan-horse| 和 |sandbox|。
如果 {tagaddress} 改变了缓冲区,你会得到警告:
"WARNING: tag command changed a buffer!!!"
在将来的版本里,也许会禁止对缓冲区的改变。这些都是为了安全原因: 有的人可能在
tags 文件里隐藏了恶意的命令。如果不这么做,你也许不能看到这一点。例如: >
:$d|/tag-function-name/
{Vi 没有这个安全保护措施}
Vi 里跳转某个标签的同时设置当前搜索模式。Vim 没有这么做,以前的搜索模式还是记
住的。除非 'cpoptions' 里设置了 't' 标志位。搜索历史里包含了这个搜索模式,所以
在搜索失败的时候你可以修改这个模式。
*emacs-tags* *emacs_tags* *E430*
Emacs 风格的 tag 文件只有在 Vim 编译的时候加入 |+emacs_tags| 特性时才有效。对
不起,这里没有 Emacs 标签文件的解释,支持它只是为了后向兼容。:-)。
Emacs 标签文件的行可能很长。Vim 只处理不超过 510 字节的行。要看到哪些行被忽
略,设置 'verbose' 为 5 或更高。
*tags-option*
'tags' 选项是文件名的列表。其中的每个文件都用来搜索标签。这可以用来指定不同于
缺省的 "tags" 文件的标签文件。它也可以用来访问一个公用的标签文件。
下列情况下,不再查找列表中的下个文件:
- 找到了当前缓冲区的匹配的静态标签。
- 找到了全局标签。
同时也取决于 'ignorecase' 选项。如果关闭了,而当前标签文件找到大小写不符合的匹
配,那么就会查找下一个文件。如果没有匹配大小写的标签,则使用第一个大小写不符合
的匹配。如果 'ignorecase' 打开,而找到全局的匹配 (不论大小写),则立即使用之,
而无须继续查找下一个文件。
如果标签文件以 "./" 开始,则 '.' 会被替代成当前的文件所在的路径。这样,你可以
使用当前文件所在的目录下的标签文件 (无论当前目录在哪里)。使用 "./" 的逻辑是,
你可以定义哪个标签文件最先查找: 先当前目录 ("tags,./tags"),还是先当前文件所处
的目录 ("./tags,tags")。
例如: >
:set tags=./tags,tags,/home/user/commontags
在这个例子里,先查找当前文件所处目录的 "tags" 文件。再查找当前目录下的 "tags"
文件。如果没有,再查找 "/home/user/commontags"。
要 Vi 兼容,可以在 'cpoptions' 里包含 'd' 标志位。这样,"./tags" 会是当前目录
下的 tags 文件,而不是当前文件所在的目录下的。
除了逗号以外,也可以用空格。而在字符串值的选项里,空格需要用反斜杠转义: >
:set tags=tags\ /home/user/commontags
这样,要在文件名里包含空格,需要三个反斜杠。要在文件名里包含逗号,需要两个反斜
杠。例如,可以用: >
:set tags=tag\\\ file,/home/user/common\\,tags
来指定文件 "tag file" 和 "/home/user/common,tags"。'tags' 选项会包含值
"tag\ file,/home/user/common\,tags"。
如果打开 'tagrelative' 选项 (这是缺省值) 而使用别的目录的标签文件,该标签文件
所引用的文件名相对于标签文件本身所处的目录。
==============================================================================
5. 标签文件格式 *tags-file-format* *E431*
*ctags* *jtags*
标签文件是外部程序创建的,比如 "ctags"。对每个函数,它会包含一个标签。有些版本
的 "ctags" 会为每个 "#define" 宏、类型等价定义 (typedef)、枚举 (enum) 等也创建
标签。
能产生标签文件的程序有:
ctags 大多数 Unix 系统都能找到。只支持 C。只有基本的功能。
*Exuberant_ctags*
exuberant ctags 这是很好的一个。它支持 C、C++、Java、Fortran、Eiffel
等等。它能为很多项目产生标签。见
http://ctags.sourceforge.net。
etags 和 Emacs 有关。支持很多语言。
JTags 用 Java 编写,为 Java 而设计。可以在这里找到:
http://www.fleiner.com/jtags/。
ptags.py 用 Python 编写,为 Python 而设计。它位于你的 Python 源
代码目录 Tools/scripts/ptags.py。
ptags 用 Perl 编写,为 Perl 而设计。可以在这里找到:
http://www.eleves.ens.fr:8080/home/nthiery/Tags/。
gnatxref 为 Ada 而设计。见 http://www.gnuada.org/。gnatxref 是
gnat 包的一部分。
标签文件的行应是以下三种格式之一:
1. {tagname} {TAB} {tagfile} {TAB} {tagaddress}
2. {tagfile}:{tagname} {TAB} {tagfile} {TAB} {tagaddress}
3. {tagname} {TAB} {tagfile} {TAB} {tagaddress} {term} {field} ..
第一个是普通的标签,和 Vi 完全兼容。传统的 ctags 实现只能产生这种格式。通常,
这用于被别的文件所引用的全局函数,
标签文件行可以用 <LF> 或者 <CR><LF> 结尾。在 Macintosh 上,<CR> 也能工作。<CR>
和 <NL> 字符不应该在行内出现。
*tag-old-static*
第二个格式只限于静态标签。现在已经废弃了,被第三个格式取而代之。只有 Elvis
1.x, Vim 还有很少的 ctags 版本支持。静态变量用于本地函数,只有文件 {tagfile}
才引用。注意 对静态变量而言,{tagfile} 的两次出现必须完全一致。关于如何使用静
态变量,见下面的 |tags-option|。
第三个格式是新出现的。它在每行尾部的可选字段上包含了附加的信息。它和 Vi 后向兼
容。只有新的 ctags 版本 (比如 Exuberant ctags) 才支持这种格式。
{tagname} 标识符。通常是函数的名字,但可以是任何标识符。不能包含 <Tab>。
{TAB} 单个 <Tab> 字符。注意: 以前的版本允许任意多个空白字符。现在不
支持,因为 {tagfile} 里可能包含空格。编译时加入
|+tag_any_white| 特性可以重新打开这个功能。 *tag-any-white*
{tagfile} 包含 {tagname} 定义的文件。可以是绝对路径或者相对路径。还可以
包含环境变量甚至通配符 (尽管使用通配符很值得怀疑)。它不能包含
<Tab>。
{tagaddress} 可以定位到 tag 的光标位置的 Ex 命令。可以是任何 Ex 命令,尽管
有一些限制 (见 |tag-security|)。Posix 只允许行号和搜索命令,这
也是最常用的。
{term} ;" 分号和双引号两个字符。这被 Vi 解释为注释的开始,从而忽略其
后的部分。这样,就能和 Vi 后向兼容,因为 Vi 忽略后面的字段。
{field} .. 可选的字段列表。每个字段有以下形式:
<Tab>{fieldname}:{value}
{fieldname} 标识字段,并且只能包含字母 [a-zA-Z]。
{value} 可以使任何字符串,但不能包含 <Tab>。
以下字符有特殊含义:
"\t" 代表 <Tab>
"\r" 代表 <CR>
"\n" 代表 <NL>
"\\" 代表单个 '\' 字符
有一个字段不需要 ':'。那就是标签的类型。它的处理方式就像前面
有 "kind:" 开头那样。ctags 能产生的类型见它的文档。
唯一的 Vim 能识别的其他字段是 "file:" (带一个空值)。用于静态变
量。
标签文件的开头可以包含这样开始的行:
!_TAG_
排序以后,他们一般都排在最前面。只有很少的以 "!" 开头的标签能排在他们前面。Vim
识别两项。第一个是指示文件是否排序的标志。如果找到这么一行,Vim 使用二分法查找
标签文件:
!_TAG_FILE_SORTED<Tab>1<Tab>{anything} ~
标签文件可以按大小写合并排序,以免 'ignorecase' 打开时只能进行线性查找。详情见
'tagbsearch'。这时可以用值 2:
!_TAG_FILE_SORTED<Tab>2<Tab>{anything} ~
另一个 Vim 识别的标签,只有在编译时带了 |+multi_byte| 特性才有效。它指定标签文
件的编码:
!_TAG_FILE_ENCODING<Tab>utf-8<Tab>{anything} ~
这里 "utf-8" 是标签们所用的编码。Vim 会把查找的标签从 'encoding' 转为标签文件
的编码。当列出标签时,则反之。如果转换失败,则直接使用未经转换的标签。
*tag-search*
标签搜索命令可以是任何 Ex 命令,但通常就是普通的搜索命令。比如:
tag1 file1 /^main(argc, argv)/ ~
tag2 file2 108 ~
该命令执行时总假设不设定 'magic'。搜索模式里仅有的特别的字符是 "^" (行首) 和
"$" (<EOL>)。见 |pattern|。注意,你必须在搜索文本里的每个反斜杠前加上反斜杠。
这和 Vi 反向兼容。
*E434* *E435*
如果该命令是一个普通的搜索命令 (也就是,以 "/" 或 "?" 开头和结尾),会进行一些
特殊处理:
- 搜索从文件第 1 行开始。
如果用 "/",搜索方向为正向,"?" 则为反向。
注意 'wrapscan' 没有影响,总是搜索整个文件。{Vi 使用 'wrapscan',使得有时标
签可能找不到}。{Vi 从别的文件的第二行开始搜索。如果没有置位 'wrapscan',它不
会去找别的文件的第一行的标签}
- 如果搜索失败,忽略大小写再重新尝试一次。如果还不行,搜索:
"^tagname[ \t]*("
(实际的标签前面加上 '^' 而后面加上 "[ \t]*(")。应用函数名的时候,它会找到在
第 0 列的函数名。这会有助于找到该函数,即使它的参数和生成 tags 文件时有差
异。如果还不行,进行另外一个搜索:
"^[#a-zA-Z_].*\<tagname[ \t]*("
这意味着: 以 '#' 或者一个标识符开始的一行,包含标签本身,后面紧跟空白和一个
'('。这会找到宏名和前面有返回类型的函数名。{Vi 没有这些额外的搜索}
==============================================================================
6. 头文件搜索 *include-search* *definition-search*
*E387* *E388* *E389*
这些命令递归地查找当前文件和所有遇到的头文件的一个字符串。这可以用来查找变量的
定义,函数或者宏。如果只想查找当前缓冲区,用 |pattern-searches| 列出来的命令。
这些命令只有在编译时加入 |+find_in_path| 特性才会有效。
如果一个文件的某行包含另一个文件,那么那个文件在当前缓冲区继续之前先进行搜索。
头文件里包含的头文件也会被搜索。当头文件找不到时,它被悄悄地忽略掉。用
|:checkpath| 命令检查哪些文件可能找不到。是不是因为你的 'path' 选项没有设对。
注意: 被搜索的是头文件本身,不是可能正在编辑它的缓冲区。只有当前的文件除外,它
使用缓冲区里的行。
字符串可能是任何的关键字或者定义的宏。对于关键字,任何匹配都会找到。对于定义的
宏,只有用匹配 'define' 选项的行才会被找到。它的缺省值是 "^#\s*define"。这对 C
程序适用,对于其它语言你可能想改变之。C++ 的一个例子见 'define'。该字符串不能
包含换行符,只能匹配一行之内的文本。
如果找到一个定义的宏的匹配,并且该行以反斜杠结尾的话。行的显示在下一行继续。
"[" 开头的命令从当前文件开始查找。"]" 开始的命令从当前光标位置开始。
'include' 选项用于定义可以包含另一个文件的行。缺省是 "\^#\s*include"。它适用于
C 程序。注意: Vim 并不试图识别 C 语法。如果 'include' 选项在 #ifdef/#endif 之
间或者注释内的一行上匹配,它也会被搜索到。'isfname' 选项用于识别匹配之后的文件
名。
'path' 选项用于查找不含绝对路径的头文件所在的目录。
'comments' 选项用来显示或者跳转到一行的命令。如果定义的模式可能包含注释,这些
行用来跳过搜索,除非使用 [!]。一个特例: 如果一行匹配模式 "^# *define",它不会
被认为是注释。
如果你想列出所有的匹配,然后选择一个并跳转之,你可以使用一个映射来做这件事。这
里是一个例子: >
:map <F4> [I:let nr = input("Which one: ")<Bar>exe "normal " . nr ."[\t"<CR>
<
*[i*
[i 显示第一个包含光标所在的关键字的行。搜索从文件开头开
始。看起来像注释的行被忽略 (见 'comments' 选项)。如果
给出一个计数,跳转到第 count 个匹配的行,注释行不忽
略。{Vi 无此功能}
*]i*
]i 类似于 "[i",但是从当前光标位置开始。
{Vi 无此功能}
*:is* *:isearch*
:[range]is[earch][!] [count] [/]pattern[/]
类似于 "[i" 和 "]i",但在 [range] 行范围搜索 (缺省: 整
个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
*[I*
[I 显示包含光标下的关键字的所有的行。找到的每行都显示文件
名和行号。搜索从文件头开始。{Vi 无此功能}
*]I*
]I 类似于 "[I",但是从当前光标位置开始。
{Vi 无此功能}
*:il* *:ilist*
:[range]il[ist][!] [/]pattern[/]
类似于 "[I" 和 "]I",但在 [range] 行范围搜索 (缺省:
整个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
*[_CTRL-I*
[ CTRL-I 跳转到第一个包含光标所在的关键字的行。搜索从文件开头开
始。看起来像注释的行被忽略 (见 'comments' 选项)。如果
给出一个计数,跳转到第 count 个匹配的行,注释行不忽
略。{Vi 无此功能}
*]_CTRL-I*
] CTRL-I 类似于 "[ CTRL-I",但是从当前光标位置开始。
{Vi 无此功能}
*:ij* *:ijump*
:[range]ij[ump][!] [count] [/]pattern[/]
类似于 "[ CTRL-I" 和 "] CTRL-I",但在 [range] 行范围
搜索 (缺省: 整个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
CTRL-W CTRL-I *CTRL-W_CTRL-I* *CTRL-W_i*
CTRL-W i 打开一个新窗口,把光标放在第一个包含光标所在的关键字的
行。搜索从文件开头开始。看起来像注释的行被忽略 (见
'comments' 选项)。如果给出一个计数,跳转到第 count 个
匹配的行,注释行不忽略。 {Vi 无此功能}
*:isp* *:isplit*
:[range]isp[lit][!] [count] [/]pattern[/]
类似于 "CTRL-W i" 和 "CTRL-W i",但在 [range] 行范围
搜索 (缺省: 整个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
*[d*
[d 显示第一个包含光标所在的关键字的宏定义。搜索从文件头
开始。如果给出一个计数,跳转到第 count 个匹配的行。
{Vi 无此功能}
*]d*
]d 类似于 "[d",但是从当前光标位置开始。{Vi 无此功能}
*:ds* *:dsearch*
:[range]ds[earch][!] [count] [/]string[/]
类似于 "[d" 和 "]d",但在 [range] 行范围搜索 (缺省: 整
个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
*[D*
[D 显示包含光标下的宏的所有的宏定义。找到的每行都显示文件
名和行号。搜索从文件头开始。{Vi 无此功能}
*]D*
]D 类似于 "[D",但是从当前光标位置开始。{Vi 无此功能}
*:dli* *:dlist*
:[range]dl[ist][!] [/]string[/]
类似于 "[D" 和 "]D",但在 [range] 行范围搜索 (缺省: 整
个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
注意 ":dl" 功能同带 "l" 标志的 ":delete"。
*[_CTRL-D*
[ CTRL-D 跳转到第一个包含光标所在的关键字的宏定义。搜索从文件头
开始。如果给出一个计数,跳转到第 count 个匹配的行。
{Vi 无此功能}
*]_CTRL-D*
] CTRL-D 类似于 "[ CTRL-D",但是从当前光标开始。{Vi 无此功能}
*:dj* *:djump*
:[range]dj[ump][!] [count] [/]string[/]
类似于 "[ CTRL-D" 和 "] CTRL-D",但是在 [range] 行范
围内搜索 (缺省: 整个文件)。
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
CTRL-W CTRL-D *CTRL-W_CTRL-D* *CTRL-W_d*
CTRL-W d 打开一个新窗口,把光标放在第一个包含光标所在的关键字的
宏定义行。搜索从文件头开始。如果给出一个计数,跳转到第
count 个匹配的行。{Vi 无此功能}
*:dsp* *:dsplit*
:[range]dsp[lit][!] [count] [/]string[/]
类似于 "CTRL-W d",但是在 [range] 行范围内查找
(缺省: 整个文件).
关于 [/] 和 [!] 见 |:search-args|。{Vi 无此功能}
*:che* *:checkpath*
:che[ckpath] 列出所有找不到的头文件。{Vi 无此功能}
:che[ckpath]! 列出所有的头文件。{Vi 无此功能}
*:search-args*
以上命令通用的参数:
[!] 如果包含,查找包括识别为注释的匹配。如果不包含,则被识别为注释 (根
据 'comments' ) 或者是一个 C 注释 ("//" 之后或者 /* */ 之间) 的行不参加
匹配。注意 如果一行被识别为注释,但是注释在行中间结束,匹配可能丢失。另
外,如果一行是注释,但是没有被识别 (根据 'comments'),还是可能从中找到匹
配。例子: >
/* comment
foobar */
< 还是可以找到 "foobar" 的匹配,因为该行没有被识别为注释 (即使语法高亮能够
识别)。
注意: 因为宏定义一般看起来不像注释,[!] 对 ":dlist"、":dsearch" 和
":djump" 没有影响。
[/] 模式可以被 '/' 包围。没有 '/' 的话,只有完整单词的匹配,就像使用模式
"\<pattern\>" 那样。只有在第二个 '/' 之后,下一个命令才可以通过 '|' 附加
在后。例如: >
:isearch /string/ | echo "the last one"
< 对于 ":djump"、":dsplit"、":dlist" 和 ":dsearch" 命令,模式是按本义理解
的字符串,而不是搜索模式。
vim:tw=78:ts=8:ft=help:norl: