注:以下资源来源于网络
熟练的使用ctags仅需记住下面七条命令:
1.$ ctags –R * ($ 为Linux系统Shell提示符)
2. $ vi –t tag (请把tag替换为您欲查找的变量或函数名)
3. :ts (ts 助记字:tags list, “:”开头的命令为VI中命令行模式命令)
4. :tp (tp 助记字:tags preview)---此命令不常用,可以不用记
5. :tn (tn 助记字:tags next) ---此命令不常用,可以不用记
6. Ctrl + ]
7. Ctrl + o
注意:运行vim的时候,必须在“tags”文件所在的目录下运行。否则,运行vim的时候还要用“:settags=”命令设定“tags”文件的路径,这样vim才能找到“tags”文件。在完成编码时,可以手工删掉tags文件。
在.vimrc中加入
" -- ctags --
" map <ctrl>+F12 to generate ctags for current folder:
map <C-F12> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR><CR>
" add current directory's generated tags file to available tags
set tags+=./tags
之后,进入vim后<ctrl>+F12就会自动生成当前目录和子目录的tags
:Tlist 打开tag管理列表
:WMToggle打开winmanager
:e 目录 打开目录
"ctags"是一个独立的程序,绝大多数Unix系统上都会预装这个程序。
1、使用tags
tag是什么?一个位置。它记录了关于一个标识符在哪里被定义的信息,比如C或C++程序中的一个函数定义。这种tag聚集在一起被放入一个tags文件。这个文件可以让Vim能够从任何位置起跳达到tag所指示的位置-标识符被定义的位置。
下面的命令可以为当前目录下的所有C程序文件生成对应的tags文件:(shell command) ctags *.c
现在你在Vim中要跳到一个函数的定义(如startlist)就可以用下面的命令:(ex command) :tag startlist,这个命令会带你到函数"startlist"的定义处,哪怕它是在另一个文件中。
CTRL+] 命令会取当前光标下的word作为tag的名字并直接跳转。这使得在大量C程序中进行探索更容易一些。 假设你正看函数"write block",发现它调用了一个叫"write line"的函数,这个函数是干什么的呢?你可以把光标置于"write_line"上,按下CTRL+] 即可。
如果"write_line"函数又调用了"write_char".你当然又要知道这个函数又是什么功能。 同时,置光标于"write_char"上按下CTRL+]。现在你位于函数"write_char"的定义处。
":tags"命令会列出现在你就已经到过哪些tag了:(ex command)
:tags
# TO tag FROM line in file/text
1 1 write_line 8 write_block.c
2 1 write_char 7 write_line.c
现在往回走。CTRL+T命令会跳到你前一次的tag处。在上例中它会带你到调用了"write_char"的"write_line"函数的地方。CTRL+T可以带一个命令记数, 以此作为往回跳的次数, 你已经向前跳过了,现在正在往回跳,我们再往前跳一次。下面的命令可以直接跳转到当前tag序列的最后:(ex command) :tag。你也可以给它一个前辍, 让它向前跳指定的步长. 比如":3tag"。CTRL+T也可以带一个前辍。
这些命令可以让你向下深入一个函数调用树(使用CTRL+]), 也可以回溯跳转(使用CTRL+T). 还可以随时用":tags"看你当前的跳转历史记录。
2、分隔窗口
":tag"命令会在当前窗口中载入包含了目标函数定义的文件。但假设你不仅要查看新的函数定义,还要同时保留当前的上下文呢?你可以在":tag"后使用一个分隔窗口命令":split"。Vim还有一个一举两得的命令:(ex command) :stag tagname。要分隔当前窗口并跳转到光标下的tag:(normal mode command) CTRL+W+]。如果同时还指定了一个命令记数, 它会被当作新开窗口的行高.
3、多个tags文件
如果你的源文件位于多个目录下,你可以为每个目录都建一个tags文件。Vim会在使用某个目录下的tags文件进行跳转时只在那个目录下跳转。
要使用更多tags文件,可以通过改变'tags'选项的设置来引入更多的tags文件。如:(ex command) :set tags=./tags, ./../tags, ./*/tags。这样的设置使Vim可以使用当前目录下的tags文件,上一级目录下的tags文件,以及当前目录下所有层级的子目录下的tags文件。这样可能会引入很多的tags文件,但还有可能不敷其用。比如说你正在编辑"~/proj/src"下的一个文件,但又想使用"~/proj/sub/tags"作为 tags文件。对这种Vim情况提供了一种深度搜索目录的形式。如下:(ex command) :set tags=~/proj/**/tags
4、单个tags文件
Vim在搜索众多的tags文件时,你可能会听到你的硬盘在咔嗒咔嗒拼命地叫。显然这会降低速度。如果这样还不如花点时间生成一个大一点的tags文件。这需要一个功能丰富的ctags程序,比如上面提到的那个。它有一个参数可以搜索整个目录树:(shell command)
cd ~/proj
ctags -R
用一个功能更强的ctags的好处是它能处理多种类型的文件。不光是C和C++源程序,也能对付Eiffel或者是Vim脚本。你可以参考ctags程序的文件调整自己的需要。
现在你只要告诉Vim你那一个tags文件在哪就行了:(ex command) :set tags=~/proj/tags
5、同名tag
当一个函数被多次重载(或者几个类里都定义了一些同名的函数),":tag"命令会跳转到第一个符合条件的。如果当前文件中就有一个匹配的,那又会优先使用它。当然还得有办法跳转到其它符合条件的tag去:(ex command) :tnext重复使用这个命令可以发现其余的同名tag。如果实在太多,还可以用下面的命令从中直接选取一个:(ex command) :tselect tagname,Vim会提供给你一个选择列表,例如:(Display)
# pri kind tag file
1 F f mch_init os_amiga.c
mch_init()
2 F f mch_init os_mac.c
mch_init()
3 F f mch_init os_msdos.c
mch_init(void)
4 F f mch_init os_riscos.c
mch_init()
Enter nr of choice (<CR> to abort):
现在你只需键入相应的数字(位于第一栏的)。 其它栏中的信息是为了帮你作出决策的。在多个匹配的tag之间移动,可以使用下面这些命令:(ex command)
:tfirst go to first match
:[count]tprevious go to [count] previous match
:[count]tnext go to [count] next match
:tlast go to last match
如果没有指定[count],默认是1。
6、tag的名字
命令补齐真是避免键入一个长tag名的好办法。只要输入开头的几个字符然后按下制表符:(ex command) :tag write_<Tab>。Vim 会为你补全第一个符合的tag名。如果还不合你意,接着按制表符直到找到你要的。有时候你只记得一个tag名的片段。或者有几个tag开头相同。这里你可以用一个模式匹配来告诉Vim你要找的tag。假设你想跳转到一个包含"block"的tag。首先键入命令:(ex command) :tag /block。现在使用命令补齐:按<Tab>。Vim会找到所有包含"block"的tag并先提供给你第一个符合的。"/"告诉Vim下面的名字不是一五一十的tag名,而是一个搜索模式。通常的搜索技巧都可以用在这里。比如你有一个tag以"write "开始:(ex command) :tselect / ^write_。"^"表示这个tag以"write_"开始。不然在半中间出现write的tag也会被搜索到。同样"$"可以用于告诉Vim要查找的tag如何结束。
7、tags的浏览器
CTRL+]可以直接跳转到以当前光标下的word为tag名的地方去,所以可以在一个tag列表中使用它。下面是一个例子。首先建立一个标识符的列表(这需要一个好的ctags):(shell command)
ctags --c-types=f -f functions *.c
现在直接启动Vim, 以一个垂直分隔窗口的编辑命令打开生成的文件:(shell command)
vim
:vsplit functions
这个窗口中包含所有函数名的列表。可能会有很多内容,但是你可以暂时忽略它。用一个":setlocal ts=99"命令清理一下显示。在该窗口中,定义这样的一个映射:(ex command)
:nnoremap <buffer> <CR> 0ye<C-W>w:tag <C-R>"<CR>
现在把光标移到你想要查看其定义的函数名上,按下回车键,Vim就会在另一个窗口中打开相应的文件并定位到到该函数的定义上。
8、其它相关主题
设置'ignorecase'也可以让tag名的处理忽略掉大小写。'tagsearch'选项告诉Vim当前参考的tags文件是否是排序过的。默认情况假设该文件是排序过的,这会使tag的搜索快一些,但如果tag文件实际上没有排序就会在搜索时漏掉一些tag。'taglength'告诉Vim一个tag名字中有效部分的字符个数。
例:
#include <stdio.h>
int very_long_variable_1;
int very_long_variable_2;
int very_long_variable_3;
int very_long_variable_4;
int main()
{
very_long_variable_4 = very_long_variable_1 *
very_long_variable_2;
}
对于上面这段代码, 4个变量长度都为20, 如果将'taglength'设为10, 则:(ex command)
:tag very_long_variable_4
会匹配到4个tag,而不是1个,光标停留在very_long_variable_1所在行上,因为被搜索的tag部分只有前面的10个字符: "very_long_",相应的显示是(是gvim中文版的真正显示,不是翻译的):(Display)
找到tag: 1/4 或更多
转自:http://computerscience.yculblog.com/post.1798348.html
csupport:
----------华丽分割------------
1.在~/.vim/c-support/templates/Templates可以设置版权信息,如作者、信箱、版权归属等,新建.c或.cpp文件是可以看到,并且列出了使用模板文件位置,可以自己编辑
2.\if 插入一般函数
3.\im 插入主函数
4.\cfu 插入函数头,即函数说明
5.\cfr 插入一个frame comment,可以用来写变量说明
6.\p< 插入一个include , 并且把光标放在<>中
7.\rc 保存并编译
8.\rr 运行
9.\nr 可以在~/.vim/c-support/codesnippets中编写一些预编译代码或者代码块,通过此命令使用
---------------------------------------------
总之c.vim是个不错的c/c++辅助代码插件 , 恩.
---------------------附:详细的c.vim hotkey-------------------------
-- Help ---------------------------------------------------------------
\hm show manual for word under the cursor (n,i)
\hp show plugin help (n,i)
-- Comments -----------------------------------------------------------
\cl end-of-line comment (n,v,i)
\cj adjust end-of-line comment(s) (n,v,i)
\cs set end-of-line comment column (n)
\c* code -> comment /* */ (n,v)
\cc code -> comment // (n,v)
\co comment -> code (n,v)
\cfr frame comment (n,i)
\cfu function comment (n,i)
\cme method description (n,i)
\ccl class description (n,i)
\cd date (n,v,i)
\ct date \& time (n,v,i)
-- Statements ---------------------------------------------------------
\sd do { } while (n,v,i)
\sf for (n,i)
\sfo for { } (n,v,i)
\si if (n,i)
\sif if { } (n,v,i)
\sie if else (n,v,i)
\sife if { } else { } (n,v,i)
\sw while (n,i)
\swh while { } (n,v,i)
\ss switch (n,v,i)
\sc case (n,i)
\s{ { } (n,v,i)
-- Preprocessor -------------------------------------------------------
\p< #include <> (n,i)
\p" #include "" (n,i)
\pd #define (n,i)
\pu #undef (n,i)
\pie #if #else #endif (n,v,i)
\pid #ifdef #else #endif (n,v,i)
\pin #ifndef #else #endif (n,v,i)
\pind #ifndef #def #endif (n,v,i)
\pi0 #if 0 #endif (n,v,i)
\pr0 remove #if 0 #endif (n,i)
\pe #error (n,i)
\pl #line (n,i)
\pp #pragma (n,i)
-- Idioms -------------------------------------------------------------
\if function (n,v,i)
\isf static function (n,v,i)
\im main() (n,v,i)
\i0 for( x=0; x<n; x+=1 ) (n,v,i)
\in for( x=n-1; x>=0; x-=1 ) (n,v,i)
\ie enum + typedef (n,i)
\is struct + typedef (n,i)
\iu union + typedef (n,i)
\ip printf() (n,i)
\isc scanf() (n,i)
\ica p=calloc() (n,i)
\ima p=malloc() (n,i)
\isi sizeof() (n,v,i)
\ias assert() (n,v)
\ii open input file (n,i)
\io open output file (n,i)
-- Snippets -----------------------------------------------------------
\nr read code snippet (n,i)
\nw write code snippet (n,v,i)
\ne edit code snippet (n,i)
\np pick up prototype (n,v,i)
\ni insert prototype(s) (n,i)
\nc clear prototype(s) (n,i)
\ns show prototype(s) (n,i)
\ntl edit local templates (n,i)
\ntg edit global templates (n,i)
\ntr rebuild templates (n,i)
-- C++ ----------------------------------------------------------------
\+co cout << << endl; (n,i)
\+c class (n,i)
\+cn class (using new) (n,i)
\+ci class implementation (n,i)
\+cni class (using new) implementation (n,i)
\+mi method implementation (n,i)
\+ai accessor implementation (n,i)
\+tc template class (n,i)
\+tcn template class (using new) (n,i)
\+tci template class implementation (n,i)
\+tcni template class (using new) impl. (n,i)
\+tmi template method implementation (n,i)
\+tai template accessor implementation (n,i)
\+tf template function (n,i)
\+ec error class (n,i)
\+tr try ... catch (n,v,i)
\+ca catch (n,v,i)
\+c. catch(...) (n,v,i)
-- Run ----------------------------------------------------------------
\rc save and compile (n,i)
\rl link (n,i)
\rr run (n,i)
\ra set comand line arguments (n,i)
\rm run make (n,i)
\rg cmd. line arg. for make (n,i)
\rp run splint (n,i)
\ri cmd. line arg. for splint (n,i)
\rk run CodeCheck (TM) (n,i)
\re cmd. line arg. for CodeCheck (TM) (n,i)
\rd run indent (n,v,i)
\rh hardcopy buffer (n,v,i)
\rs show plugin settings (n,i)
\rx set xterm size (n, only Linux/UNIX & GUI)
\ro change output destination (n,i)
------------------------------------------------------------------------------------------------------------------------------------------
cscope使用
- 建立cscope使用的索引文件
- 在你需要浏览源码的根目录下(如你想用cscope看linux源码)使用下面命令:
- #: cscope -Rbkq<回车>
- R 表示把所有子目录里的文件也建立索引
- b 表示cscope不启动自带的用户界面,而仅仅建立符号数据库
- q生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度
- k在生成索引文件时,不搜索/usr/include目录
- 在你需要浏览源码的根目录下(如你想用cscope看linux源码)使用下面命令:
- 在源码根目录下打开任意.c文件,使用如下命令:
- Ctrl+]将跳到光标所在变量或函数的定义处 Ctrl+T返回
- :cs find s ---- 查找C语言符号,即查找函数名、宏、枚举值等出现的地方
:cs find g ---- 查找函数、宏、枚举等定义的位置,类似ctags所提供的功能
:cs find d ---- 查找本函数调用的函数
:cs find c ---- 查找调用本函数的函数
:cs find t: ---- 查找指定的字符串
:cs find e ---- 查找egrep模式,相当于egrep功能,但查找速度快多了
:cs find f ---- 查找并打开文件,类似vim的find功能
:cs find i ---- 查找包含本文件的文 - 2的所以命令也可以且按銉来实现:
- Ctrl+\ 再按 s 表示:cs find s命令
- 同理实现cs find + g,d,c,t,e,f,i命令
- cscope_map.vim说明:
- 有英文注释的我就不说明了,我就说一下里边的键map映射
- 如: nmap <C-\>s :cs find s <C-R>=expand("<cword>")<CR><CR>
- nmap 表示在vim的普通模式下,即相对于:编辑模块和可视模式,以下是几种模式
- :map 普通,可视模式及操作符等待模式
:vmap 可视模式
:omap 操作符等待模式
:map! 插入和命令行模式
:imap 插入模式
:cmap 命令行模式
- :map 普通,可视模式及操作符等待模式
- <C-\>表示:Ctrl+\
- s表示输入(即按:s)s
- : 表示输入':'
- “cs find s"表示输入"cs find s"也即是要输入的命令
- <C-R>=expand("cword")总体是为了得到:光标下的变量或函数。cword 表示:cursor word, 类似的还有:cfile表示光标所在处的文件名吧
- <CR><CR>就是回车吧,不太清楚
- nmap 表示在vim的普通模式下,即相对于:编辑模块和可视模式,以下是几种模式
- 补充 -----------------------------------------------------------------------------------------------------------------------------------------
-
在缺省情况下, cscope 在生成数据库后就会进入它自己的查询界面,我们一般不用这个界面,所以使用了“ -b ”选项。如果你已经进入了这个界面,按 CTRL-D 退出。
Cscope 在生成数据库中,在你的项目目录中未找到的头文件,会自动到 /usr/include 目录中查找。如果你想阻止它这样做,使用“ -k ”选项。
Cscope 缺省只解析 C 文件 (.c 和 .h) 、 lex 文件 (.l) 和 yacc 文件 (.y) ,虽然它也可以支持 C++ 以及 Java ,但它在扫描目录时会跳过 C++ 及 Java 后缀的文件。如果你希望 cscope 解析 C++ 或 Java 文件,需要把这些文件的名字和路径保存在一个名为 cscope.files 的文件。当 cscope 发现在当前目录中存在 cscope.files 时,就会为 cscope.files 中列出的所有文件生成索引数据库。通常我们使用 find 来生成 cscope.files 文件,仍以 VIM 7.0 的源代码为例:
cd ~/src/vim70
find . –type f > cscope.files
cscope -bq这条命令把 ~src/vim70 目录下的所有普通文件都加入了 cscope.files ,这样, cscope 会解析该目录下的每一个文件。上面的 cscope 命令并没有使用“ -R ”参数,因为在 cscope.files 中已经包含了子目录中的文件。
注意 : find 命令输出的文件以相对路径表示,所以 cscope.out 的索引也相对于当前路径。如果你要在其它路径中使用当前的 cscope.out ,需要使用下面介绍的 -P 选项。
Cscope 只在第一次解析时扫描全部文件,以后再调用 cscope ,它只扫描那些改动过的文件,这大大提高了 cscope 生成索引的速度。
下表中列出了 cscope 的常用选项:
-R: 在生成索引文件时,搜索子目录树中的代码
-b: 只生成索引文件,不进入cscope的界面
-q: 生成cscope.in.out和cscope.po.out文件,加快cscope的索引速度
-k: 在生成索引文件时,不搜索/usr/include目录
-i: 如果保存文件列表的文件名不是cscope.files时,需要加此选项告诉cscope到哪儿去找源文件列表。可以使用“-”,表示由标准输入获得文件列表。
-I dir: 在-I选项指出的目录中查找头文件
-u: 扫描所有文件,重新生成交叉索引文件
-C: 在搜索时忽略大小写
-P path: 在以相对路径表示的文件前加上的path,这样,你不用切换到你数据库文件所在的目录也可以使用它了。要在 VIM 中使用 cscope 的功能,需要在编译 VIM 时选择“ +cscope ”。 VIM 的 cscope 接口先会调用 cscope 的命令行接口,然后分析其输出结果找到匹配处显示给用户。
-
在 VIM 中使用 cscope 非常简单,首先调用“ cscope add ”命令添加一个 cscope 数据库,然后就可以调用“ cscope find ”命令进行查找了。 VIM 支持 8 种 cscope 的查询功能,如下:
s: 查找C语言符号,即查找函数名、宏、枚举值等出现的地方
g: 查找函数、宏、枚举等定义的位置,类似ctags所提供的功能
d: 查找本函数调用的函数
c: 查找调用本函数的函数
t: 查找指定的字符串
e: 查找egrep模式,相当于egrep功能,但查找速度快多了
f: 查找并打开文件,类似vim的find功能
i: 查找包含本文件的文例如,我们想在 VIM 7.0 的源代码中查找调用 do_cscope() 函数的函数,我们可以输入:“ :cs find c do_cscope ”,回车后发现没有找到匹配的功能,可能并没有函数调用 do_cscope() 。我们再输入“ :cs find s do_cscope ”,查找这个 C 符号出现的位置,现在 VIM 列出了这个符号出现的所有位置。
我们还可以进行字符串查找,它会双引号或单引号括起来的内容中查找。还可以输入一个正则表达式,这类似于 egrep 程序的功能,但它是在交叉索引数据库中查找,速度要快得多。
VIM 提供了一些选项可以调整它的 cscope 功能:
- cscopeprg 选项用于设置 cscope 程序的位置。
- cscopequickfix 设定是否使用 quickfix 窗口来显示 cscope 的结果,详情请“ :help cscopequickfix ”;
- 如果你想 VIM 同时搜索 tag 文件以及 cscope 数据库,设置 cscopetag 选项;
- cscopetagorder 选项决定是先查找 tag 文件还是先查找 cscope 数据库。设置为 0 则先查找 cscope 数据库,设置为 1 先查找 tag 文件。我通常设置为 1 ,因为在 tag 文件中查找到的结果,会把最佳匹配列在第一位。VIM 的帮助页中给出了使用 cscope 的建议方法,使用命令“ :help cscope-suggestions ”查看。