记一次Emacs源代码之旅

scinart posted @ 2013年5月03日 20:12 in elisp with tags emacs elisp , 4064 阅读

好吧,我说的不是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是编译过的,你可以选择重新编译这个文件或者再次定义这个函数。

 

---全文完---

Avatar_small
依云 说:
2013年5月03日 21:29

看来 Vim 不支持图片是有原因的呀 :D


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter