2

I have this loop:

(catch 'QUIT
  (while 
      (search-forward-regexp "\\([^\n\\]\\(?:\\\\\\\\\\)*\\|^\\(?:\\\\\\\\\\)+\\)%.*\n"
                 nil t)
    (save-excursion
          (let ((b (make-marker))
        (e (make-marker))
        MatchedStringOverlay
        ACTION)
        (set-marker b (match-beginning 0))
        (set-marker e (point))

        (setq MatchedStringOverlay (make-overlay b e))
        (unwind-protect 
        (progn
          (overlay-put MatchedStringOverlay 'face '(:background "OliveDrab1"))
          (setq ACTION (read-char "Options:
- [y] erase string and the corresponding \"newline\"
- [l] erase string keeping the corresponding \"newline\"
- [n] skip
- [q] quit:
"))
          (cond 
           ((char-equal ACTION ?y)
            (replace-match "\\1"))
           ((char-equal ACTION ?l)
            (replace-match "\\1\n"))
           ((char-equal ACTION ?n)
            nil)
           ((char-equal ACTION ?q)
            (throw 'QUIT nil))
           )
          )
          (remove-overlays b e))
        )))
  )

that performs some interactive replacements on buffer.

Now it happens that when I do undo after the loop, the command "undoes" all the replacements I made within the loop. How can I make each replacement a "single item" in buffer-undo-list?

I've searched in the docs, in the internet and I read the code of undo command but I've not been able to find how to get what I need.

I think I should add a nil in buffer-undo-list to mark the boundary between two change groups (see here). So I tried

(add-to-list 'buffer-undo-list nil)

just before the first cond group but it does not work.

Gabriele Nicolardi
  • 1,199
  • 8
  • 17
  • 1
    +1 for trying and succeeding to find the answer yourself. You might consider adding here how you found it - that info might help others, along with your question. – Drew Jun 23 '17 at 13:33
  • @Drew I just continued searching for related posts. Thank you. – Gabriele Nicolardi Jun 23 '17 at 15:28
  • 1
    OK; thx. Next time, you might also consider asking *Emacs*: As @phils suggested. `C-h i`, choose the Elisp manual, then `i undo TAB`. (On the web, the doc you want is [here](http://www.gnu.org/software/emacs/manual/html_node/elisp/Undo.html).) – Drew Jun 23 '17 at 17:11

1 Answers1

2

You're looking for undo-boundary:

undo-boundary is a built-in function in ‘src/undo.c’.

(undo-boundary)

Mark a boundary between units of undo.
An undo command will stop at this point,
but another undo command will undo to the previous boundary.

See also C-hig (elisp)Undo RET

phils
  • 48,657
  • 3
  • 76
  • 115