ChatGPT解决这个技术问题 Extra ChatGPT

使用 Emacs 进行“撤消”后如何“重做”更改?

This article 说“Emacs 具有重做,因为您可以在撤消时反转方向,从而撤消撤消”。

这是什么意思?用户如何使用 Emacs “重做”?

已接受答案下方的答案告诉您,如果这就是您查看此答案的原因,考虑到它的编写方式,我希望大多数人实际上都在寻找它。
我只是按了空格键,然后撤消,然后撤消空格并重做您所做的撤消操作,直到它结束,然后再次开始……我知道有更复杂的方法,但这很快而且容易,这就是我滚动的方式。
Emacs 28 现在支持此功能,请参阅:stackoverflow.com/a/60163018/432509

M
Michael Ekstrand

短版:通过撤消撤消。如果您撤消,然后执行 Cf 等非编辑命令,则下一个撤消将撤消撤消,从而导致重做。

更长的版本:

您可以将撤消视为对操作堆栈的操作。如果您在一系列撤消操作之后执行某个命令(甚至是诸如 Cf 之类的导航命令),则所有撤消操作都会被推送到操作堆栈中。所以下一个撤消撤消最后一个命令。假设您确实有一个如下所示的操作序列:

插入“foo”插入“bar”插入“我爱垃圾邮件”

现在,您撤消。它撤消最后一个操作,产生以下列表:

插入“foo” 插入“bar”

如果此时您执行除撤消以外的其他操作 - 比如说 Cf,操作堆栈将如下所示:

插入“foo”插入“bar”插入“我爱垃圾邮件”撤消插入“我爱垃圾邮件”

现在,当您撤消时,要撤消的第一件事就是撤消。导致您的原始堆栈(和文档状态):

插入“foo”插入“bar”插入“我爱垃圾邮件”

如果您执行修改命令来中断撤消序列,则该命令将添加到撤消之后,因此是之后要撤消的第一件事。假设您在“bar”上退格而不是点击 Cf。那么你会有

插入“foo” 插入“bar” 插入“我爱垃圾邮件” 撤消插入“我爱垃圾邮件” 删除“bar”

这种添加/重新添加会无限发生。这需要一点时间来适应,但它确实为 Emacs 提供了一种高度灵活且强大的撤消/重做机制。


万一这听起来很烦人,主要优点是你总是可以回到以前的状态。在大多数编辑器中,撤消几项更改然后意外键入一个字符会使您“陷入困境”,无法重做已撤消的操作。 Emacs 使这变得微不足道。
我想在你的构造中,如果一个人想在纸上做,你需要两个堆栈。因为例如,在你写“现在,你撤消”的地方。它撤消了最后一个动作,结果如下清单:“你(可以理解)没有显示撤消,如果他做了很多撤消,你不会显示它们,直到做了一些事情来破坏撤消序列,然后你会添加它们。另一种显示它的方法是有一个列表,并在它们被破坏之前将撤消添加到列表中,但要注意光标在列表中的位置,所以我们知道撤消从哪里向后工作
@barlop 迟到的回复,但至少从用户可见的角度来看,撤消仅在序列被破坏后才在堆栈上(否则,“撤消”重复只会切换最后一个操作)。这可能不是它的实现方式(例如,它可以使用某种指向队列的指针或其他东西),但我试图在这里解释用户可见的行为。
我不知道为什么这个答案甚至没有告诉你如何被接受。
可悲的是,这个答案没有说明重做命令是 Cg C-/。
p
programking

撤消:C-_

撤消后重做:Cg C-_

在 C-_ 上键入多次以重做 C-_ 已撤消的内容要多次重做 emacs 命令,执行您的命令,然后键入 C-xz,然后在 z 键上键入多次以重复该命令(当你想要的时候很有趣多次执行宏)


