路过,来宣传一下我自己的C语言补全插件

Vim、Emacs配置和使用
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

路过,来宣传一下我自己的C语言补全插件

#1

帖子 kevinlei » 2011-08-10 18:24

ctags_cache

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

http://bitbucket.org/abadcafe/ctags_cache/

特色:
1. 自动调用ctags生成当前所编辑文件、其所引用的头文件,以及头文件引用的头文件的tags,并把tags保存在内存里随时更新,所以再也无需维护任何tags文件。

2. 自动补全函数名,全局变量,局部变量,成员变量,以及匿名结构体和嵌套结构体的成员变量。例如如下结构:

代码: 全选

typedef struct
{
    int abc;
    int bbc;
    union
    {
        int cbc;
        int dbc;
    };

    union
    {
        int ebc;
        int fbc;
    } uuu;
} sss;

sss a;
当你按a.<c-x><c-o>的时候,会把abc, bbc, cbc, dbc, uuu都补出来,但ebc和fbc就不会显示。当你a.uuu.<c-x><c-o>的时候才会显示出来。

3. 所有操作都是异步的,由后台线程完成,所以人感觉不到延迟。

不足:
1. 插件用python3写成,需要编译带py3支持的vim。
2. 插件在补全C语言的时候非常完美,速度与准确性都很不错,但没有针对C++做任何工作。

可能会有人觉得,没有tags文件不是没法跳转了吗?

这里我要推荐一下gnu global和它的vim接口插件gtags.vim。这是个类似于cscope的工具,但是有两点优势:
1. 当你在/abc/bbc/下生成了数据库以后,你进入/abc/bbc/cbc/dbc目录coding,并想进行跳转,它会自动向上查找到数据库进行操作。
2. 你在/abc/bbc/下的任意一个子目录里更改了一个文件f,然后执行global -u,不管你的数据库有多大(比如说整个kernel),都能很快的把数据库里有关文件f的信息都更新了,但cscope的更新操作就很慢。所以,可以在.vimrc里加一句

代码: 全选

au BufWritePost *.[ch] silent !global -u &> /dev/null &
然后只要:w就能让数据库保持最新。

也就是说,如果你是一个纯C程序员,那么通过这两个工具,你就能得到准确性与速度都非常完美并且可以跟任何其他软件(比如说source insight)媲美的智能补全与符号跳转功能。
头像
月下叹逍遥
论坛版主
帖子: 33994
注册时间: 2010-10-07 14:23
系统: Archdows10
来自: 某系某星某洲某国某省某市
联系:

Re: 路过,来宣传一下我自己的C语言补全插件

#2

帖子 月下叹逍遥 » 2011-08-10 18:26

lz潜的久了…… :em04
浮生七十今三十,从此凄惶未可知
头像
jadeity
帖子: 689
注册时间: 2010-10-21 17:55

Re: 路过,来宣传一下我自己的C语言补全插件

#3

帖子 jadeity » 2011-08-10 19:08

月下叹逍遥 写了:lz潜的久了…… :em04
还能记着帐号真不容易 :em20
头像
lilydjwg
论坛版主
帖子: 4258
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 路过,来宣传一下我自己的C语言补全插件

#4

帖子 lilydjwg » 2011-08-10 19:58

You will need vim compiled with python3.
太好了,终于不用自己 port 了~~
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

Re: 路过,来宣传一下我自己的C语言补全插件

#5

帖子 kevinlei » 2011-08-10 21:15

lilydjwg 写了:
You will need vim compiled with python3.
太好了,终于不用自己 port 了~~
万幸啊,你的patch进hg了...不然不晓得有多麻烦呢.
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

Re: 路过,来宣传一下我自己的C语言补全插件

#6

帖子 kevinlei » 2011-08-10 21:20

jadeity 写了:
月下叹逍遥 写了:lz潜的久了…… :em04
还能记着帐号真不容易 :em20
我在linux坛子都用同一个帐号的
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 路过,来宣传一下我自己的C语言补全插件

#7

帖子 eexpress » 2011-08-10 22:26

自动调用ctags,不是可以rc写一行au就可以嘛。
估计你这,只能对C规划使用。
支持大家测试吧。
● 鸣学
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

Re: 路过,来宣传一下我自己的C语言补全插件

#8

帖子 kevinlei » 2011-08-11 0:28

eexpress 写了:自动调用ctags,不是可以rc写一行au就可以嘛。
估计你这,只能对C规划使用。
支持大家测试吧。
兄台试过用au自动更新100多M的tags文件么?

ctags生成的tags文件是个线性列表,要想更新其中属于特定文件的tags,除了线性遍历没有别的办法.

而实际上,ctags -a是把新文件的tags添加在老文件最后,然后调用sort -u.

这必然是一个很慢的过程. tags文件小还无所谓, 大了就郁闷了.

所以我写了这个插件,与clang complete一样是实时解析C文件而无须维护tags文件,准确性与clang complete一样,但速度更快.哪怕是编辑kernel目录里的任意文件(包含的头文件甚至能达到200个),也感觉不到延迟.这就是我写这个插件的目的.
头像
Strange
帖子: 1824
注册时间: 2006-05-19 9:54
来自: Shanghai

Re: 路过,来宣传一下我自己的C语言补全插件

#9

帖子 Strange » 2011-08-11 7:31

