记一次Emacs源代码之旅
好吧,我说的不是C-source code啦,而是一个simple.el里定义的函数,叫#'next-line,
咦,这名字怎么这么熟悉,对,就是任何教程都会第一个告诉你的那个绑定在C-n上的函数,next-line, 我发现我按住C-n时,Emacs就会卡,而C-p却不这个问题,于是我想看看C-n究竟做了点什么,为什么会这么卡。
(defun next-line (&optional arg try-vscroll) "注释部分被我去掉了。" (interactive "^p\np") (or arg (setq arg 1)) (if (and next-line-add-newlines (= arg 1)) (if (save-excursion (end-of-line) (eobp)) ;; When adding a newline, don't expand an abbrev. (let ((abbrev-mode nil)) (end-of-line) (insert (if use-hard-newlines hard-newline "\n"))) (line-move arg nil nil try-vscroll)) (if (called-interactively-p 'interactive) (condition-case err (line-move arg nil nil try-vscroll) ((beginning-of-buffer end-of-buffer) (signal (car err) (cdr err)))) (line-move arg nil nil try-vscroll))) nil)
通过在函数的不同位置加(message "%s" "here")语句,追踪到它执行的是上边黄色的部分(通过观察发现浅黄色部分也很有可能被执行到),于是
(global-set-key "\C-n" '(lambda () (interactive) (line-move 1 nil)))
连续按C-n,还是卡,果然不出所料,继续追踪。
(defun line-move (arg &optional noerror to-end try-vscroll)
(unless (and auto-window-vscroll try-vscroll
;; Only vscroll for single line moves
(= (abs arg) 1)
;; But don't vscroll in a keyboard macro.
(not defining-kbd-macro)
(not executing-kbd-macro)
(line-move-partial arg noerror to-end))
(message "%s" "executed?")
(set-window-vscroll nil 0 t)
(if (and line-move-visual
;; Display-based column are incompatible with goal-column.
(not goal-column)
;; When the text in the window is scrolled to the left,
;; display-based motion doesn't make sense (because each
;; logical line occupies exactly one screen line).
(not (> (window-hscroll) 0)))
(line-move-visual arg noerror)
(line-move-1 arg noerror to-end))))
这下好么,连注释都没有了,通过加一句message,发现unless的条件总是假,那就把它去掉,直接执行下边的语句试试?
按住C-n,居然不卡了,神奇,(其实我的探索过程时发现在defining-kbd-macro的时候总是不卡,想起的短路效应才怀疑是line-move-partial耽误的时间),于是看看这几个条件,前几个都应该秒出,把最后一个注释掉,依然不卡。
这个line-move-partial究竟是做什么的?
谷歌一下,发现了一帖子:http://lists.gnu.org/archive/html/emacs-devel/2006-09/msg00580.html 发现有人早在06年就提出来了,引用如下
If I remove the call to line-move-partial, everything is fine (except, certainly, the display of partial images).
往下看回复,一个人叫Kim F. Storm(不认识)给了如下建议
This should be fixed by setting redisplay-dont-pause to t.
继续,Richard Stallman的回复,等等,难道就是自由软件教父Richard Stallman???能看见它的回复,值了啊,
This just means that C-n is slow. Kim Storm tried to optimize it; were the optimizations made so far not sufficient?
问题解决:
因为Emacs打开图片本来就挺慢的,所以干脆牺牲掉一部分Emacs对图片的支持(根据前文打开图像可能只显示一部分),来换取对文本浏览的速度(按住C-n如流水一般),处理方法很简单,把simple.el里的line-move里unless里的line-move-partial注释掉就行了,由于simple.el是编译过的,你可以选择重新编译这个文件或者再次定义这个函数。
---全文完---
2013年5月03日 21:29
看来 Vim 不支持图片是有原因的呀 :D