爱德华兹名言:Linux应用程序开发(二) ── vim+ctags+cscope

来源:百度文库 编辑:偶看新闻 时间:2024/04/30 18:33:32
Linux应用程序开发(二) ── vim+ctags+cscope

六、通用的使用 VIM+Ctags+Cscope 访问程序文件的方法

1. ctags+cscope配合使用的原因:
    为什么要配合,因为,比如cscope能提供更多的查找功能等功能。但是ctags远比cscope支持更多的文件。比如要访问一个java工程文件,那么cscope是能力低下的,比如对类识别不行,但是我们仍然可以利用其一些功能,比如找到什么函数调用了这个函数。
    另外,还有点注意,ctags不能利用QuickFix窗口,而cscope可以利用,这也是cscope的好处。一般,如果仅仅有C/C++文件,用cscope更多,如果是其他文件,则用ctags更多。
    不管是用ctags还是cscope,都可以用WinManager和Taglist,来实现左边上面是文件列表,下面是Taglist,右边是文件浏览窗口的效果!但是Taglist依赖ctags,如果用cscope,ctags还是要用的。具体的让WinManager和Taglist配合的方法,见vim配置文件。

2. 生成数据库并让vim使用:
一般的做法是:在最上层目录,生成这些文件。然后vim在最上层打开,并利用下面提到的WinManager来导航到里面目录。
(1) ctags生成tags文件:
ctags -R . 可以搜索目录下所有的文件,并生成 tags 文件。
为了生成最多的tags:
C/C++这样:ctags --extra=+q --fields=+Saim --c++-kinds=+lpx --c-kinds=+lpx -R .
Java这样:ctags --java-kinds=+l -R .

(主要是--xx-kinds控制着要分析出哪些东西,如--java-kinds=+l表示要加上(+)local variable,默认的有哪些,没有哪些,用ctags --list-kinds 可以知道,off的都是默认不分析的,否则是分析的)
cscope只能分析C/C++/lex/yacc文件!

然后在vim里 :set tags=path/to/tags(用,分隔,可以多个)

(2) cscope生成cscope.in.out cscope.out cscope.po.out文件:
由于cscope默认不看非.c .yacc .lex外的文件,所以,假设你要找C和C++其他文件,要这样:
find . -name "*.h" -o -name "*.c" -o -name "*.cc" > cscope.files
cscope -bkq -i cscope.files
(找java文件同理)
而,对于纯C文件,你可以:
cscope -Rbkq ./ 即可。

然后在vim里 :cs add path/to/cscope.out
如果要重新生成,用:!cscope -Rbkq,再用 :cs reset重新读入.

3. ctags 管理跳转栈:
ctags设计来找到各种希望找的东西,如类定义处,函数定义处。对各种语言都有支持,但原设计就是针对function定义的,所以,ctags对寻找functions定义特别有效,像函数原型是默认不做tag的。
(1) vim的支持tags的命令:(这些命令在编译时要加进ctags支持才能用)
vim靠内置的命令,来支持使用ctags得到的tags文件。
:tags 列出目前你跳转的栈,可以得知当前位置 (可惜不能用QuickFix窗口)
:tag 跳到:tags列表的顶部(栈底)
:tag tagname 跳到tagname的定义处
Ctrl+] 压栈(跳到标记定义处) Ctrl+W ] 在横着的新窗口打开(:stag tagname)
n Ctrl+t 出栈(后跳n次,会使你的:tags列出的表缩短) ── 跨文件时,用 Ctrl + o才能跳回去。

:tselect tagname 可以列出所有的相同的tagname,你按数字可以跳到对应条目。
:tnext 跳到下一个相同tagname处
:tprevious 同理
:tfirst    同理
:tlast     同理

匹配用/ /来括起来,让vim知道里面的是正则式
如 :tselect /^write_ 可以匹配以 write 开头的

:set ignorecase 可以在任何时候忽略大小写,比如在:tag tagname时。如果设置了这个,又想case有效,则在表达式后加\C
但如果想某次有效,则在表达式后面加\c
上面的表达式都用//包起来。


4. cscope看vim配置文件和以前的文档即可。

