Shynur
1
我是 elisp 新人, 正在阅读 Emacs 内置的 Emacs Lisp Intro. 在 [Emacs Lisp Intro > Narrowing & Widening > save-restriction] 这边,
反复读了几遍, 还是很困惑. 诸君能否帮助理解一下呢?
PS: 此处疑点有两个. 一是顺序问题; 二是图片中第二行的 one right after the other
, 这说的大概是紧靠, 为何仅在 “紧靠” 时需要这样写呢? (最后那个例子就是未 “紧靠” 的)
cireu
2
save-excursion
会记录你的当前使用的 buffer,在退出时恢复到那个 buffer。而 restriction 不会记录他在哪个 buffer。
先 save-excursion
再 save-restriction
可以用伪代码表示为
(let ((g0 (record-current-excursion))
(g1 (record-current-restriction)))
(unwind-protect
(progn
body ...)
(restore-excursion g0)
(restore-restriction g1)))
假如在 body 里面切换过 buffer,退出代码块时 restore-excursion
会帮助你回到原来的 buffer,然后 restore-restriction
就会被正常地执行。
如果反过来的话,退出来先执行 restore-restriction
。此时 restriction 的 current-buffer 上下文不正确,尚未回到原来的 buffer,无法达到期望的结果
1 个赞
Shynur
3
可书上讲的是, 应该 先恢复 restriction 再恢复 excursion. 而且, 如果 save-restriction
只能记录调用时的 buffer 的话, 那么像下面这样的代码也会出错的 (准确来说是, 与你的预期不符):
(save-excursion
(save-restriction
(set-buffer "1.txt")
(widen)))
cireu 讲解的很清楚,不妨自己找个例子试一下
foo
foo
foo
bar
bar
bar
baz
baz
baz
(defun test1 ()
"Test 1."
(interactive)
(save-excursion
(save-restriction
(goto-char (point-min))
(forward-line 2)
(narrow-to-region (point-min) (point))
(goto-char (point-min))
(replace-string "foo" "bar"))))
(defun test2 ()
"Test 2."
(interactive)
(save-restriction
(save-excursion
(goto-char (point-min))
(forward-line 2)
(narrow-to-region (point-min) (point))
(goto-char (point-min))
(replace-string "foo" "bar"))))
自己运行一下 test1
和 test2
两个函数,看看有什么不同
2 个赞
Shynur
5
很棒的例子, 谢谢. 我一直将注意力放在 body 中可能出现的 widen
却疏忽了 narrow
所以有时候光看,想着想着就把自己绕糊涂了 自己动手实验一下反而就豁然开朗
平时实验,推荐用论坛内大佬开发的一个包,不会污染当前的 Emacs 环境
我自己倒是更常用 with-emacs
:
写起来更顺畅,毕竟 repl 用起来还是有一点局促。
1 个赞