vim 打造属于自己的 IDE

一.ctags 安装和配置

首先要说的是ctags是一个linux上很普遍的源码分析工具, 可以将代码中的函数变量等定义的位置记录在一个名称为tags的文件. 类似于数据库记录功能. tags文件的产出最简单的方法是在需要生成tags的工程项目的根目录下执行ctags -R命令, 这会调用tags递归的扫描当前目录以及所有子目录中可以被tags识别的文件所以文件数据信息都会汇集到tags文件中.这里总结一下几个本人暂时知道的几个需要注意的地方:

  ->ubuntu在默认系统环境中已经集成了ctags功能, 但这个ctags并不是完整的版本, 为了保证vim可正常的使用tags建议安装完整的ctags支持, ubuntu完整的ctags被重名为exuberant-ctags但依然可以通过ctags索引到, 安装命令如下:

  sudo apt-get install ctags

  ->如果你的vim有使用echofunc插件来显示函数的参数定义, 那么在使用ctags生产索引文件时需要使用如下附加参数:

  ctags -R --fields=+lS

  ->ctags默认生成的索引文件只包含了对C语言的语法分析, 如果你需要ctags支持对C++语法分析. 需要使用下面的命令:

  ctags -R --c++-kinds=+p --fields=+iaS --extra=+q

       ->如果同时支持上面两个使用场景,需要使用下面的命令:

       ctags -R --c++-kinds=+p --fields=+liaS --extra=+q

  ->如果你在C语言编写的代码中使用上面提到的C++命令生成tags, 那么你将惊讶的发现, 当你希望通过ctags跳转到光标下函数定义的地方的时候, vim总是跳转到这个函数定义的地方, 原因是ctags的C++命令增加了额外的语法分析以便支持C++更加复杂的语法结构, 这种额外的语法分析用在C语言中的时候就会出现跳转默认定位到函数声明的地方.

  ->ctags默认是支持C和C++的由于本人暂时没有做过其他语言的开发工作, 所以不清楚ctags是否支持其他编程语言.

  ->请不要每次生成tags的时候都使用上面的命令, 包括以后其他的很多功能的实现都是如此, 命令是实现一个功能的原型, 如果仅仅使用命令在类unix(windows下面也是如此)的操作系统上实现常用的操作和功能, 那么你的操作将会变得很低效. 个人认为vim的使用也有这个规律, 最普遍的操作最好不要使用长长的命令来实现. 取而代之的方法是设置快捷键和命令的简写映射.

二. ctags 在 vim中的使用

  vim配置tags使用的过程是, 先在终端中生成一个项目的tags文件, 再在vimrc中告诉vim哪里去找这个tags. 假如我们有一个项目在/home/boddy/hello/下面, 并且这个目录下已经生成tags文件.那么只要在vimrc文件中添加如下语句就可以让vim在每次启动的时候自动找到这tags了:

 set tags+=/home/boddy/holle/tags

 如果你有多个tags需要使用,可以重复上面的语句, 也可以在同一个语句中加入多个路径,每个路径用","隔开.

