如何在不通知的情况下修改缓冲区?


11

问:如何在不undo通知的情况下在缓冲区中插入/修改文本?

这是用例。我在每个文件的开头都有一个注释块,除其他外,它为文件的最新更改更新了时间戳。我希望能够在没有undo设施注意的情况下修改该时间戳。

我要在undo此处短路的原因是由于以下情况,这种情况在编辑/编译LaTeX文档(可能还有其他情况,但这是最常使我发疯的情况)时出现:

  1. 对文件进行一些小的更改,以查看它将如何影响已编译的文档
  2. 保存文件(更新时间戳)
  3. latex在文件上运行
  4. 确定更改是不好的
  5. undo 变化

步骤(5)(undo)的问题在于它不会撤消在步骤(1)中所做的更改,而是撤消步骤(2)中的时间戳更新。这不会打扰我(我只能undo再说一次),除了它还会一直指向文件顶部的时间戳,这几乎总是与实际的实质性更改相距很多行。这非常刺耳,完全打乱了我的注意力。

我针对正在访问的文件提出问题,但更笼统地说是关于修改缓冲区。

因此:如何避免undo注意到对缓冲区的特定修改?


1
这与您的撤消问题无关,但可能有助于解决“撤消要害”的问题:stackoverflow.com/a/20510025/1279369
nanny 2014年

2
如果将此日期戳更改附加到撤消历史记录中的最新项上,这不是最好的方法吗?这样一来undo,两者都会消失。
马拉巴巴

我认为您真正想要的是atomic-change-group

@john:那有什么帮助?分组的两个更改由单独的命令触发:“小更改”(例如,插入)和保存时完成的时间戳更新。
吉尔斯(Gillles)“所以-别再邪恶了”

请注意,由于某种原因,现有答案中的所有方法均不适用于我,但是此答案定义了一个with-undo-collapse非常有用的宏:emacs.stackexchange.com/a/7560/2418
ideaman42 '16

Answers:


6

@stsquad的答案使我走上了正确的道路。基本上,这些步骤是:

  1. buffer-undo-list
  2. 禁用 undo
  3. 做你的事
  4. 重新启用undo并还原buffer-undo-list

因此,这是此功能的示意图:

(defun disable-undo-one-off ()
  (let ((undo buffer-undo-list))        ; save the undo list
    (buffer-disable-undo)               ; disable undo
    (do-some-stuff)                     ; do your thing
    (buffer-enable-undo)                ; re-enable undo
    (setq buffer-undo-list undo)))      ; restore the undo list

编辑:实际上,事实证明,更简单的解决方案仍然是let-bind,buffer-undo-list以便在let还原原始列表时更改get 主体中的列表:

(defun disable-undo-one-off ()
  (let (buffer-undo-list)
    (do-some-stuff)))

这样做的主要局限性在于,它似乎适用于不更改缓冲区中字符数的修改(例如,将“小猫”更改为“小狗”,但不更改“猫”),因为否则将撤消其余操作列表现在指的是错误的点。因此,这仅仅是部分解决方案


您可能希望将其包装在展开保护中,以防万一您在事情进行中途中断了活动。我没有意识到您正在使用一个使跟踪内容更容易的功能来完成所有这些工作。
stsquad

您是否还可以添加时间戳更新的解决方案以不更新撤消历史记录(和点历史记录,如果可能的话)?
考沙尔·莫迪

@stsquad:好主意,稍后会尝试这样做。再次感谢您对有问题的功能和清单的提示。

@kaushalmodi:澄清问题:这意味着您想查看实际的时间戳更新功能吗?

@Dan想了解如何修改时间戳更新功能以不更新撤消或指向历史记录。
Kaushal Modi 2014年

3

撤消操作结合了撤消列表中的多个元素。nil列表中的条目标记了两个变更组之间的边界。通过删除nil由顶级循环自动插入的列表的开头¹,您可以将时间戳更新与上次缓冲区更改分组在一起,这在技术上不符合您的请求,但实际上应该可以解决您的情况。

(defun time-stamp-group-undo ()
  (if (eq nil (car buffer-undo-list))
      (setq buffer-undo-list (cdr buffer-undo-list)))
  (time-stamp))

(警告:未经测试,撤消列表可能需要更多按摩。)

您还可以通过修改时间戳记更新的位置条目(整数),以其他方式使用撤消列表。

¹ self-insert-command与组插入类似。


2

建议的问题在于,撤消树是要从您要到达的位置获取的增量的列表。尽管完全有可能在缓冲区上禁用撤消跟踪,但我不确定不主动记录更改会带来什么影响。我目前有一个切换开关可以打开/关闭特定的缓冲区,因为在不断增长的日志或刷新页面上没有撤消信息是没有意义的。但是,它忽略了切换的更改:

(defun my-toggle-buffer-undo ()
  "Toggle undo tracking in current buffer."
  (interactive)
  (with-current-buffer (current-buffer)
    (if (eq buffer-undo-list t)
        (setq buffer-undo-list nil)
      (buffer-disable-undo (current-buffer)))))

(define-key my-toggle-map "u" 'my-toggle-buffer-undo)

buffer-disable-undo实际上只是将buffer-undo-list设置nil。也许如果您在切换时保存了buffer-undo-list的状态,那么以后可以恢复它吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.