在mode-line上标记svn状态

psvn.el是一款Emacs下的svn插件,前段时间把Emacs升级到23,升级整理的过程中,看到psvn.el,遂去它的主页把它的最新版本down下来,试了一下,果然功能又强大多了,一个我一直想要的功能就是在mode-line上显示当前文件的svn状态,比如是否修改过,就像下面这样:
psvn用一个带有颜色的圆表示文件的状态,绿色的圆表示未修改过,淡红色的圆表示已经修改过。
由于psvn包只有一个文件psvn.el,所以它那个圆应该不是事先做好的图片,应该是程序里面生成的。那这个就比较有意思了,竟然可以在Emacs中画圆,赶快去瞧瞧它是杂实现的。
由于这个圆是在mode-line上画的,直接去psvn.el里面去搜索mode-line,搜到一个mode-line-process,还有一个:
(setq svn-status-mode-line-process-status (format " running %s" cmdtype)) |
平时运行svn-status命令的时候,会看到状态栏显示running,看来是控制这个mode-line-process来实现的,看一下mode-line-process的文档:
1 2 3 4 5 6 7 8 | mode-line-process is a variable defined in `bindings.el'. Its value is nil Automatically becomes buffer-local when set in any fashion. Documentation: Mode-line control for displaying info on process status. Normally nil in most modes, since there is no process to display. |
看来真是它,我们来试试:
(setq mode-line-process " hi, I'm mode-line-process") |
C-x C-e执行上面的语句,mode-line变成:
果然!
继续搜索mode-line,找到一个函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | (defun svn-status-state-mark-modeline-dot (color) (propertize " " 'help-echo 'svn-status-state-mark-tooltip 'display `(image :type xpm :data ,(format "/* XPM */ static char * data[] = { \"18 13 3 1\", \" c None\", \"+ c #000000\", \". c %s\", \" \", \" +++++ \", \" +.....+ \", \" +.......+ \", \" +.........+ \", \" +.........+ \", \" +.........+ \", \" +.........+ \", \" +.........+ \", \" +.......+ \", \" +.....+ \", \" +++++ \", \" \"};" color) :ascent center))) |
看这函数名,代码和图形,有点像是它画的圆,那么我们再来看看这个svn-status-state-mark-modeline-dot函数都哪里调用了。继续查找,只有一个地方调用了:
1 2 3 4 5 | (defun svn-status-install-state-mark-modeline (color) (push `(svn-status-state-mark-modeline ,(svn-status-state-mark-modeline-dot color)) mode-line-format) (force-mode-line-update t)) |
而svn-status-install-state-mark-modeline是svn-status-update-state-mark调用的,svn-status-update-modeline又调用了svn-status-update-state-mark,看来没错了,应该就是svn-status-state-mark-modeline-dot画的圆,为了更加确定一点,来做个实验。
改下svn-status-state-mark-modeline-dot的函数变成这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | (defun generate-circle (tip space edge inside) "Generate a circle." (propertize " " 'help-echo tip 'display `(image :type xpm :data ,(format "/* XPM */ static char * data[] = { \"18 13 3 1\", \" c %s\", \"+ c %s\", \". c %s\", \" \", \" +++++ \", \" +.....+ \", \" +.......+ \", \" +.........+ \", \" +.........+ \", \" +.........+ \", \" +.........+ \", \" +.........+ \", \" +.......+ \", \" +.....+ \", \" +++++ \", \" \" };" space edge inside) :ascent center))) |
然后执行下面的代码:
(insert (generate-circle "我是圆" "None" "black" "red")) |
出现下面的截图:
(insert (generate-circle "我是月环食" "None" "yellow" "red")) |
再来一张膏药旗
(insert (generate-circle "我是膏药旗" "white" "yellow" "red")) |
再画个立方体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | (defun generate-cube (tip) "Generate a cube." (propertize " " 'help-echo tip 'display `(image :type xpm :data ,(format "/* XPM */ static char * data[] = { \"32 39 5 1\", \". c none\", \"+ c black\", \"@ c #3070E0\", \"# c #F05050\", \"$ c #35E035\", \"................+...............\", \"..............+++++.............\", \"............+++++@@++...........\", \"..........+++++@@@@@@++.........\", \"........++++@@@@@@@@@@++........\", \"......++++@@++++++++@@@++.......\", \".....+++@@@+++++++++++@@@++.....\", \"...+++@@@@+++@@@@@@++++@@@@+....\", \"..+++@@@@+++@@@@@@@@+++@@@@@++..\", \".++@@@@@@+++@@@@@@@@@@@@@@@@@@++\", \".+#+@@@@@@++@@@@+++@@@@@@@@@@@@+\", \".+##++@@@@+++@@@+++++@@@@@@@@$@.\", \".+###++@@@@+++@@@+++@@@@@++$$$@.\", \".+####+++@@@+++++++@@@@@+@$$$$@.\", \".+#####+++@@@@+++@@@@++@$$$$$$+.\", \".+######++++@@@@@@@++@$$$$$$$$+.\", \".+#######+##+@@@@+++$$$$$$@@$$+.\", \".+###+++##+##+@@++@$$$$$$++$$$+.\", \".+###++++##+##+@@$$$$$$$@+@$$@+.\", \".+###++++++#+++@$$@+@$$@++$$$@+.\", \".+####+++++++#++$$@+@$$++$$$$+..\", \".++####++++++#++$$@+@$++@$$$$+..\", \".+#####+++++##++$$++@+++$$$$$+..\", \".++####+++##+#++$$+++++@$$$$$+..\", \".++####+++####++$$++++++@$$$@+..\", \".+#####++#####++$$+++@++++@$@+..\", \".+#####++#####++$$++@$$@+++$@@..\", \".++####++#####++$$++$$$$$+@$@++.\", \".++####++#####++$$++$$$$$$$$+++.\", \".+++####+#####++$$++$$$$$$$@+++.\", \"..+++#########+@$$+@$$$$$$+++...\", \"...+++########+@$$$$$$$$@+++....\", \".....+++######+@$$$$$$$+++......\", \"......+++#####+@$$$$$@++........\", \".......+++####+@$$$$+++.........\", \".........++###+$$$@++...........\", \"..........++##+$@+++............\", \"...........+++++++..............\", \".............++++...............\" };" ) :ascent center))) |
(insert (generate-cube "我是立方体")) |
再来一张更眩的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | (defun generate-compact-disk (tip) "Generate one compact disk." (propertize " " 'help-echo tip 'display `(image :type xpm :data ,(format "/* XPM */ static char * data[] = { \"16 16 8 1\", \" c None s None\", \". c #808080\", \"X c #FFFF00\", \"o c #c0c0c0\", \"O c black\", \"+ c #00FFFF\", \"@ c #00FF00\", \"# c white\", \" ..... \", \" ..XXoooOO \", \" .+XXXoooooO \", \" .@++XXoooo#oO \", \" .@@+XXooo#ooO \", \".oo@@+Xoo#ooooO \", \".ooo@+.O.oooooO \", \".oooo@O#OoooooO \", \".oooo#.O.+ooooO \", \".ooo#oo#@X+oooO \", \" .o#oooo@X++oO \", \" .#ooooo@XX++O \", \" .ooooo@@XXO \", \" ..ooo@@OO \", \" ..OOO \", \" \" };" ) :ascent center))) |
(insert (generate-compact-disk "我是光盘")) |
其实, 只要你明白xpm的格式, 自己完全可以构建那个data, 画出各种各样的图形.
现在还有个问题,怎么定制这些圆的颜色呢?
我们来看看svn-status-update-mode-line的代码:
1 2 3 4 5 6 | (defun svn-status-update-modeline () "Update modeline state dot mark properly" (when (and buffer-file-name (svn-status-in-vc-mode?)) (svn-status-update-state-mark (svn-status-interprete-state-mode-color (vc-svn-state buffer-file-name))))) |
svn-status-update-mode-line把
1 2 | (svn-status-interprete-state-mode-color (vc-svn-state buffer-file-name)) |
作为参数传给svn-status-update-state-mark,而svn-status-update-state-mark代码:
1 2 3 | (defun svn-status-update-state-mark (color) (svn-status-uninstall-state-mark-modeline) (svn-status-install-state-mark-modeline color)) |
svn-status-update-state-mark的参数为颜色,这就是说svn-status-interprete-state-mode-color的作用应该是得到颜色,且来看看它的定义:
1 2 3 4 5 6 7 8 9 10 11 | (defsubst svn-status-interprete-state-mode-color (stat) "Interpret vc-svn-state symbol to mode line color" (case stat ('edited "tomato" ) ('up-to-date "GreenYellow" ) ;; what is missing here?? ;; ('unknown "gray" ) ;; ('added "blue" ) ;; ('deleted "red" ) ;; ('unmerged "purple" ) (t "red"))) |
这个函数的参数是当前文件的svn状态,返回一个颜色字符串。
看来只要改这个函数就能定制颜色了。
等等,难道要直接修改psvn.el吗?当然不需要,而且那是个不好的习惯。由于Elisp不像c等编译型语言,它是解释型语言(也可以编译成字节码),如果你多处定义了同一个函数,后面的会覆盖的前面的定义。根据这个特性,我们就可以在我们自己的配置文件中重新定义一下svn-status-interprete-state-mode-color就可以了,重新定义如下:
1 2 3 4 5 6 7 8 9 10 | (defsubst svn-status-interprete-state-mode-color (stat) "Interpret vc-svn-state symbol to mode line color" (case stat ('up-to-date "GreenYellow") ('edited "tomato") ('unknown "gray") ('added "blue") ('deleted "red") ('unmerged "purple") (t "black"))) |
这样,未修改的文件绿色圆,修改过的淡红色圆,增加的文件蓝色圆,删除的文件红色圆。