5. 使用Path:
有时,我们要定义额外的Path,以访问某些文件。且方便gf(goto file,在normal模式下,按gf,会打开光标下的文件,它会在Path下去搜),find(不支持正则式的搜索,用法 :find netrw.vim)等命令。

path选项定义了一个目录列表,在使用gf,find,以及CTRL-W f等命令时,如果使用的是相对路径,那么就会在path选项定义的目录列表中查找相应的文件。path选项以逗号分隔各目录名。我们依旧以VIM 7.0的源代码为例(源代码放在~/src/vim70/目录中)。

对于这个项目,我们的path选项设置如下:
set path=.,/usr/include,,~/src/vim70/**

稍微解释一下各项的含义,更详细的信息,请查看path选项的帮助页:
.                在当前文件所在目录中搜索
/usr/include     在/usr/include目录中搜索
,,               在当前工作路径中搜索
~/src/vim70/**   在~/src/vim70的所有子目录树中进行搜索!!

6. 多文件浏览采用 MiniBufExplorer:
因为使用了WinManager和Taglist,所以tabe显得不好用了,用buffer会更方便。
但是vim自带的buffer管理工具只有:ls, :bnext, :bdelete 等的命令,这里用MiniBufExplorer.好处是在顶上可视化列出了各个buffer。仍然用:bnext等命令。
然后,在vim中设置了,用shift+Tab来切换buffer,挺方便。
关闭一个buffer,而不退出窗口,在标签上按d,这是MiniBufExplorer的命令。个

7. Taglist
提醒用 s 来切换按名字排序(大写,再小写,每个里面按首字母)还是出现次序排序
用 u 来更新list(默认可以再次调用ctags)
另外,在vimrc中设置了单击来打开对应位置

8. WinManager
s来切换按xx排序,r做反排序
另外,在各个窗口间切换,用 Ctrl+方向键 更快~~~

9. vimgrep查找文本 或 Grep插件查找文本:
ctags找到了--list-kinds中指示的东西,你可以用:tag tagname找出这些tags,cscope也找了它可以找的东西,可以用:cs find g/d/c/t/e tagname找到相应的东西,其中t表示找那个文本,尤其是e表示用egrep查找。单都是在cscope的数据库中查找。
但是,很多时候,仍需要对文件本身搜索,或者想到某个特定子目录搜索,并支持正则式。
(1) 可以用 :vimgrep命令:
:vimgrep是vim内置的grep,如果你用:grep等,则是让vim调用外部的系统的grep。用:vimgrep的好处是,不依赖于系统的,使得各个系统上都可以用。但是会慢点,因为它会把每个文件,放入buffer,再分析。
用法简单:
:vimgrep /pattern/ path
其中 pattern为正则式,如 \表示main单词
path 为shell元字符式,如 ./SSF/**/*.java 表示搜索SSF目录下,所有子目录,及所有嵌套子目录的 java文件。
(2) 也可以用Grep插件,下面命令都支持正则式:
:Grep 在指定的文件查找
:Rgrep 递归查找
:Bgrep 在打开的缓冲区中查找
他会问你更多信息,比如哪些文件中查找,在哪个目录中查找,很方便。
如:
Search for pattern: 时可以填 \ (匹配单词,而不是字符串)
Search in files: 时可以填 *.java

10. 高亮文本:
:colorscheme 可以选择某个主题。
在.vim里,自己创建colors doc plugin syntax 四个目录,doc和plugin用户放plugin的文件和doc文件,syntax用于放置指导语法加亮的文件,而colors就用于放置高亮主题。目前我用的是desert主题。

11. 目前用到的插件:
a.vim             
color_sample_pack.vim
minibufexpl.vim    
taglist.vim         
winmanager.vim (winfileexplorer.vim wintagexplorer.vim)
code_complete.vim   #这个好好看看它的代码体吧,很简单,却很高效的用tab补全很多东西,如调用函数时,在(后按tab,就可补出各个参数的类型。比如很方便自动生成main,for,while,#define等。
grep.vim              
NERD_commenter.vim


