最近在移植代码过程中,需要在三个不同的gcc(FSF, Marvell和Android)源代码目录下,查看、比较文件。在另外的目录下打开同一个文件的操作比较繁琐,于是写了点Emacs Lisp代码,自动完成带开文件的操作。
方法很简单,有一个根目录列表,
(defvar wl-find-file-gcc-root-list
(mapcar 'expand-file-name
'("~/project/git/marvell-toolchain/src/gcc-src/"
"~/project/git/fsf-gcc/"
"~/project/android/toolchain/gcc/gcc-4.4.3/")))
然后通过比较根目录字符串,得到当前buffer对应文件的相对路径,在提示用户选择其它根目录,并打开该目录下的对应文件。
(defun wl-find-file-root (filename root-list)
(find-if (lambda (dir)
(when (> (length filename)
(length dir))
(string-equal dir (substring filename
0 (length dir)))))
root-list))
(defun wl-find-file-in-other-root (filename dir root-list)
(let* ((root (wl-find-file-root filename root-list))
(relative-path (substring filename (length root))))
(find-file-existing (expand-file-name relative-path dir))))
(defun wl-iswitchb-completing-read (prompt choices
&optional dummy require-match)
"Use iswitchb completion functionality."
(let ((iswitchb-make-buflist-hook
(lambda ()
(setq iswitchb-temp-buflist
(cond ((consp (car choices))
(mapcar 'car choices))
((stringp (car choices))
choices)
((symbolp (car choices))
(mapcar 'symbol-name choices))
(t
(error "Unknown type of choices.")))))))
(iswitchb-read-buffer prompt nil require-match)))
(defvar wl-find-file-completing-read-function
'wl-iswitchb-completing-read)
(defun wl-gcc-find-buffer-file-in-other-root (dir)
(interactive
(list
(let ((completion-ignore-case t)
(root (wl-find-file-root (buffer-file-name)
wl-find-file-gcc-root-list)))
(funcall wl-find-file-completing-read-function
"Open file in: " (remove-if (lambda (elem)
(string-equal elem root))
wl-find-file-gcc-root-list)))))
(wl-find-file-in-other-root (buffer-file-name)
dir
wl-find-file-gcc-root-list))
模仿Land of Lisp里面的程序风格,把代码分成functional和非functional两部分,其中wl-find-file-in-other-root是functional的,实现核心功能,而接口则是非functional,使用全局变量。





