1

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 "Opzioni per eliminare la stringa commentata:
- [y] per eliminare la stringa con relativo \"newline\"
- [l] per eliminare la stringa mantenendo il \"newline\"
- [n] per mantenere la stringa commentata
- [q] per uscire da questo loop:
"))
          (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 (remove-overlays b e)))
           )
          )
          (read-string "UNWIND EXIT"))

        (read-string "NORMAL EXIT")
        )))
  )

in which the unwind cleanup-form is always evalueted, but I need it to be evaluate only when something goes wrong (e.g. a quit of the script).

Where is my mistake? I thought it shouldn't be evaluate since the body form of unwind-protect exits normally.

The loop is meant to interactively remove some kinds of commented lines in LaTeX code, letting me choose if removing also the corresponding newline.

Gabriele Nicolardi
  • 1,199
  • 8
  • 17

2 Answers2

3

This is a classic case where reading the docs gives you the answer immediately:

unwind-protect is a special form in ‘C source code’.

(unwind-protect BODYFORM UNWINDFORMS...)

Do BODYFORM, protecting with UNWINDFORMS. If BODYFORM completes normally, its value is returned after executing the UNWINDFORMS. If BODYFORM exits nonlocally, the UNWINDFORMS are executed anyway.

The name is weird, but describes that the body form is protected against stack unwinding, which happens when running into an error. unwind-protect is therefore equivalent to the finally keyword as seen in Java and alike. If you want to handle errors, use condition-case (which is like case, but for error conditions).

wasamasa
  • 21,803
  • 1
  • 65
  • 97
2

To add a bit to what @wasamasa has said -

The answer to your question is not to use unwind-protect, but instead to (1) define what you mean, in English, by "something goes wrong", then (2) define that in Lisp, in such a way that an error is raised or another signal is sent when "something goes wrong", and then (3) put your normal code inside a condition-case and define a handler for the specific error or signal that indicates "something goes wrong".

(You can define your own errors, BTW.)

Consult the Elisp manual, starting with node Signalling Errors.

Drew
  • 75,699
  • 9
  • 109
  • 225