emacs 光标移动路径点

Vim、Emacs配置和使用
回复
kardinal
帖子: 750
注册时间: 2006-03-19 11:39

emacs 光标移动路径点

#1

帖子 kardinal » 2013-02-07 2:37

简单的说,当光标依次移动到 a b c d 位置的时候,用 (beacon) 标记;
然后用(beacon-jump)可以依次返回 d c b a 这几个点,
或者 (C-u 3 beacon-jump) 直接返回 b 点

[lisp]
(defun beacon ()
(interactive)
(let ((k (where-is-internal 'beacon-jump)))
(message (concat (mapconcat 'key-description k " , ")
(if k " or ")
"C-M-c to jump back.")))
(let ((x (point-marker)))
(catch 'exit (and (catch (recursion-depth) (recursive-edit)) (throw 'exit t)))
(switch-to-buffer (marker-buffer x))(goto-char x)))

(defun beacon-jump (&optional n)
(interactive "p")
(let* ((x (recursion-depth))
(i (if (> (or n 1) x)
x n)))
(throw (- x i) t)))
[/lisp]

虽然看起来比较简单,但实际上是非常变态的,
因为(recusive-edit) 或者(exit-recusive-edit)控制权会跨层转移,所以
(dotimes (i 100) (recursive-edit)) 也只能执行一次(recursive-edit),exit-recursive-edit 亦然
为了实现能够退出多层,用了一种比较恶心的方式,元芳你怎么看
[lisp]
;; 在 recursive-edit 时执行的退出代码
(throw (- (recursion-depth) n) t)
;; 接收到退出代码时的动作
(catch 'exit
(and
(catch (recursion-depth)
(recursive-edit))
(throw 'exit t)))
[/lisp]
这段实际展开时差不多是这个样子
[lisp]
(catch 'exit
(and
(catch 0
(catch 'exit
(and
(catch 1
(catch 'exit
(and
(catch 2
(catch 'exit
(and
(catch 3
(catch 'exit
(and
(catch 4
(catch 'exit
(and
(catch 5
(throw 3 t))
(throw 'exit t))))
(throw 'exit t))))
(throw 'exit t))))
(throw 'exit t))))
(throw 'exit t))))
(throw 'exit t)))
[/lisp]
回复