loading...









有意思,竟然还能这样。不过你的立方体和光盘图标是怎么画的啊?
ASCII art?
[回复]
ahei 回复:
一月 28th, 2010 at 1:16 下午
不是ascii art,是直接画出图像的。其实你只要懂xpm格式,完全可以自己写那个data, 画各种各样的图像
[回复]
不要这么nb好不好,看到那个立方体震惊了~~
欢迎来 irc.oftc.net #emacs-cn ,呵呵,里面的 xwl 不知道你知道不
[回复]
ahei 回复:
一月 28th, 2010 at 1:40 下午
irc.oftc.net我这打不开,我翻墙过去看,也没看到啥啊
[回复]
x 回复:
一月 29th, 2010 at 1:50 上午
@ahei, 看样子没玩过IRC?
[回复]
ahei 回复:
一月 29th, 2010 at 2:25 上午
没玩过,但是知道,emacs下还有它的插件
[回复]
ahei 回复:
一月 29th, 2010 at 3:40 上午
@ahei, 出糗了,
我去irc.oftc.net瞧了,那个xwl我知道的,用过他的dired-isearch。
[回复]
搜索semantic时找到了这个博客,写得很好啊,看来我对Emacs还没有入门呢。曾经试用了我所能找到的所有代码编辑器,还是Emacs配置之后用起来最舒服。我原本想写一篇博文向初学者介绍Emacs,现在看来不用重复造车轮了。
[回复]
ahei 回复:
二月 5th, 2010 at 12:24 上午
@Ariesbear, 呵呵,谢谢支持。可以再谢谢阿,每个人都有不同的看法,正如你所说,think different,而且也能对Emacs认识的更清楚一些。
[回复]
这么好的域名,可不可以用于建个Emacs的中文讨论区?用fluxbb或phpbb论坛程序很方便啊?
[回复]
ahei 回复:
二月 11th, 2010 at 1:16 上午
我之前也有这个打算,不过emacs不像其他东西,用的人少,而且需要花时间,光靠我一个人是不够的,你看水木emacs版都不活跃。
[回复]
happybabe 回复:
二月 11th, 2010 at 8:00 上午
@ahei, 有多少人能看得懂水木区的排版?orz…emacser都在哪里热闹呢?
[回复]
ahei 回复:
二月 11th, 2010 at 8:02 上午
@happybabe, 还好吧,现在国内emacser应该主要还是在水木emacs版活动。
[回复]
psvn 貌似在 windows下不能用,在windows下 启用 psvn 后 ,输入 svn-state ,指向的是有.svn 的目录, 但是却提示我 Searching for program: no such file or directory, svn
[回复]
ahei 回复:
八月 20th, 2010 at 11:05 上午
@kun, 你要装svn命令
[回复]
kun 回复:
八月 24th, 2010 at 6:48 上午
@ahei, 我今天试了一下,装了SVN命令,也设置了环境变量,
输入svn-state 还是提示 Searching for program: no such file or directory, svn. 晕啊
[回复]
ahei 回复:
八月 24th, 2010 at 6:51 上午
@kun, 首先你在cmd里面敲SVN有问题吗?其次,你装了之后重启过Emacs吗?
[回复]
kun 回复:
八月 24th, 2010 at 7:01 上午
@ahei, 在cmd里 输入svn 命令都没问题,
emacs也重启过了, svn-admin-create 是 可以用的,svn-status 和 svn-status-update这些都操作不了
[回复]
ahei 回复:
八月 24th, 2010 at 7:07 上午
@kun, 那我就不知道了,…
[回复]
Hi, 我在emacs中启用了该扩展以后,当我修改了一个文件以后mode-line上面的颜色是改变了,可是当我提交了以后mode-line上面的颜色却没有自动变回原来的颜色..你们遇到国这种现象吗?
[回复]
ahei 回复:
十二月 6th, 2010 at 7:40 下午
@victor, M-x revert-buffer
[回复]
victor 回复:
十二月 6th, 2010 at 7:48 下午
@ahei, 有没有什么办法让我提交了以后自动更新!
[回复]
ahei 回复:
十二月 6th, 2010 at 7:59 下午
@victor, 那只能自己写个命令提交完调用revert-buffer
[回复]
victor 回复:
十二月 6th, 2010 at 8:02 下午
@ahei,
..我对lisp不熟,不知道怎么加,可否写个例子阿?
[回复]
ahei 回复:
十二月 6th, 2010 at 8:05 下午
@victor, 呵呵,所以要学, 学Emacs最重要的就是学这个了, lisp学会了,就无敌了,啥需求都自己搞定, 呵呵
[回复]
ahei大哥,帮我写个显示CUA状态的mode line嘛,只需要像emaci那样有颜色就行了。
[回复]
ahei 回复:
二月 26th, 2011 at 4:16 下午
@lynn, 这是我为view-mode写的,你照着写吧:
[回复]
lynn 回复:
二月 26th, 2011 at 4:51 下午
@ahei, 之前也参照过,但是不知道哪些是重点,现在写好啦:
[回复]
ahei 回复:
二月 26th, 2011 at 5:21 下午
@lynn, 呵呵,弄好就好
[回复]
我也遇到了楼上kun的问题, 在windows下 启用 psvn 后 ,输入 svn-state ,指向的是有.svn 的目录, 但是却提示我 Searching for program: no such file or directory
能不能研究一下是什么导致的,鼓捣了一天也没解决。郁闷。。。。。
[回复]