看起来很给力
ニンニク入れますか?
x60 with gentoo
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 路过,来宣传一下我自己的C语言补全插件

#10

帖子 eexpress » 2011-08-11 10:12

100多M。丫丫的。没搞这么大的过。难道是在看内核源码。

要到si的程度,我倒是觉得要脱离vim框架。
● 鸣学
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

Re: 路过,来宣传一下我自己的C语言补全插件

#11

帖子 kevinlei » 2011-08-11 13:21

eexpress 写了:100多M。丫丫的。没搞这么大的过。难道是在看内核源码。

要到si的程度,我倒是觉得要脱离vim框架。
还好吧,si最主要的长处就是自动补全、自动跳转和符号索引。自动跳转和符号索引的话,gnu global和cscope都很给力的。cscope就是增量更新索引的时候太慢了。。。global还是很不错的。
头像
lilydjwg
论坛版主
帖子: 4258
注册时间: 2009-04-11 23:46
系统: Arch Linux
联系:

Re: 路过,来宣传一下我自己的C语言补全插件

#12

帖子 lilydjwg » 2011-08-11 14:10

kevinlei 写了: 3. 所有操作都是异步的,由后台线程完成,所以人感觉不到延迟。
才注意到这点。能否介绍下你是怎样异步实现的呢?哪些操作进行了异步处理?在 Vim 中后台线程是不能操作 UI 的,那么后台线程的结果如何被取回 UI 线程中的呢?
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 路过,来宣传一下我自己的C语言补全插件

#13

帖子 eexpress » 2011-08-11 14:22

si的好处,其实是不同变量不同颜色(字体/阴影等)。实时显示,函数调用正向/反向的框图(这个可以用graphviz实现)。
其他方面,基本vim可以实现。

si的全局变量替换,老版本至少是有严重bug的。
● 鸣学
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

Re: 路过,来宣传一下我自己的C语言补全插件

#14

帖子 kevinlei » 2011-08-11 15:38

lilydjwg 写了:
kevinlei 写了: 3. 所有操作都是异步的,由后台线程完成,所以人感觉不到延迟。
才注意到这点。能否介绍下你是怎样异步实现的呢?哪些操作进行了异步处理?在 Vim 中后台线程是不能操作 UI 的,那么后台线程的结果如何被取回 UI 线程中的呢?
实际上,我并没有在后台线程中直接操作ui(其实也是可以的,比如传进一段vimL代码,然后用vim.eval()执行)。

我是在内存里缓存了所有打开的文件和他们所依赖的头文件的tags。

然后,针对这些tags,有update、find、remove 3个操作。其中,update和remove两个操作,都是异步的。

当打开文件、:w写入文件的时候,都会由后台线程执行update操作。关闭文件的时候,则是由后台线程执行remove操作。

根据我的统计,打开一个包含300个头文件的c文件(这已经有点夸张了,kernel里的文件通常只是包含150-200个左右)并把所有这些文件都用ctags解析出tags,通常耗时在5秒以下。

在这5秒钟里执行find,就会阻塞住。但实际上,从打开vim到找到要编辑的地方,并且按下i,差不多也会需要几秒钟。所以实际上人只是会觉得稍微滞了一下。而当缓存建立完成以后,每次:w,都只是更新所修改的那一个文件而已,哪怕这个文件巨大,比如说现实中的sqlite3.c有10万行,ctags重新生成也只要1-2秒,而人很少在2秒内多次:w。所以,除了头一次打开某个c文件查找一堆h文件的时候,别的时候都感觉不到延迟。

而现实中,当我们在编辑一个项目的时候,每个c文件通常会依赖相同的一批h文件,所以当你打开下一个c文件时,就会先在内存里查找。比方说,打开kernel里的romfs.c会新增187个h文件,而接下来打开他的同一个目录下的super.c,则只是新增了20个h文件。因为它与前者共用了很多h文件,这样就很快了。

后台线程的代码其实很简单,空闲时候都等在self._run_cond这个condition上,直到调用work方法传进去一个闭包,才会醒来执行这个闭包,执行完了继续等待。而update、remove等操作就由这个闭包体现。

代码: 全选

class CtagsCacheWorker(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.daemon = True
        self._run_cond = threading.Condition()
        self._run_func = None
        self.start()

    def work(self, func, wait_complete = 0):
        with self._run_cond:
            self._run_func = func
            self._run_cond.notify()
            if wait_complete:
                self._run_cond.wait_for(lambda: self._run_func == None)

    def run(self):
        with self._run_cond:
            while 1:
                self._run_cond.wait_for(lambda: self._run_func)
                self._run_func()
                self._run_func = None
                self._run_cond.notify()
上次由 kevinlei 在 2011-08-11 15:43,总共编辑 1 次。
kevinlei
帖子: 40
注册时间: 2007-01-13 14:45

Re: 路过,来宣传一下我自己的C语言补全插件

#15

帖子 kevinlei » 2011-08-11 15:41

eexpress 写了:si的好处,其实是不同变量不同颜色(字体/阴影等)。实时显示,函数调用正向/反向的框图(这个可以用graphviz实现)。
其他方面,基本vim可以实现。

si的全局变量替换,老版本至少是有严重bug的。
有了after/syntax/c.vim以后,vim的颜色也丰富了许多,不过不同变量还是没有区分开。不过个人感觉是够用了。我的si都把(不同字体/阴影)关了的,看着眼花。。。
回复