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.