要重复内容,您还可以使用 C-u,例如 C-u 8 *(在插入符号所在的位置插入八个 *)。因此您可以使用 C-u x C-_ 撤消 x 个步骤。
这与原始问题无关,但在执行键盘宏(使用 C-x e)后,您可以根据需要再次执行它,只需按 e 即可。
此外,C-/C-x u 是替代的撤消键绑定,相当于 C-_。我更喜欢 C-/,因为它更容易命中。
警告:当这个答案说 C-g C-_ 将“撤消后重做”时,这只适用于您第一次点击该组合。之后,在没有 C-g 的情况下重复您的撤消键。因此,要在撤消后立即重做 3 次,请键入 C-g C-_ C-_ C-_。如果您键入 C-g C-_ C-g C-_ C-g C-_,您将绕圈子,撤消您的重做...
@RoryO'Kane我对emacs了解不多,所以请纠正我哪里错了,但是鉴于Cg C-_在重做后没有任何影响,可能是因为它只在之后运行撤消(就像您的描述“撤消后重做”所暗示的那样。所以它不是在循环重做撤消或重做等它没有做任何事情,因为撤消不仅仅是在它之前完成。所以Cg C- _ Cg C-_ 在第一个之后并没有转圈,它实际上什么都不做。
R
Rory O'Kane

撤消一次:C-/

要撤消两次:C-/ C-/

撤消后立即重做一次:Cg C-/

在撤消后立即重做两次:Cg C-/ C-/。请注意,Cg 没有重复。

要立即再次撤消,一次:Cg C-/

再次立即撤消,两次:Cg C-/ C-/

重做一遍,同样的……

如果您在上次撤消命令后按下了任何键(无论是键入字符还是只是移动光标),则无需在下一次撤消/重做之前键入 C-gC-g 只是一个安全的键,它本身什么都不做,但算作一个非撤消键,表示撤消序列的结束。按 C-f 之类的另一个命令也可以;只是它会将光标从您拥有的位置移动。

如果您无意中按了 C-g 或其他命令,而您现在以错误的方向撤消,只需按 C-g 即可再次反转您的方向。您必须一直撤消意外重做和撤消,然后才能进行所需的撤消,但如果您一直按 C-/,您最终将达到您想要的状态。事实上,如果您点击 C-g 一次然后按 C-/ 足够多次,则缓冲区曾经处于的每个状态都是可访问的。

C-/ 之外的 undo 的替代快捷方式是 C-_C-x uM-x undo

有关 Emacs 撤消系统的更多详细信息,请参阅 Emacs 手册中的 Undo


T
Trey Jackson

对于那些想要拥有更常见的撤消/重做功能的人,有人编写了 undo-tree.el。它提供了非 Emacs 撤消的外观和感觉,但提供了对撤消历史的整个“树”的访问。

我喜欢 Emacs 内置的 undo 系统,但发现这个包非常直观。

这是文件本身的评论:

Emacs 有一个强大的撤销系统。与大多数软件中的标准撤消/重做系统不同,它允许您恢复缓冲区的任何过去状态(而标准撤消/重做系统可以在您重做时立即丢失过去的状态)。然而,这种能力是有代价的:许多人发现 Emacs 的撤消系统令人困惑且难以使用,因此产生了许多包,用功能较弱但更直观的撤消/重做系统来代替它。标准撤消/重做导致的数据丢失,以及 Emacs 撤消的混乱,都源于试图将撤消历史视为更改的线性序列。它不是。这个包提供的 `undo-tree-mode' 将 Emacs 的 undo 系统替换为一个将 undo 历史视为其本质的系统:更改的分支树。这个简单的想法允许将标准撤消/重做系统的更直观的行为与永不丢失任何历史记录的功能相结合。额外的好处是在某些情况下可以更有效地存储撤消历史记录,从而允许在 Emacs 开始丢弃历史记录之前累积更多更改。


极好的!谁说 emacs undo 深不可测? :-)
惊人!概念上合理且用户直观。这应该在默认包中。一条评论:我希望在从分支点重做时也显示一些警报消息,而不仅仅是在恢复到它时。例如,当用户调用重做时:“从分支点重做”或“使用默认重做分支”——只是为了提醒用户有多个分支。
解决这个问题的另一种方法更容易实现并且不需要可视化器,只保留最后一个分支点,并提供 3 个命令:撤消、重做、切换分支。当 THE 分支被命中时,撤消/重做会发出警报,并且 switch-branch 只会在分支处切换,否则只会发出“不在分支处”消息。如果任何时候发生分支,前一个分支点就会丢失。这将以最小的复杂性相当好地解决状态丢失问题。
请注意,这在重做中有一个长期存在的错误,它可能会随机失败:github.com/syl20bnr/spacemacs/issues/9903 - 自 2014 年以来已知
@ideasman42 显然这是一个“非错误”:dr-qubit.org/Lost_undo-tree_history.html
M
Micah Elliott

当心 redoundo-tree 怪癖!

许多流行的“入门工具包”(prelude、purcell、spacemacs)都与 undo-tree 捆绑在一起。大多数(全部?)甚至自动启用它。如前所述,撤消树是可视化和遍历撤消/重做树的便捷方式。 Prelude 甚至给它一个键和弦 (uu),还有 C-x u

问题是:undo-tree 似乎破坏了 Emacs 的默认和众所周知的 redo 绑定:C-g C-/

相反,您可以使用这些对称键进行撤消/重做:

C-/     undo
C-S-/   redo

这些很有用,因为有时您想在不打开可视化工具的情况下快速重做。


这个。我正在使用 Spacemacs,但无法弄清楚为什么它对我不起作用。谢谢!
i
ideasman42

Emacs 28 adds a redo 命令(称为 undo-redo)。

如果您想要更典型的撤消/重做,可以使用以下命令。

(global-set-key (kbd "C-z") 'undo-only)
(global-set-key (kbd "C-S-z") 'undo-redo)

要访问此功能(也可以使用非线性历史记录,请参阅 undo-fu,它是内置撤消的 emacs 的精简包装器)。


m
monotux

我发现 redo.el extremly handy 用于执行“正常”撤消/重做,我通常将其绑定到 CSz 并撤消到 Cz,如下所示:

(when (require 'redo nil 'noerror)
    (global-set-key (kbd "C-S-z") 'redo))

(global-set-key (kbd "C-z") 'undo)

只需下载文件,将其放入您的 lisp-path 中,然后将上述内容粘贴到您的 .emacs 中。


redo.el 标题中的注释说它是为 XEmacs 制作的。在 GNU Emacs 和其他相关的 Emacsen 中使用它有什么问题吗?
我还没有遇到任何问题,而且我已经使用它至少 6 个月了 :)
来自 emacswiki.org/emacs/RedoMode :但是,redo.el 已过时,并且经常破坏“缓冲区”的内容,因为自 Emacs 22 以来,“原始撤消”的行为与旧版本略有不同。RedoPlus 是重做的一个分支.el 并在较新版本的 Emacs 中正常工作。您可以在此处获取 RedoPlus:emacswiki.org/emacs/redo+.el
我认为,默认情况下,这现在绑定到 M-_
i
ideasman42

默认情况下,Emacs 中的重做需要按 Cg,然后撤消。

但是,也可以使用 Emacs 内置的 undo 来实现重做命令。

undo-fu 使用 Emacs 内置的撤消功能来公开撤消和重做。

编辑,undo-fu 现在已经集成到 evil-mode 中(如果你是 evil-mode 用户)。

例子:

(use-package undo-fu)
(use-package evil
  :init
  (setq evil-undo-system 'undo-fu))

A
A.M.

Doom Emacs 用户,我希望你已经滚动到这里或者在页面上搜索了“doom”...

Doom Emacs 打破了原版 Emacs 重做快捷方式:Cg C-/ C-/ C-/ 等(或 Cg C-_ C-_ C-_ 等)...相反,它只是不断撤消。

Doom Emacs 还破坏了其他答案之一中提到的撤消树重做快捷方式,因为它对 spacemacs 等有用:SC-/ (AKA C-?) ...而是引发错误“C-? 未定义” .

你需要的是:

处于邪恶模式(Cz 切换进入和退出邪恶模式)(在邪恶模式下应该看到蓝色光标,而不是橙色光标)和

处于“命令模式”又名“正常模式”(与“插入模式”相反)(Esc 切换到命令模式)(应该看到块光标,而不是行光标),然后是

用于撤消和

重做 Cr


对于非邪恶模式用户,请查找交互功能 undo-fu-only-redo
v
vineeshvs

如果要重做上一个操作,请执行以下操作。

ESC 执行另一个撤消 (C + /)


B
Bhargav Das Gupta

在 doom emacs 中,
Ctrl + Shift + - 撤消
Alt + Shift + - 重做