这种方法是我最初使用tags的的方式, 缺点显而易见, 每当我们开始新的项目的时候,不得不重新修改set tags后面的路径, 虽然这样的修改并不麻烦, 也不需要经常操作. 但不免还是让人觉得太死板不智能.

  为了让vim对tags的支持更加自动话, 首先想到的方法是在vimrc中添加 settags+=./tags语句, 这样当前目录下的tags就不需要我们手动添加了.但我们不可能永远在项目的根目录操作. 如果在项目的子目录里操作, 这个方法将会失效. 事实上, 任何一个项目文件夹都有一个显著的特点: 任何子目录递归向上都可以到达项目的根目录. 这个特点将会在下面的实践中大显身手, 让我们从各种和项目整体相关的操作中解脱出来. 这包括ctags cscope lookupfile等相关索引文件的自动添加和随时更新. 在项目任意子目录下的任意时刻对项目的自动make和make clean等. 这些最频繁操作要么是自动完成的要么是通过vimrc的map功能映射到不同的快捷键上, 这会让我们的vim具有所以IDE所具有的便捷性的同时保持了vim在编码方面无比的高校性和在功能定制方便的无比的可定制性. 我想这就是我为什么宁愿选择折腾vim而没有使用成熟的IDE的原因.

  上面提到工程项目的目录递归特性, 实际上, 我们需要使用一个tags最典型的需求是希望在一个项目中快速的找到函数,变量,宏等定义的地方. 这些查找大多是在项目文件夹内完成. 因此, 只要我们能上vim实现对当前所在目录的递归查找功能, 这个需求就会满足. 只要项目的根目录下存在tags文件, 任何时候任在任何一个项目的子目录下使用vim都可以正确的找到这个tags, 同时如果我们的电脑中存在多个项目, 当我们切换到另一个项目的子目录的时候, vim递归查找到永远是当前项目根目录下面的tags(前提是tags存在于项目根目录), 无意间就实现tags的自动切换功能. 

  实现vim对tags的自动递归查找其实很简单, 因为vim已经实现了这个功能, 只是默认没有开启. 在vimrc添加下面两行配置, 就会是见证奇迹的时刻:

  set autochdir
  set tags=tags;

  set autochdir表示自动切换目录的意思, set tags=tags;表示自动查找, 这两句同时设置vim即可实现递归的tags查找, 注意: set tags=tags;这一句的最后有一个分号, 这个分号是不能省略的. vim的配置文件使用的是vim自己的脚步语言. 这里是少数几个在行尾需要使用分号的地方之一.

  最后需要说明的一点: ctags在默认的命令下生成的tags中使用的是相对路径的存放所有查找结果, 这在多数情况下是一个优点, 因为相对路径不依赖于项目的根目录所在位置. 这样在整个项目转移到别的位置的时候, 相对路径的tags依然可以正常的实现跳转. 不过相对路径的tags并不是没有缺点, 如果你的vim中使用了FuzzyFinder来作为查找项目文件的工具, 你将惊讶的发现如果你在项目根目录的子目录下执行项目文件查找,在找到了想要的文件并最后回车跳转的时候如果tags使用的是相对路径, 这一步将会失败, 因为FuzzyFinder无法正确的通过当前的目录(不是项目根目录)加上tags中的相对路径计算出正确的文件位置. 解决的办法是在ctags生产tags文件的时候使用绝对路径, 使用方法是在ctags -R 的命令后面添加项目根目录的绝对路径, 如: ctags -R /home/boddy/hello/ , 使用绝对路径可以保证tags在任何调用他的工具中正确的找到文件位置. 唯一的缺点是如果项目移动了, tags必需重新生成, 鉴于我们的项目在自己的电脑中移动的需求很小的同时重新生成一tags的时间也就是几秒钟的事情(只要不是超级大的项目,tagseh生成还是很快的), 我个人选择了在任何时候使用ctags都使用绝对路径, 当然这个功能是在vim中通过参数自动实现的, 本文的最后将会提到.

三. cscope的安装和配置

        sudo apt-get install cscope

使用ctags生成tags类似,通过下述命令可以生成cscope.out[2]:

    在当前目录中生成cscope.out:

[plain] view plain copy
  1. cscope -Rb  

(2) 添加额外的目录

指定源码绝对路径,查找时不受当前工作路径的限制:

[plain] view plain copy
  1. cscope -Rb -s absoluteDir  

    例如在进行Linux驱动开发的时候,将absoluteDir取为Linux源码所在的目录,然后在驱动项目目录执行上述命令(不是进入Linux源码中哦,而是自己在Linux源码之外所创建的目录)。此时,在进行驱动开发的时候,就可以利用cscope的查找功能了, 而不必将当前目录切换到Linux源码目录中。

(3)添加路径前缀

    通过第上述步骤(2)虽然可以达到搜索不受工作路径的影响,但是会有一个副作用:同一个文件会有两个重复的路径,一个相对路径,一个绝对路径。因此,在查找的过程中,会出现重复的结果。

    为了避免上述副作用,最好是使用下述命令代替上述第(2)步的命令,同样可以达同样的目的,并避免了副作用:

  1. cscope -Rbqkv -P pwd  

    -P,表示为搜索路径添加前缀, pwd是获取当前工作路径的命令。

3.2 添加目录/库文件

(1)手动方式    

打开vim之后,可以通过下述命名添加目录

[plain] view plain copy
  1. :cs add directory  
或者
[plain] view plain copy
  1. :cscope add directory  

(2)自动方式一    

也可以将下面语句添加到vim的配置文件.vimrc

[plain] view plain copy
  1. if filereadable("cscope.out")  
  2.     cs add cscope.out  
  3. elseif $CSCOPE_DB  != ""  
  4.     cs add $CSCOPE_DB  
  5. endif      

    这样子就会在打开vim的时候自动加载当前目录下车cscope.out文件。

(3)自动方式二

autoload_cscope.vim插件更方便,它会先在当前目录查找cscope.out,有则加载,否则进入其父目录查找,直到找到可用的cscope.out为止。

四、cscope 的使用

3.3 find命令

Cscope的功能通过它的子命令find来实现。

[plain] view plain copy
  1. :cs find c|d|e|g|f|i|s|t name  
    其中各个参数意义如下[5]:
[plain] view plain copy
  1. s -- symbol:find all references to the token under cursor  
  2. g -- global:find global definition(s) of the token under cursor  
  3. c -- calls:find all calls to the function name under cursor  
  4. t -- text:find all instances of the text under cursor  
  5. e -- egrep:egrep search for the word under cursor  
  6. f -- file:open the filename under cursor  
  7. i -- includes:find files that include the file name under cursor  
  8. d -- called:find functions that function under cursor calls  
3.4 快捷键映射

    为了便于查找,根据参考资料[4][5]的提示,可以在.vimrc中设置上述各命令的快捷映射:

