0

Can the evaluation of code snippets be undone in emacs? Or do I have to restart without having the code sitting in init.el to bring the system back to its previous state?


I tried out this code with M-x eval-region.

(define-minor-mode org-numbers-overlay-mode
  "Add overlays to org headings which number them"
  nil " *1." nil


  (let ((hooks '(after-save-hook
                 org-insert-heading-hook))
        (funcs '(org-promote
                 org-cycle-level
                 org-promote-subtree
                 org-demote
                 org-demote-subtree
                 org-move-subtree-up
                 org-move-subtree-down
                 org-move-item-down
                 org-move-item-up
                 org-move)))
      (if org-numbers-overlay-mode
       (progn
         (org-numbers-overlay-update)
         (dolist (fn funcs)
           (advice-add fn :after #'org-numbers-overlay-update))
         (dolist (hook hooks)
           (add-hook hook #'org-numbers-overlay-update)))

     (progn
       (dolist (fn funcs)
         (advice-add fn :after #'org-numbers-overlay-update))
       (dolist (hook hooks)
         (remove-hook hook #'org-numbers-overlay-update))

       (loop for o in (overlays-in (point-min) (point-max))
             if (eq (overlay-get o 'type) 'org-number)
             do (delete-overlay o))))))

(defun org-numbers-overlay-update (&rest args)
  (interactive)

  (when org-numbers-overlaymode
        (let ((levels (make-vector 10 0)))
          (save-excursion
            (widen)
            (goto-char (point-min))
            (while (outline-next-heading)
              (let* ((detail (org-heading-components))
                     (level (- (car detail) 1))
                     (lcounter (1+ (aref levels level)))
                     (o (or (loop for o in (overlays-in (point)
                                                        (save-excursion (end-of-line) (point)))
                                  if (eq (overlay-get o 'type) 'org-number)
                                  return o)
                            (make-overlay (point) (+ (point) (car detail))))))
                (aset levels level lcounter)
                (loop for i from (1+ level) to 9
                      do (aset levels i 0))
                (overlay-put o 'type 'org-number)
                (overlay-put o 'evaporate t)
                (overlay-put o 'after-string
                             (let (s)
                               (loop for i across levels
                                     until (zerop i)
                                     do (setf s (if s (format "%s.%d" s i)
                                                  (format " %d" i))
                                              ))
                               s))))))))

And it ended up breaking the TAB to fold headline function in org-mode. So I needed to undo the evaluation of the code. I did a restart to revert the changes, but having to restart every time a problematic code is evaluated seems to be quite a hassle.

Sati
  • 775
  • 6
  • 23
  • The question is unclear. Could you please elaborate? Thx. – Drew Jul 18 '19 at 02:02
  • 3
    Instead of trying things out in your main emacs instance, start another one to experiment with. If it works, save the code; if not, kill the experimental instance. If you start the experimental instance with just a small init file that sets up a minimal environment, it is quite fast. But most importantly, you don't lose your main emacs instance if things go south. As for the question, AFAIK it's not possible in general to undo evaluation: you might be able to undo it (laboriously) in simple cases, but IMO it's just not worth it. – NickD Jul 18 '19 at 02:51
  • 2
    It's a bit like giving someone a collection of wooden blocks, paint, and dynamite, and asking whether you can "undo" anything which they might happen to do with those things. You might be able to put things back they way they were before (or in an equivalent state), but it very much depends on what they actually did. – phils Jul 18 '19 at 21:37
  • 1
    I strongly suspect the author of that code intended to use advice-remove when the minor mode is being disabled. As it is, they have repeated the advice-add again. – phils Jul 18 '19 at 21:41

1 Answers1

1

No, there's no automatic undo of the changes made by a running script. If you don't want to restart then you can remove the advice and hooks that you added but restarting is probably easier.

db48x
  • 17,977
  • 1
  • 22
  • 28