12. 颜色相关:
首先,在vim中输入 :runtime syntax/colortest.vim 可打印出目前你可以使用的颜色。只有那么几种。包括粗体。所以,这就是终端里使用vim没有gvim颜色多,或者没有gvim颜色正常的原因。但是,你好好调整一下,还是能够满足自己要求的。
另外,各种颜色主题,是不能让,如函数,单独高亮的,因为这需要语法帮助。这需要你单独找语法文件,就是什么东西是函数,并应该高亮为什么颜色。把语法文件放到 ~/.vim/syntax中。
我是从官网下了cpp.vim放到~/.vim/syntax目录中,于是.cpp文件可以有更多的高亮了。
但是,c.vim是我从别的地方找的,官网上找的c.vim不起作用,我又不好改。目前用的c.vim如下,主要加亮了函数名和C关键字。而cpp.vim是使用c.vim的,所以默认也就让cpp.vim支持同样的效果了。

要读懂和改这个简单文件,需要知识如下:
:hi 命令时一直都是以图形介面(gui)为例设置前景和背景色。由于命令终端对颜色显示的限制,Vim在命令行下可以使用的颜色相对gui 要少得多,所以使用:hi命令时图形介面和命令行介面的颜色是分开设置的。对于黑白终端来说就无所谓颜色了,而彩色终端用cterm来表示,前景色就是 “ctermfg”,而背景色是“ctermbg”。下面是一个表格:

终端类型 前景色      背景色      注释
term           -              -              黑白终端
cterm     ctermfg    ctermgb       彩色终端
gui          guifg        guibg          图形介面


下面是这个文件 c.vim
"========================================================
" Highlight All Function
"========================================================
syn match   cFunction "\<[a-zA-Z_][a-zA-Z_0-9]*\>[^()]*)("me=e-2
syn match   cFunction "\<[a-zA-Z_][a-zA-Z_0-9]*\>\s*("me=e-1
hi cFunction        gui=NONE guifg=#B5A1FF

"========================================================
" Highlight All Math Operator
"========================================================
" C math operators
syn match       cMathOperator     display "[-+\*/%=]"
" C pointer operators
syn match       cPointerOperator display "->\|\."
" C logical   operators - boolean results
syn match       cLogicalOperator display "[!<>]=\="
syn match       cLogicalOperator display "=="
" C bit operators
syn match       cBinaryOperator   display "\(&\||\|\^\|<<\|>>\)=\="
syn match       cBinaryOperator   display "\~"
syn match       cBinaryOperatorError display "\~="
" More C logical operators - highlight in preference to binary
syn match       cLogicalOperator display "&&\|||"
syn match       cLogicalOperatorError display "\(&&\|||\)="

" Math Operator
hi cMathOperator            guifg=#3EFFE2 ctermfg=lightyellow  
hi cPointerOperator         guifg=#3EFFE2 ctermfg=lightyellow
hi cLogicalOperator         guifg=#3EFFE2 ctermfg=lightyellow
hi cBinaryOperator          guifg=#3EFFE2 ctermfg=lightyellow
hi cBinaryOperatorError     guifg=#3EFFE2 ctermfg=lightyellow
hi cLogicalOperator         guifg=#3EFFE2 ctermfg=lightyellow
hi cLogicalOperatorError    guifg=#3EFFE2 ctermfg=lightyellow



" ------------------------ further work ------------------------
" hi cType ctermfg=green
hi cConditional ctermfg=lightred
hi cRepeat ctermfg=lightred
hi cStatement ctermfg=lightred
hi cLabel ctermfg=lightred
"hi cType ctermfg=green
hi cDefine ctermfg=magenta
hi cUndefine ctermfg=magenta
hi cFunction ctermfg=blue

" ----------------------- 以下的是备查而已 ------------------------
" hi other words later
" C language keywords.
" For compilers with asm keyword - error if not c_c_vim_compatible.
syn keyword       cKRStatement      asm
syn keyword     cGNUStatement     __asm__
syn keyword       cLabel            case default
syn keyword       cConditional      if else switch
syn keyword       cRepeat           while for do

" C data types
syn keyword       c89Type           int long short char void signed unsigned float double
" These are actually macros that expand to the above.
syn keyword     c99Type           bool complex imaginary
syn keyword     cGnuType          __label__ __complex__ __volatile__

" C language structures
syn keyword       cStructureType    typedef
syn keyword       cStructure        struct union enum