[plain] view plain copy
  1. nmap <S-s> :cs find s <C-R>=expand("<cword>")<CR><CR>  
  2. nmap <C-g> :cs find g <C-R>=expand("<cword>")<CR><CR>  
  3. nmap <S-c> :cs find c <C-R>=expand("<cword>")<CR><CR>  
  4. nmap <S-t> :cs find t <C-R>=expand("<cword>")<CR><CR>  
  5. nmap <S-e> :cs find e <C-R>=expand("<cword>")<CR><CR>  
  6. nmap <S-f> :cs find f <C-R>=expand("<cword>")<CR><CR>  
  7. nmap <S-i> :cs find i ^<C-R>=expand("<cword>")<CR>$<CR>  
  8. nmap <S-d> :cs find d <C-R>=expand("<cword>")<CR><CR>  

    使用时,将光标停留在要查找的对象上,按下Ctrl + g,将会查找该对象的定义(这里使用Ctrl是为了避免和vim的原有快捷方式冲突);其它的快捷方式使用如Shift+ s/c/t/e/f/i/d。

五,在coding过程中,有了变量或函数的自动弹出功能,可以极大的提高编码的效率和准确率,这里介绍的AutoComplPop和OmniCppComplete脚本插件就是实现这样一个功能。

1. 代码(普通变量函数)的自动弹出 AutoComplPop

下载:http://www.vim.org/scripts/script.php?script_id=1879 

        安装:

               先解压:unzip vim-autocomplpop.zip

              同其他脚本插件的安装方法一致,将解压后的文件拷贝到~/.vim/ 下的相应目录里:

                     autoload/*    ->    ~/.vim/autoload/

                     doc/*    ->    ~/.vim/doc/

                     plugin/*    ->    ~/.vim/plugin/

       使用:

              重新打开vim即可使用。添加help文件:helptags ~/.vim/doc/即可(打开帮助文件:h(elp) autocomplpop)

       效果图:


2. c/c++代码(类的 . , ->, :: 操作符)的自动补全 OmniCppComplete

       下载:http://www.vim.org/scripts/script.php?script_id=1520

       安装:

              先解压:unzip omnicppcomplete-0.41.zip

              同其他脚本插件的安装方法一致,将解压后的文件拷贝到~/.vim/ 下的相应目录里:

                     autoload/*    ->    ~/.vim/autoload/

                     doc/*    ->    ~/.vim/doc/

                     after/*    ->    ~/.vim/after/

       使用:

              重新打开vim,添加help文件:helptags ~/.vim/doc/(打开帮助文件:h(elp) omnicppcomplete),但其功能的展现还需要一下操作和设置:

              omnicppcomplete脚本插件的基本设置,在~/.vimrc中添加(我的喜好设置):

                     set completeopt=menu,menuone  
                     let OmniCpp_MayCompleteDot=1    “  打开  . 操作符
                     let OmniCpp_MayCompleteArrow=1  "打开 -> 操作符
                     let OmniCpp_MayCompleteScope=1  ”打开 :: 操作符
                     let OmniCpp_NamespaceSearch=1   “打开命名空间
                     let OmniCpp_GlobalScopeSearch=1  
                     let OmniCpp_DefaultNamespace=["std"]  
                     let OmniCpp_ShowPrototypeInAbbr=1  “打开显示函数原型
                     let OmniCpp_SelectFirstItem = 2”自动弹出时自动跳至第一个

              要生成专用于c/c++的ctags文件,并引导vim找到改tags文件:

              tags文件生成命令(通常位于代码项目的最上层目录下执行)[admin@local]$ ctags -R --c++-kinds=+p --fields=+iaS --extra=+q

              引导omnicppcomplete找到tags文件:

                     (1)在vim中设置:set tags+=/home/project/project_1/tags 。该方法不方便,每次使用都要set一下

                     (2)在~/.vimrc中添加常用的路径tags:

                            set tags+=/home/project/project_1/tags

                            set tags+=/home/project/project_2/tags

              这样,每次打开vim便会自动寻找以上设置的tags文件。另外,可以通过vim中:set tags来查看已设置的tags文件路径。

       效果图:

 

六、在vim中加入echofunc这个可以自动提示函数原型的插件,最先版可以通过以下链接下载:

http://www.vim.org/scripts/script.php?script_id=1735

该插件主要是解决omnicppcomplete不能补全函数的问题,基本上也不用配置,主要是在.vimrc中定义两个快捷键来切换函数的不同定义。

安装: 把下载下来的 echofunc.vim 放到 $HOME/.vim/plugin 目录下。
帮助: 请看 echofunc.vim 的开头部分。

插件 echofunc 依赖于另一个插件 ctags 。创建 tags 文件时使用以下命令:

$ ctags -R --fields=+lS
[html] view plain copy
  1. let g:EchoFuncKeyNext='<S-n>'  
  2. let g:EchoFuncKeyPrev='<S-p>'  





猜你喜欢

转载自blog.csdn.net/cherisegege/article/details/80212722