首页 最近更新 网站讯息 页面索引 这是什么?

EmacsCustomizationAndExtension

最新内容参见 http://www.wanglianghome.org/svn/emacsbook/trunk/emacs.org

内容

  1. CVS Emacs
    1. Emacs daemon
    2. Pretty font
    3. 问题
  2. Help scripts
  3. Simple todo (Org Mode)
  4. Encrypted bbdb
  5. remember with Org Mode
  6. filecache and anything
  7. etags and etags-select
  8. cscope
  9. install-elisp
  10. repeated tasks (Org Mode)
  11. reminder (Org Mode)
  12. eldoc, paredit, and find-func
  13. notes (Org Mode)
  14. yasnippet
  15. hippie-expand and auto-complete
  16. Help scripts for root access

CVS Emacs

使用CVS Emacs的理由很简单,它具有一些已经发布的 GNU Emacs 不具备的功能。就目前来讲,一个是 Emacs daemon,另一个就是可以享受漂亮的字体。

访问CVS Emacs的方法参见 http://savannah.gnu.org/cvs/?group=emacs

Emacs daemon

从前只有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。

Pretty font

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)

Help scripts

作为一名 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里面编辑的内容。

Simple todo (Org Mode)

就我个人来看,Org Mode是近年来最震撼人心的 Emacs Mode 之一,它的出现,使得大量用户更加紧密地团结在Emacs周围。

主页: http://orgmode.org/

代码: 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手册。

Encrypted bbdb

参见[5]

remember with Org Mode

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 and anything

filecache参见[6]

anything参见[7]

etags and etags-select

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

cscope提供的功能比etags更强大,它的使用很简单,只需在项目根目录下运行

  find . -name "*.[hc]" >cscope.files
  cscope -b -q -k

即可。

而在GNU Emacs里面也只需一行代码

  (require-maybe 'xcscope)

在GNU Emacs里面可以使用绝大多数cscope的功能,然而要想显示函数调用关系的话,还需要另外的程序,如CbrowserKScope

install-elisp

参见[8]

repeated tasks (Org Mode)

只要对任务开始日期稍加修改,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>的下一次日期是按今天算起的下一个星期,也就是说,不一定是星期四;如果今天是星期二,那么下一次开始日期就是星期二。

reminder (Org Mode)

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

eldoc, paredit, and find-func

配置和扩展Emacs的过程中,或多或少都会写点 Emacs Lisp 程序,eldoc和paredit使得这个过程更加流畅和便捷。

eldoc能够在echo area显示函数的参数列表,它对系统自带函数和用户自定义函数一视同仁。例如当输入

  (dolist

的时候,eldoc显示如下帮助信息:

  dolist: ((VAR LIST [RESULT]) BODY...)

其中各个参数部分还会随着用户的输入而逐个高亮显示。

paredit是为了对付 Lisp 程序里无处不在的括号,下面列出它的部分功能:

更多功能参见paredit.el中的变量paredit-commands

find-func参见[9]

notes (Org Mode)

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。

yasnippet

主页: http://code.google.com/p/yasnippet/

演示:YouTube,下载高清晰度版本

我的配置:

  (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 and auto-complete

hippie-expand参见[10]

auto-complete参见[11]

Help scripts for root access

前面提到曾使用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))))