如何崩溃撤消历史?
我正在使用一种Emacs模式,该模式可以让您通过语音识别控制Emacs。我遇到的问题之一是Emacs处理撤消的方式与您期望通过语音进行控制时的工作方式不匹配。 当用户说出几个字然后停顿时,这被称为“话语”。话语可能包含多个命令,供Emacs执行。识别器经常会错误地识别出话语中的一个或多个命令。在这一点上,我希望能够说“撤消”,并使Emacs撤消所有由语音执行的动作,而不仅仅是语音中的最后一个动作。换句话说,我希望Emacs就撤消而言将一个发声视为一个命令,即使一个发声包含多个命令也是如此。我还想指出要回到发话之前的确切位置,我注意到普通的Emacs撤消操作不会这样做。 我已经设置了Emacs来在每个话语的开始和结束时获取回调,所以我可以检测到这种情况,我只需要弄清楚Emacs会做什么。理想情况下,我会打电话给类似的东西(undo-start-collapsing),然后(undo-stop-collapsing)将介于两者之间的所有内容神奇地折叠成一张唱片。 我在文档中进行了一些检索,发现了undo-boundary这一点,但这与我想要的相反-我需要将所有动作折叠成一个撤消记录,而不是拆分。我可以undo-boundary在发声之间使用,以确保插入被认为是分开的(默认情况下,Emacs将连续插入操作视为一个达到一定限制的操作),仅此而已。 其他并发症: 我的语音识别守护程序通过模拟X11按键来向Emacs发送一些命令,并通过emacsclient -e这样的方式发送一些命令,如果有人说(undo-collapse &rest ACTIONS)我没有可以包装的地方。 我使用undo-tree,不确定是否会使事情变得更复杂。理想情况下,解决方案将与undo-treeEmacs的正常撤消行为一起使用。 如果话语中的命令之一是“撤消”或“重做”怎么办?我想我可以更改回调逻辑,以始终将它们作为独特的发音发送给Emacs,以使事情变得更简单,然后应像使用键盘一样处理它。 延伸目标:语音可能包含用于切换当前活动窗口或缓冲区的命令。在这种情况下,最好在每个缓冲区中分别说一次“撤消”,我不需要那么花哨。但是,单个缓冲区中的所有命令仍应分组,因此,如果我说“ do-x do-y do-z switch-buffer do-a do-b do-c”,则x,y,z应该是一个撤消原始缓冲区中的记录,而a,b,c应该是切换到缓冲区中的一个记录。 是否有捷径可寻?AFAICT没有内置的功能,但Emacs广阔而深刻。 更新:我最终在下面使用了jhc的解决方案并添加了一些额外的代码。在全局中,before-change-hook我检查要更改的缓冲区是否在修改了此话语的全局缓冲区列表中,如果没有,它将进入列表并被undo-collapse-begin调用。然后,在发话结束时,我迭代列表中的所有缓冲区并调用undo-collapse-end。以下代码(为函数命名而在函数名称前添加md-): (defvar md-utterance-changed-buffers nil) (defvar-local md-collapse-undo-marker nil) (defun md-undo-collapse-begin (marker) "Mark the beginning of a collapsible undo block. This must be followed with a call to undo-collapse-end with a marker …