最新内容参见 http://www.wanglianghome.org/svn/emacsbook/trunk/emacs.org
使用CVS Emacs的理由很简单,它具有一些已经发布的 GNU Emacs 不具备的功能。就目前来讲,一个是 Emacs daemon,另一个就是可以享受漂亮的字体。
访问CVS Emacs的方法参见 http://savannah.gnu.org/cvs/?group=emacs 。
从前只有Emacs server的概念,即可以让已经启动的Emacs进程作为server,然后使用emacsclient连接它;而 Emacs daemon 则是让Emacs进程作为daemon存在。
两者的区别是,Emacs server至少具有一个frame,即使不使用emacsclient程序,我们仍然可以使用这个Emacs进程;而daemon没有任何交互界面存在,必须通过emacsclient创建frame才能使用它。
使用Emacs daemon的好处之一是在重新启动 X Window 的时候无须关闭Emacs进程;另外就是可以远程启动,Emacs daemon可以在登录退出时仍然运行在服务器端。
CVS里面的emacsclient程序拥有两个新的选项:-c
和-t
,分别用于创建X frame和终端上的frame。
CVS Emacs的另一个特性是可以使用更加漂亮的字体,正是这一特性,使我一直坚持使用 CVS Emacs,而不是正式发布的稳定版本,屏幕截图参见 [1] 。
编译方法如下:
cd emacs ./configure --prefix=/usr --enable-font-backend make bootstrap && make sudo make install
设置字体方法是运行 M-x customize-face RET default RET ,我基本都是使用 Liberation Mono 。
另外,建议从 http://www.m17n.org/ 下载并安装 libotf
, m17n-lib
, m17n-db
,以及m17n-contrib
。从configure
的结果可以看出这几个库是否存在或找到。如果对动态链接不太了解的话,请使用如下方法编译:
./configure --prefix=/usr && make && sudo make install
因为是开发版,CVS Emacs 难免有这样那样的问题,尤其是对于刚刚开发出来的新特性,但是对于基本特性来说,质量还是相当过硬的,这也是为什么我使用 CVS Emacs 一年多来再也没有回头使用已经发布的稳定版本的原因。如果在使用过程中确信是 CVS Emacs 的问题,建议报到emacs-devel邮件列表上[2],以便开发者及时发现并解决问题。
在同时使用 Emacs daemon 和漂亮字体的时候我曾遇到过一个问题,至今不得要领,解决方法是很偶然发现的,即将自己的配置全都放在 custom-set-faces 语句之后。我的 .emacs
文件是如下的样子:
(custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. ) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(default ((t (:inherit nil :stipple nil :background "white" :foreground "black" :inverse-video nil :box nil :strike-through nil :overline nil :underline nil :slant normal :weight normal :height 140 :width normal :foundry "unknown" :family "Liberation Mono"))))) (add-to-list 'load-path "~/elisp") (require 'wl-fedora-init)
作为一名 GNU Emacs 重度用户,却一度使用vi做些系统管理的工作,因为vi的启动速度快。命令行上输入vi加文件名,修改三五字符,便存盘退出,就这层意义上说,Emacs慢了。当然也可以使用 Emacs server,但是那就复杂了些,如果是远程登录,就更复杂了,搞不好便要启动多个Emacs进程。
这个问题随着multi-tty乃至 Emacs daemon 的出现,便迎刃而解了。首先,我们可以在命令行上使用emacsclient -t
的用法,在终端上开启一个frame,速度堪比vi。如果喜欢图形界面,请使用emacsclient -c
。不过,敲这么一长串字符,比起vi两个字符而言,还是繁琐了不少。
解决这个问题也很简单,要么做一个alias,要么创建一个短名字的脚本,为了能够用在更多的场合,我选择创建两个bash脚本,名字分别为ect[3]和ecc[4]。
所谓更多的场合,目前来讲也只有一个,就是配合firefox的扩展 It's All Text! 使用。通过这一套工具的组合,便可以使用Emacs编辑原本需要在textarea里面编辑的内容。
就我个人来看,Org Mode是近年来最震撼人心的 Emacs Mode 之一,它的出现,使得大量用户更加紧密地团结在Emacs周围。
代码: git://repo.or.cz/orgmode.git
管理代办事项是Org Mode的核心功能之一,使用起来非常简单。在 Outline Mode 的基础上,Org Mode提供了C-c C-t
切换任务状态。第一次将人物切换到TODO
状态,第二次切换到DONE
表示完成。下面是一个简单的例子。
* TODO 写一篇关于Emacs的blog * DONE 确认测试全部通过
另外还可以通过C-c C-s
设置任务开始日期,C-c C-d
设置截止日期。更多功能参见Org Mode手册。
参见[5]
Org Mode功能很强大,只是在开始记录的时候稍嫌麻烦,比如要先打开相应的org文件,选择合适的位置,才能插入内容。如果配合remember使用Org? Mode,则对于那些上下文无关的内容,可以大大减轻辅助工作量。下面是一些配置:
(autoload 'remember "remember" nil t) (autoload 'remember-region "remember" nil t) (define-key global-map [(f8)] 'remember) (setq remember-annotation-functions '(org-remember-annotation)) (setq remember-handler-functions '(org-remember-handler)) (add-hook 'remember-mode-hook 'org-remember-apply-template) (setq org-directory "~/gtd/") (setq org-remember-templates `((?t "* TODO %?\n %i\n %a" ,(expand-file-name "todo.org" org-directory) "Tasks") (?n "* %u %?\n\n %i\n %a" ,(expand-file-name "notes.org" org-directory) "Notes")))
想要记录某些内容的时候,按F8
键,然后使用快捷键t
或者n
选择插入任务还是笔记,在输入buffer里面写完后C-c C-c
,就可以把内容存到相应的文件里面特定的分类下。比如输入一个任务,那么这个任务保存在~/gtd/todo.org
文件的Tasks
大类下面。
filecache参见[6]
anything参见[7]
etags是GNU Emacs的标配,程序员通常用它来定位函数、变量或其它实体的定义。对于每个名字之只有一处定义的项目,etags足够用了;如果某个名字对应多出定义,那么etags会根据用户请求逐个遍历这些定义位置,直到用户找到自己想要的东西而终止遍历。
但是当一个名字对应的定义过多时,etags会带来挫折感,需要遍历好多次才能找到自己想要的东西,而且在遍历过程中没办法知道到底还有多少种可能,要么抱着死马当活马医的心态不停遍历下去,要么改用其它工具。这个时候,就是etags-select.el发挥作用的时候,它无须搜索项目里的每个文件,而是和etags一样,利用预先生成的TAGS文件,不同之处是对于有多个定义的情况,etags-select首先列出所有的选择让用户选择,让人做到心中有数。
目前的etags-select.el实现有个小小的缺陷,即不支持嵌套的TAGS文件,比如Emacs的TAGS文件里面就间接引用另外一个TAGS-LISP文件,通过重定义etags-select中的一个函数可以解决这个问题:
(defun etags-select-get-tag-files () "Get tag files." (if etags-select-use-xemacs-etags-p (buffer-tag-table-list) (mapcar 'tags-expand-table-name tags-table-list) (tags-table-check-computed-list) tags-table-computed-list))
cscope提供的功能比etags更强大,它的使用很简单,只需在项目根目录下运行
find . -name "*.[hc]" >cscope.files cscope -b -q -k
即可。
而在GNU Emacs里面也只需一行代码
(require-maybe 'xcscope)
在GNU Emacs里面可以使用绝大多数cscope的功能,然而要想显示函数调用关系的话,还需要另外的程序,如Cbrowser或KScope
参见[8]
只要对任务开始日期稍加修改,Org Mode 就能够管理周期性代办事项。比如周四要开会,可以设置如下代办事项:
* TODO 开会 SCHEDULED: <2009-01-22 四>
如果是每周四都开会,就改写成如下的样子:
* TODO 开会 SCHEDULED: <2009-01-22 四 +1w>
1w表示每周,另外1d表示每天,1m表示每月。对于周期性的任务,C-c C-t
每次将开始日期修改为相应的下一次开始日期,并保持TODO
状态不变。
通常情况下,任务开始日期总是严格地按照预定间隔变动,但是当我们需要忽略掉已经过期的日期时,就可以使用++
或者.+
来修饰时间间隔,如<2009-01-22 四 ++1w>的下一次日期一定是今天之后的第一个星期四,而<2009-01-22 四 .+1w>的下一次日期是按今天算起的下一个星期,也就是说,不一定是星期四;如果今天是星期二,那么下一次开始日期就是星期二。
Org Mode本身并没有提供提醒功能,需要配合appt使用。下面是一个简单的配置:
(require 'appt) (setq appt-display-format 'window) (appt-activate 1) (setq org-agenda-include-diary t) (org-agenda-to-appt) (defadvice org-agenda-redo (after org-agenda-redo-add-appts) "Pressing `r' on the agenda will also add appointments." (progn ;; Dangerous!!! This might remove entries added by `appt-add' manually. (setq appt-time-msg-list nil) (let ((config (current-window-configuration))) (appt-check t) (set-window-configuration config)) (org-agenda-to-appt))) (ad-activate 'org-agenda-redo)
在 Org Mode 的 Agenda View 下,按r
或者g
,就可以把有具体时间的任务添加到appt的任务提醒列表里面。需要注意的是,手工使用appt-add
添加的提醒将被清除,无法恢复。所以,当使用本节的配置时,请将任务添加到相应的org文件里,而不是使用appt-add
。
配置和扩展Emacs的过程中,或多或少都会写点 Emacs Lisp 程序,eldoc和paredit使得这个过程更加流畅和便捷。
eldoc能够在echo area显示函数的参数列表,它对系统自带函数和用户自定义函数一视同仁。例如当输入
(dolist
的时候,eldoc显示如下帮助信息:
dolist: ((VAR LIST [RESULT]) BODY...)
其中各个参数部分还会随着用户的输入而逐个高亮显示。
paredit是为了对付 Lisp 程序里无处不在的括号,下面列出它的部分功能:
C-k
删除整个括号表达式,即使它跨越多行;否则删除到当前一级括号表达式的最后,但保留括号M-s
删除当前括号表达式的左右括号C-S-)
将当前一级的右括号向右扩展一位,即将下一个表达式包含进来更多功能参见paredit.el中的变量paredit-commands
。
find-func参见[9]
Org Mode 最简单的功能不是管理代办事项,而是记笔记,不需任何配置,就想使用 Outline Mode 那样即可。除此之外,如果想记录每次记笔记的时间,可以使用快捷键C-c !
来插入一个日期。更花哨地,可以配合使用remember,不仅可以记录日期,还能插入链接。
(setq org-reverse-note-order t) (setq org-remember-templates `((?m "* %U\n\n %?%i\n %a" ,(expand-file-name "minutes.org" org-directory) "Minutes")))
效果有点像一个本地的twitter。
主页: http://code.google.com/p/yasnippet/
我的配置:
(when (file-exists-p "~/elisp/3rd-party-lib/yasnippet") (add-to-list 'load-path "~/elisp/3rd-party-lib/yasnippet") ;;; Workaround: do not show menu until I find a way to show menu only ;;; on certain window. (setq yas/use-menu nil) (when (require-maybe 'yasnippet) (yas/initialize) (yas/load-directory "~/elisp/3rd-party-lib/yasnippet/snippets/") (remove-hook 'after-change-major-mode-hook 'yas/minor-mode-auto-on) (add-hook 'cperl-mode-hook 'yas/minor-mode-auto-on) (add-hook 'perl-mode-hook 'yas/minor-mode-auto-on) (add-hook 'c-mode-common-hook 'yas/minor-mode-auto-on)))
hippie-expand参见[10]
auto-complete参见[11]
前面提到曾使用vi做些系统管理的工作,速度快是原因之一,根本原因还是如何获得root权限,就这一点来说,sudo emacs
根本没法和sudo vi
相提并论。幸好,我们有TRAMP。
TRAMP本是为了编辑远程文件而设计的,仔细阅读它的文档会发现,它还提供了使用root权限打开本地文件的功能,方法是C-x C-f /sudo::
,后面加上本地文件名,如C-x C-f /sudo::/etc/X11/xorg.conf
,此外,对文件名还提供TAB
键补全功能,第一次按TAB
键会要求输入密码。
为了方便在命令行上使用,我创建了两个bash脚本——sudoect[12]和sudoecc[13],以及一个 Emacs Lisp 辅助函数,如下:
(defun wl-sudo-find-file (file dir) (find-file (concat "/sudo:localhost:" (expand-file-name file dir))))