" C storage modifiers
syn keyword       c89StorageClass   static register auto volatile extern const
syn keyword       cKRStorageClass   fortran
syn keyword     c99StorageClass   restrict inline
syn keyword     cGNUStorageClass __attribute__


13. 支持tags更新:
见下面绑定在F7上的功能,就是把ctags和cscope重新更新。
这个的好处显然的,比如你想对新改的代码使用code_complete.vim插件中的功能。

14. c++补全:
omnicppcomplete 插件很好用。这个放在~/.vim里后,注意下面.vimrc文件中对它的几行设置,否则不太好似。

15. C-x C-o:
C++ 自动补全OK了,但是C的函数怎么补全呢?? 在ctags存在的情况下,用C-x C-o吧,我棒定到F8上去了,见vimrc.   它比 C-p强的地方是,它会把函数的函数原型也列出来,方便输入,其他的找到的,也会标出类型。


强烈建议程序员完整的阅读usr_29.txt和usr_30.txt

---------------------- 下面是 2009 03 29 日vimrc文件内容:----------------------
" An example for a vimrc file.
"
" Maintainer:    Bram Moolenaar
" Last change:    2006 Nov 16
"
" To use it, copy it to
"     for Unix and OS/2: ~/.vimrc
"          for Amiga: s:.vimrc
" for MS-DOS and Win32: $VIM\_vimrc
"        for OpenVMS: sys$login:.vimrc

" When started as "evim", evim.vim will already have done these settings.
if v:progname =~? "evim"
finish
endif

" Use Vim settings, rather then Vi settings (much better!).
" This must be first, because it changes other options as a side effect.
set nocompatible

" allow backspacing over everything in insert mode
set backspace=indent,eol,start

if has("vms")
set nobackup        " do not keep a backup file, use versions instead
else
set backup        " keep a backup file
endif
set history=50        " keep 50 lines of command line history
set ruler        " show the cursor position all the time
set showcmd        " display incomplete commands
set incsearch        " do incremental searching

" For Win32 GUI: remove 't' flag from 'guioptions': no tearoff menu entries
" let &guioptions = substitute(&guioptions, "t", "", "g")

" Don't use Ex mode, use Q for formatting
map Q gq

" In many terminal emulators the mouse works just fine, thus enable it.
set mouse=a

" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
syntax on
set hlsearch
endif

" Only do this part when compiled with support for autocommands.
if has("autocmd")

" Enable file type detection.
" Use the default filetype settings, so that mail gets 'tw' set to 72,
" 'cindent' is on in C files, etc.
" Also load indent files, to automatically do language-dependent indenting.
filetype plugin indent on

" Put these in an autocmd group, so that we can delete them easily.
augroup vimrcEx
au!

" For all text files set 'textwidth' to 78 characters.
autocmd FileType text setlocal textwidth=78

" When editing a file, always jump to the last known cursor position.
" Don't do it when the position is invalid or when inside an event handler
" (happens when dropping a file on gvim).
autocmd BufReadPost *
    \ if line("'\"") > 0 && line("'\"") <= line("$") |
    \   exe "normal! g`\"" |
    \ endif

augroup END

else

set autoindent        " always set autoindenting on

endif " has("autocmd")

" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
         \ | wincmd p | diffthis

" ///////////////////////////////////////////////////////////////

" common options

if has("win32")
set encoding=utf-8
set termencoding=utf-8
set fileencoding=chinese
set fileencodings=ucs-bom,utf-8,chinese
set langmenu=zh_CN.utf-8
source $VIMRUNTIME/delmenu.vim
source $VIMRUNTIME/menu.vim
language messages zh_cn.utf-8
language messages zh_cn.utf-8

set guifont=Courier_New:h12:cANSI    " 指定windows下的英文字体和大小
set guifontwide=NSimSun:h11              " 指定windows下的中文字体和大小
else
set fileencodings=utf8,gbk,big5
endif

set tabstop=4
set shiftwidth=4
set mouse=a
set backupdir=~/tmp/vim/
set scroll=10
set autoindent
set smartindent
set cindent
syntax enable
syntax on
set fdm=indent
set foldlevel=100
set number

:map :tabprevious
:map :tabnext
:imap :tabprevious
:imap :tabnext


