我编写了一个Emacs Lisp函数,它调用shell命令来处理给定的字符串并返回结果字符串.这是一个简单的例子,它只是调用tr将文本转换为大写:
(defun test-shell-command (str)
"Apply tr to STR to convert lowercase letters to uppercase."
(let ((buffer (generate-new-buffer "*temp*")))
(with-current-buffer buffer
(insert str)
(call-process-region (point-min) (point-max) "tr" t t nil "'a-z'" "'A-Z'")
(buffer-string))))
Run Code Online (Sandbox Code Playgroud)
此函数创建临时缓冲区,插入文本,调用
tr,用结果替换文本,并返回结果.
上面的函数按预期工作,但是,当我在此函数周围编写包装器以将命令应用于区域时,撤消历史记录中将添加两个步骤.这是另一个例子:
(defun test-shell-command-region (begin end)
"Apply tr to region from BEGIN to END."
(interactive "*r")
(insert (test-shell-command (delete-and-extract-region begin end))))
Run Code Online (Sandbox Code Playgroud)
当我调用时M-x test-shell-command-on-region,区域将替换为大写文本,但是当我按C-_(undo)时,撤消历史记录中的第一步是删除文本的状态.退回两步,恢复原始文本.
我的问题是,如何防止中间步骤被添加到撤消历史记录中?我已经阅读了有关撤消的Emacs文档,但就我所知,它似乎并没有解决这个问题.
这是一个函数,它通过调用内置的Emacs函数完成同样的事情upcase,就像之前一样:在
delete-and-extract-region结果传递给
insert:
(defun test-upcase-region (begin end)
"Apply upcase to region from BEGIN to END."
(interactive "*r")
(insert (upcase (delete-and-extract-region begin end))))
Run Code Online (Sandbox Code Playgroud)
在调用时M-x test-upcase-region,撤消历史记录中只有一个步骤,如预期的那样.因此,似乎调用
test-shell-command会创建一个撤消边界.这可以以某种方式避免吗?
关键是缓冲区名称.请参阅维护撤消:
通常在新创建的缓冲区中记录撤消信息以启动; 但如果缓冲区名称以空格开头,则最初禁用撤消录制.您可以使用以下两个功能显式启用或禁用撤消录制,也可以自行设置buffer-undo-list.
with-temp-buffer创建一个名为?*temp*(注意前导空格)的缓冲区,而您的函数使用*temp*.
要删除代码中的撤消边界,请使用带有前导空格的缓冲区名称,或者在临时缓冲区中显式禁用撤消重新编码buffer-disable-undo.
但一般来说with-temp-buffer,真的使用.这是Emacs中此类事物的标准方式,使您的意图对于阅读代码的任何人都清楚.此外,with-temp-buffer努力正确清理临时缓冲区.
至于为什么临时缓冲区中的undo会在当前缓冲区中创建撤消边界:如果先前的更改是可撤消的并且在某个其他缓冲区(在本例中为临时缓冲区)中进行,则会创建隐式边界.来自undo-boundary:
每当在某个其他缓冲区中进行先前的可撤消更改时,所有缓冲区修改都会添加边界.这是为了确保每个命令在每个缓冲区中进行更改的边界.
因此,禁止临时缓冲区中的撤销也会删除当前缓冲区中的撤消边界:先前的更改不再是可撤消的,因此不会创建隐式边界.
| 归档时间: |
|
| 查看次数: |
923 次 |
| 最近记录: |