2

I am writing template insert function for a file format that needs to keep header counter updated.

I'd like that undo operation removes not only in place template changes but also corresponding header update.

For example starting from:

## 2
# 1
- ...
# 2
- ...

function will insert the template:

## 3
# 1
- ...
# 2
- ...
# 3
- <here>

and C-/ (M-x undo) will return buffer state to original in one step.

Like rollback in SQL ))

UPDATE I do nothing in regard to my question and it works as I want:

(defun gaphrase-next-num ()
  (save-excursion
    (goto-char (point-min))
    (let (beg end num)
      (catch 'return
        (when (looking-at "## \\([1-9][0-9]*\\)")
          (setq beg (match-beginning 1)
                end (match-end 1))
          (setq num (string-to-int (buffer-substring beg end)))
          (delete-region beg end)
          (goto-char beg)
          (setq num (1+ num))
          (insert (int-to-string num))
          (throw 'return num))
        (insert "## 1\n")
        1))))

(defun gaphrase-insert-template ()
  (interactive)
  (forward-line 0)
  (when (looking-at "# ")
    (forward-line 1))
  (unless (re-search-forward "^# " (+ (point) 10240) t)
    (goto-char (point-max)))
  (forward-line 0)
  (while (memq (char-before) '(?\  ?\n ?\t))
    (delete-char -1))
  (insert "\n# ")
  (insert (int-to-string (gaphrase-next-num)))
  (insert "\n- \n")
  (backward-char))

but I like to state such behavior explicitly.

UPDATE 2 With a help of @Drew I checked elisp manual:

The editor command loop automatically calls ‘undo-boundary’ just before executing each key sequence, so that each undo normally undoes the effects of one command.

It looks like Emacs undo all changes at once for single interactive command. Only some special commands are treated especially, like self-insert-command because it would be boring to undo each character individually. I am not sure though if it's entire true.

1 Answer 1

2

Yes, I think you can do this. I think you need to use function undo-auto-amalgamate to tell Emacs to amalgamate (combine) operations in a single undo. It removes the previous undo-boundary.

I haven't used this, so I can't tell you more about how to use it. (And the doc in the Elisp manual for it seems pretty poor.) C-h f says this:

undo-auto-amalgamate is a compiled Lisp function in simple.el.

(undo-auto-amalgamate)

Amalgamate undo if necessary.

This function can be called before an amalgamating command. It removes the previous undo-boundary if a series of such calls have been made. By default self-insert-command and delete-char are the only amalgamating commands, although this function could be called by any command wishing to have this behavior.


I just submitted bug #35344 about the lack (I think) of helpful doc for this function (or more generally, about how to group undo segments into larger chunks).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.