高亮C的所有变量和函数
作者: nowait@smth
1 前言
emacs的代码语法加亮实在是做的不好,和source insight无法相比, 可能是以前没有集成cedet,不好分析语法的原因吧.我就自己写了一个山寨品来用. 之所以说这个文章里要介绍的这个zjl-c-hl.el是山寨的,是由于最重要的变量和参数加亮的实现原理是山寨的:用semantic得到单个函数的变量和参数list(这个还不算山寨),然后用highlight.el对函数范围内的变量和参数进行匹配加亮(就是这个就比较山寨). 我估计正常应该是用font-lock-add-keywords的高级功能来加亮,从而比较深的整合进emacs本身中. 不过我一直没有去深入的研究, 这个code也是按需要逐渐添加的. 虽然比较山寨,不过挺好用的. 下面是简单的介绍,很短, 看完了解了,有需要的朋友就可以拿来用了.
3 install
到这儿下载zjl-c-hl.el(以后应该wiki上面会有)http://code.google.com/p/dea/source/browse/trunk/lisps/zjl-c-hl.el
这个包里面使用了emacswiki上的highlight.el,从这儿下载:http://www.emacswiki.org/emacs/highlight.el
(require ‘zjl-c-hl)
4 Feature
- 支持c文件, 如果是.cpp文件,内部实际是c,也可以:), 那种实际是cpp的,估计把zjl-c-hl-c++-mode-enable-flag为妥.
- 加亮对象包括:局部变量,函数引用, 操作符,数字. 加亮的结果是还剩下的黑白字(默认face)部分的则一定是全局变量,宏或错误的局部变量(比如输入错误).
- 加亮过的区域,不会再被加亮一次,除非函数内部被修改(参见下一条), 这样cpu资源消耗不大
- 函数内部被修改后,进行局部(实际上是整个函数的)重新加亮. 具体表现为,就是随着代码输入,延时1-3秒加亮.
-
颜色face可以customize,分为白背景和暗背景, 白背景的加亮face我尽量做成了source insight的默认颜色, 暗背景的我目前也是用的和白背景一样的face…, 我自己没怎么用过暗背景,觉得现在的也可以接受, 所以用户如果对暗背景的默认颜色不满意可以有两个选择
- 自己默默的改得符合自己喜好
- 改好了之后, 把custom.el发给我
5 缺陷
没有能够准确辨识出全局变量,宏,和函数调用导致:
- 函数名/全局变量如果书写错误,无法实时得知,只能等待编译时知晓.
- 全局变量没有加亮,不能够和宏定义区分, 不像source insight那样看的自然
6 可以customize的变量
我直接从代码里面copy过来了,将就着看
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | (defcustom zjl-c-hl-c-mode-enable-flag t "*Enable c mode highlight when zjl-c-hl-disable-global-all is called" 'zjl-c-hl) (defcustom zjl-c-hl-c++-mode-enable-flag t "*Enable c++ mode highlight when zjl-c-hl-disable-global-all is called. Currently only c style file but named as *.cpp is supported" :type 'boolean :group 'zjl-c-hl) (defcustom zjl-c-hl-normal-size 40000 "*The size of erea that zjl-c-hl can highlight without any delay. You can improve this if your computer has enough performance." :type 'integer :group 'zjl-c-hl) (defcustom zjl-c-hl-toobig-size 10000000 "*The threshold size of function that zjl-c-hl will stop to highlight since it is too big. " :type 'integer :group 'zjl-c-hl) (defcustom zjl-c-hl-toobig-not-update-size 1000000 "*The size of function that zjl-chl will stop to highlight when the function is modified." :type 'integer :group 'zjl-c-hl) (defcustom zjl-c-hl-numberofscreen-to-hl-each-time 2 "*The number of screens around current screen to highlight every time." :type 'integer :group 'zjl-c-hl) (defcustom zjl-c-hl-firstscreen-hl-toggle nil "*When not nil and when you open a new buffer, hl buffer before it shown on window." :type 'boolean :group 'zjl-c-hl) |
7 程序的骨干的说明-—给不满意效果想要自行修改代码的同志看的
入口函数是zjl-c-hl-enable-global-all, 这个函数根据c-mode/c++-mode分别调用zjl-c-hl-enable-global, zjl-c-hl-enable-global里面定义是
7.1 font-lock-add-keywords
7.2 (add-hook hook ‘zjl-c-hl-init)
加亮变量和参数,具体是挂载在window-scroll-functions这个hook来实现. 使用这个hook原因有两个
- 避免semantic的后台自动load文件分析时也运行zjl-c-hl-init, 所以我们就需要有机制判断只有拥有window的buffer才会被执行zjl-c-hl.
- 每会用户scroll窗口的时候,也需要刷新新的位置的函数内部的加亮.
所以window-scroll-functions是很好的选择
- (add-hook ‘window-scroll-functions ‘zjl-c-hl-window-scroll-hook t t)
- 如果是第一次运行这个hook则
(add-hook ’semantic-after-partial-cache-change-hook ‘zjl-c-hl-semantic-after-partial-cache-change-hook t t)zjl-c-hl-semantic-after-partial-cache-change-hook(tags)的内容是
- semantic会把局部被更新的tags放在这个函数的调用参数里面, 里面包含了需要它重新分析过(由于buffer被修改导致的)的区域, 把这个区域标志为未加亮区域(具体是一个这样的list ((4 . 50) (100 . 300) (401 . 555)))
- 调用zjl-c-hl-window-scroll-hook,实时刷新一下当前窗口内容
- (run-with-idle-timer 0.5 nil ‘zjl-c-hl-timer-do-every-time (current-buffer))
每次窗口移动后,用户idle时,加亮当前窗口内的变量和参数,具体是- 设定范围A为当前窗口的前2个窗口的起始点所在的函数的开始和后2个窗口的末尾点所在的函数的结束
- 检查范围A中是否有没有被刷新的区域, 如果有找出来, 并分别加亮区域
再之后,就是比较复杂的具体加亮,就不赘述了.
- 如果是第一次运行这个hook则

loading...
不错,不过貌似我不习惯用这个,因为有自动补全。。
[回复]
ahei 回复:
五月 17th, 2010 at 1:50 上午
@B.Qnyd, 。。。这个与自动补全有啥关系呢?
[回复]
B.Qnyd 回复:
五月 17th, 2010 at 2:11 上午
@ahei, 嘿嘿,自动补全就不会出错了啊,把C语法弄那么炫耀干什么啊
[回复]
ahei 回复:
五月 17th, 2010 at 2:22 上午
@B.Qnyd, 。。。好吧
[回复]
赞,虽然我对emacs自带的高亮已经满足了,不过还是谢谢作者提供这么好的功能,说不定哪天我就喜欢上了
[回复]
ahei 回复:
五月 17th, 2010 at 5:25 上午
@Meteor Liu, 话说你以前不是想要这个功能吗?
[回复]
Meteor Liu 回复:
五月 17th, 2010 at 5:45 上午
@ahei,
有段时间看到有人介绍ctypes,觉得可能会很酷就想要,
最近这段时间又喜欢上简洁了,不想把emacs弄太花
[回复]
ahei 回复:
五月 17th, 2010 at 5:48 上午
@Meteor Liu, 呵呵,这么快就喜欢简洁啦?我玩到现在只要不麻烦的好玩的我都想加上,反正又不需要啥配置的,直接require就行,呵呵
[回复]
Meteor Liu 回复:
五月 17th, 2010 at 6:05 上午
@ahei,
被highlight-tail害的,当初你一介绍highlight-tail就用上了,那时候我也是喜欢把好玩的扩展都装上,
后来发现highlight-tail的bug实在不能忍,再后来就开始简洁了,非必须的扩展全删掉了,
color-theme都不用了。
[回复]
ahei 回复:
五月 17th, 2010 at 6:08 上午
@Meteor Liu, 哈哈,不要这样嘛,我现在也不用highlight-tail了,不过等我有空的时候一定要把那个bug干掉,其实semantic也有责任的,有时候文件大了,没开highlight-tail的话,也有小的滚屏的,不过很快就没了,不像开着highlight-tail的话,会一直有
[回复]
Meteor Liu 回复:
五月 17th, 2010 at 6:15 上午
@ahei,
除了滚屏我还发现个bug:
我习惯了cua-mode,开了highlight-tail的话基本上我就不能用C-c复制了
[回复]
ahei 回复:
五月 17th, 2010 at 6:21 上午
@Meteor Liu, 那个C-c不太好,想按C-c C-c的话,稍微按慢了点就变成两个C-c了,不爽,既然用Emacs就得习惯Emacs阿,呵呵
[回复]
Tubo 回复:
五月 18th, 2010 at 1:05 上午
@ahei,
呵呵,我也很不喜欢那个CUA。
[回复]
ahei 回复:
五月 18th, 2010 at 1:13 上午
@Tubo, 在我看来CUA只有一个优点,就是它的矩形操作很nb,比那个rect-mark好用,所以我一直在用它的矩形操作
[回复]
fangzhzh 回复:
五月 17th, 2010 at 11:41 下午
@Meteor Liu, 我还是喜欢有color-theme的emacs,否则太素了,呵呵
[回复]
nowait 回复:
五月 17th, 2010 at 5:30 上午
@Meteor Liu, 也多谢ahei, 发个文章, 编辑也挺耗时间的
[回复]
ahei 回复:
五月 17th, 2010 at 5:31 上午
@nowait, 哈哈,我现在都成专业编辑了。
[回复]
晕,我咋没看到什么效果
[回复]
ahei 回复:
五月 17th, 2010 at 5:53 上午
@, 我刚才更新了他的Elisp包,你再更新一下。
[回复]
匿名 回复:
五月 17th, 2010 at 6:31 上午
@ahei, 不错,不过黑色背景下就不好看了,呵呵
[回复]
ahei 回复:
五月 17th, 2010 at 6:35 上午
@, 呵呵,你可以看看DEA里面的zjl-c-hl-face-settings
[回复]
哈哈,这个不错,我喜欢,以前用source insight就觉得这个功能很好,要是能和source insight一样强大就更好了。
[回复]
ahei 回复:
五月 18th, 2010 at 2:29 下午
@wolfhuang, 呵呵, 关于高亮, source insight还有什么更强大的地方呢?
[回复]
看看我配的如何……
[回复]
nowait 回复:
五月 23rd, 2010 at 2:41 上午
@, 貌似还不错, 我有添加进code去了
[回复]
各位大牛。
写程序时经常要靠宏定义输出一些DEBUG信息比如
#ifdef DEBUG
cout<<"The value of number is: "<<number<<endl;
#endif
我知道YASnippet可以定义一个缩略写来迅速展开,不过我希望可以以更智能地输出信息比如自动加入当前函数名,这个不知道有没有插件可以做到?
[回复]
ahei 回复:
五月 29th, 2010 at 7:35 上午
@demon386, yasnippet应该可以做到的, 因为yasnippet里面定义snippet的时候可以使用elisp, 有了elisp啥不能实现
[回复]
demon386 回复:
六月 3rd, 2010 at 3:04 下午
@ahei, 嗯。写成了,自动添加函数信息和文件信息,yasnippet很好很强大。。
[回复]
ahei 回复:
六月 3rd, 2010 at 3:42 下午
@demon386, 不错,你也很强大
[回复]
刚看到楼上在讨论c-c-的事情,不知与我遇到的情况是否一样,我发现在emacs中,用鼠标左键去选择文本,每次minibuffer都出现c-c,当再次点击emacs中的其他地方,emacs提示c-c- 为undefined。感觉非常不爽,不知站长有什么办法让c-c- 不自动加上。(这与mouse-drag-region函数是否有关?)
[回复]
ahei 回复:
五月 29th, 2010 at 7:54 上午
@xilbert, 那应该是你的配置的问题, 建议你用emacs -Q试试
[回复]
xilbert 回复:
五月 29th, 2010 at 8:00 上午
@ahei, emacs -Q 启动后依旧如此,每次用
鼠标选择文本,依旧自动加上 c-c-
[回复]
ahei 回复:
五月 29th, 2010 at 8:09 上午
@xilbert, 这个我就不知道了, 很诡异, 我这没问题.
[回复]
xilbert 回复:
五月 29th, 2010 at 9:04 上午
@ahei,
确实很诡异,我用的23.2版的,我把下面这句加入配置文件里
(define-key global-map [down-mouse-3] ‘mouse-drag-region)
换用右键选择文字,结果发现就不会出现问题。真的很奇怪!
[回复]
xilbert 回复:
五月 29th, 2010 at 9:15 上午
@ahei,
我还又下了了23.1版的emacs,emacs -Q 运行后,左键选择文本后,依然自动加上c-c-
键,难道我的机器这么怪异?(系统:windows xp ,将ctrl 与 caps lock 互换过)
[回复]
ahei 回复:
五月 29th, 2010 at 9:19 上午
@xilbert, 你用的是官方的emacs Windows版本吗?
[回复]
xilbert 回复:
五月 29th, 2010 at 9:26 上午
@ahei,
一个是NTemacs23.1
另一个是emacsW32 23.2
[回复]
用了一周,当括号不匹配的时候,很容易就让emacs当掉. 比如在输入if语句,刚写了两个前括号((的时候.
一开始还以为是cedet的idle分析问题,后来禁用掉这个语法高亮就OK了.
我不懂eslip,也不知道怎么来解决这个问题.
其它好像也没什么可以高亮变量的函数的插件,太可惜了.
但愿这人bug能早点修复
[回复]
ahei 回复:
六月 6th, 2010 at 4:20 上午
@sweord, 你试试emacs -Q启动,然后只加载zjl-hl,看看有没有错误,我这试了是没错误的,建议你检查一下你的配置文件.
[回复]
nowait 回复:
六月 7th, 2010 at 7:37 上午
@sweord, 汗, 我确实没有仔细考虑这个括号或函数是不是有头没尾会有问题,
, 虽然有一点预感可能会出问题…
[回复]
支持楼主完善你强大的作品,我感动得都快哭了。
[回复]
@网摘
http://www.emacswiki.org/emacs/JianliZhao
这个是在大约一年前或者一年半以前的时候放的, 后来我一直没有更新. 和这个上面贴的差别, 改进也挺大的, 消耗资源少多了, 而且应该很难死. 写ellisp如果用这个mode也能有加亮…. 不过确实是还没有用正宗的做法来做, 也没有研究怎么做….
[回复]