" taglist and winmanager integration
let Tlist_Use_SingleClick=1
let Tlist_Show_One_File=1
let Tlist_Exit_OnlyWindow=1
let g:winManagerWindowLayout='FileExplorer|TagList'
map wm :WMToggle

" MiniBufferExplorer
let g:miniBufExplMapWindowNavVim = 1
let g:miniBufExplMapWindowNavArrows = 1
let g:miniBufExplMapCTabSwitchBufs = 1
let g:miniBufExplModSelTarget = 1
let g:miniBufExplUseSingleClick = 1
"map :bn
"map :bp

" cscope options
set cscopequickfix=s-,c-,d-,i-,t-,e-,g-
if has("cscope")
    set csprg=/usr/bin/cscope
    "use both cscope and ctag for 'ctrl-]', ':ta', and 'vim -t'
    set cscopetag
    set csto=0
    set cst
    set nocsverb
    " add any database in current directory
    if filereadable("cscope.out")
        cs add cscope.out
    " else add database pointed to by environment
    elseif $CSCOPE_DB != ""
        cs add $CSCOPE_DB
    endif
    set csverb
endif

map s :cs find s =expand("") :cw
map g :cs find g =expand("") :cw
map c :cs find c =expand("") :cw
map t :cs find t =expand("") :cw
map e :cs find e =expand("") :cw
map f :cs find f =expand("") :cw
map i :cs find i ^=expand("")$ :cw
map d :cs find d =expand("") :cw

" ctags options
set tags=./tags
" au BufWritePost *.c,*.cpp,*.cc,*.h !cscope_ctags_cppfiles
" reproduce ctags and cscope.out and reset cscope to vim.(ctags is automatically reseted)
map :!ctags --extra=+q --fields=+Saim --java-kinds=+l --c++-kinds=+lpx --c-kinds=+lpx -R . :!find . -name "*.h" -o -name "*.c" -o -name "*.cc" -o -name "*.cpp"> cscope.files :!cscope -bkq -i cscope.files :cs reset


" c/cpp complete
imap
set completeopt=longest,menuone
let OmniCpp_DefaultNamespaces = ["std"]
let OmniCpp_NamespaceSearch = 1
let OmniCpp_MayCompleteDot = 1
let OmniCpp_MayCompleteArrow = 1
let OmniCpp_MayCompleteScope = 1
let OmniCpp_ShowScopeInAbbr = 1
let OmniCpp_ShowPrototypeInAbbr = 1

" color scheme
colorscheme desert

" other options
map :cp
map :cn
imap :cp
imap :cn

map :make :copen
map :!./a.out

map :A
imap :A

map :bp
map :bn

map :Rgrep
imap :Rgrep












---------------------------------------------------------------------------------------------
(旧)六、VIM配套工具集:
(一)用 cscope 查看源代码
生成索引,记住Rbkq就行
cscope -Rbkq
-R: 在生成索引文件时,搜索子目录树中的
代码
-b: 只生成索引文件,不进入 cscope 的界面
-k: 在生成索引文件时,不搜索 /usr/includ
e 目录
-q: 生成 cscope.in.out 和 cscope.po.out 文
件,加快 cscope 的索引速度


● cscope在Vim中的基本用法是 :cs + 子命令
:cs find {querytype} {name}
● find 的子命令
s: Find this C symbol # 记法 s - symbol,查找的是symbol,不是一般的text
g: Find this definition   # g就记住是definition
d: Find functions called by this function   # d 是 called 后那个d
c: Find functions calling this functio     # c 是 called 前那个c
t: Find this text string                   # t 是 text 的意思,就是 一般的 text 查找
e: Find this egrep pattern                 # e 正则式了
f: Find this file                          # f 是 file 的意思
i: Find files #including this file         # i 是 include 的意思,即查找 包含此头文件的文件

当然,你可能会find很多,cs find 如果找到一个,则默认定位到那个去,如果找到多个,则会列出来,可能在本窗口列出(如果不设置在QuickFix窗口列出,默认就是这个样子,可以看看),也可能在QuickFix窗口列出,那一般是设置在QuickFix这个单独的窗口列出,见下边.vimrc设置的这一行::set cscopequickfix=s-,c-,d-,i-,t-,e-,g- ,但默认是不打开QuickFix窗口的,所以要你自己用:cw或:copen打开后就看到结果了(关闭QuickFix可以用:cclose)。见下面的快捷键设置,我默认是打开的,最后我加了一个:cw.
不管在哪里列出,需要遍历列出的项,则用鼠标一个一个点击,或者用命令如下:
:cw (或:copen)对make,cscope等,在最后一行提示你有多个选择时,你可以用:cw来打开QuickFix窗口,用:cn定位到下一个,用:cp定位到上一个,也可以在QuickFix窗口中用上下或鼠标点击操作。当然,我为了方便,用快捷键设置了,见下面。设置到F7和F8上面了。


其他cs 的子命令:
在最后一行敲:cs你可以得到:所有的用法,一目了然,便于查找。简单说明如下:
上面的:cs 中的find子命令只是其中一个,其他的有如add常用于添加另一个cscope.out数据库文件,这样你可以用很多个,就是写上路径。
show用于显示现有的cscope连接,即你用add加成功的cscope.out数目。
reset很有用,当你改完代码后,需要重新生成cscope.out等文件 (重新生成cscope.out文件,可以用:!外部命令,这里应该是 :!cscope -Rbkq), 这时为让vim中的cscope数据库刷新,需要:cs reset一下。
:h if_cscop.txt查看完整文档

最后,为方便使用,常为cscope的命令做map,和vim相关的.vimrc的部分如下,完整的.vimrc查看另一篇博客。

.vimrc中要写的和cscope相关的:

"这表示cs的这些子命令都使用quickfix窗口,-表示是更新quickfix窗口,而不是追加。如果写成 +,如s+就表示是对quickfix窗口追加。如果没出现在这里的命令,默认直接在当前窗口下直接列出找到的所有项。
:set cscopequickfix=s-,c-,d-,i-,t-,e-,g-

"下面的来自 :h if_cscop.txt中的建议,不必太注意细节,只是看到里面已经把当前目录下的cscope.out加进去了。
if has("cscope")
    set csprg=/usr/local/bin/cscope
    set cscopetag
    set csto=0
    set cst
    set nocsverb
    " add any database in current directory
    if filereadable("cscope.out")
        cs add cscope.out
    " else add database pointed to by environment
    elseif $CSCOPE_DB != ""
        cs add $CSCOPE_DB
    endif
    set csverb
endif

"做键的映射,让cscope更方便。其中 =expand("") 是为了让如 :cs find s 后添上当前光标处的word,你可以自己敲这个试试.
nmap s :cs find s =expand("") :cw
nmap g :cs find g =expand("") :cw
nmap c :cs find c =expand("") :cw
nmap t :cs find t =expand("") :cw
nmap e :cs find e =expand("") :cw
nmap f :cs find f =expand("") :cw
nmap i :cs find i ^=expand("")$ :cw
nmap d :cs find d =expand("") :cw

"做键的映射,能够用F7和F8来切换QuickFix窗口中的项
map :cp
map :cn
imap :cp
imap :cn
" 这是为插入模式设置map, imap :cni 表明切换后仍为插入模式,但是我不太喜欢,有时会引起误操作,所以一般不要后面那个i。



最后,这样设置了配置文件后,就会有一些简单的用法可以用了:
ctrl-t 是本文件内的跳转到上次光标位置
ctrl-o 是跨文件的跳转(比如你上次打开一个文件,又关闭了,再打开一个新的,如果一直按这个,就会打开上次那个文件)
:ts tagname 查找所有的tagname符合的,列出,供你选择,再跳转
ctrl-] 在tagname上, 等于 :cs find g xxx



(二) 用ctags 查看源代码:
       由于ctags只是生成tags文件,不包含怎么在vim中找到某种特定的tag的命令,比如函数原型怎么找,定义怎么找等,它就是一个tags生成程序而以。而VIM本身只提供纯粹针对tags的查找(如列出所有相关tags,调到第一个符合的tags...),即不识别类,函数之类的,所以VIM+ctags不能实现复杂查找。除非有其他插件支持。且对c++支持不好,比如从类成员的使用跳到c++类成员的定义处就不行,而只能用ts列出匹配项,让你自己选,而cscope可以。
       所以最好用cscope,它本身就在最后一行模式支持多种语言中特定tag类型(如类,函数)的查找,且可以map成快捷键。

下面为用法:
1. ctags & tags:
tags是ctags生成的文件,典型形式如下:
!_TAG_FILE_FORMAT       2       /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED       1       /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR    Darren Hiebert /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME      Exuberant Ctags //
!_TAG_PROGRAM_URL       http://ctags.sourceforge.net    /official site/
!_TAG_PROGRAM_VERSION   5.6     //
A       main.cpp        /^class A{$/;" c       file:
A::i    main.cpp        /^      int i;$/;"      m       class:A file:   access:private
A::ok   main.cpp        /^      ok() {$/;"      f       class:A file:   access:private signature:()
a       main.cpp        /^      unsigned char a = 0x01 | 0x08;$/;"      l
i       main.cpp        /^      int i;$/;"      m       class:A file:   access:private
main    main.cpp        /^int main() {$/;"      f       signature:()
ok      main.cpp        /^      ok() {$/;"      f       class:A file:   access:private signature:()

很容易看懂意思吧,每一行就是一个tag,后面跟出许多fields。从形式上就这米简单。
而cscope的不是这种tags形式,不太明白,没看。

2.重要信息:
ctags --list-kinds 打印出对每种语言支持识别的tags,比如C++支持类名,函数定义,函数原型...
ctags --list-languages 列出支持的语言

3.主要用法:
由于vim大约在7.0以后,支持了对你包含了的头文件中的tag的下拉菜单补全,比如你包含了一个系统头文件或你自己的文件,写出一部分再按Ctrl-P,就可以有下拉的菜单。当然,跳转等复杂特性是不支持的。即便如此,也不大需要对系统路径下的文件进行ctags扫描了,下面所述,均针对你的程序文件:
(1)简单用法:
ctags -R 在源代码顶层目录下执行,默认配置适合大多数情况.(-R = --recurse)
(2)复杂用法:
逻辑上这样的:ctags自动根据文件后缀判断是什么语言的文件,并采取相应的分析方法,所以,原则上将ctags -R对任何程序文件都适用。
但是ctags到底处理语言中的哪些tags,然后tags文件中到底包含哪些fields,这个是需要详细指定的,因为一些你想要的,默认没有设置,比如函数原型在c/c++中都默认没有去查找,所以要用--c++-kinds=+p 添加上函数原型。下面 --c++-kinds=+lpx 和 --c-kinds=+lpx 只指定要加上lpx就行了,是因为你用 ctags --list-kinds,你会发现,它写有哪些tags是默认支持的,而我发现,就lpx没有被默认支持,所以我添加这三个。 而--fields=+Saim 是往tags文件中指定哪些field,这个见man里有默认显示的field,这里是加上一些默认不显示的重要的,记住是Saim就行了!至于 --extra=+q 是为C++等增强特性:对是class的成员的tag,一律加上class名前缀,即classname::tag。
所以,这样写,如果你想支持最多的话:
ctags --extra=+q --fields=+Saim --c++-kinds=+lpx --c-kinds=+lpx -R Main.cpp
记法:3部分: q Saim 和 lpx
我把这一堆(不包括-R)做了个alias为cpptags

(三) 为什么cscope比ctags强大 ─── 因为ctags仅仅用于生成tags文件。
Cscope 是一个交互式的屏幕下使用的工具,用来帮助你:
* 无须在厚厚的程序清单中翻来翻去就可以认识一个 C 程序的工作原理。
* 无须熟悉整个程序就可以知道清楚程序 bug 所要修改的代码位置。
* 检查提议的改动 (如添加一个枚举值) 可能会产生的效果。
* 验证所有的源文件都已经作了需要的修改;例如给某一个现存的函数添加一个参数。
* 在所有相关的源文件中对一个全局变量改名。
* 在所有相关的位置将一个常数改为一个预处理符号。

它被设计用来回答以下的问题:
* 什么地方用到了这个符号?
* 这是在什么地方定义的?
* 这个变量在哪里被赋值?
* 这个全局符号的定义在哪里?
* 这个函数在源文件中的哪个地方?
* 哪些函数调用了这个函数?
* 这个函数调用了哪些函数?
* 信息 "out of space" 从哪来?
* 这个源文件在整个目录结构中处于什么位置?
* 哪些文件包含这个头文件?