emacselispminor-mode

Emacs minor mode programming: cancel toggle-off procedure?


I am programming my own Emacs minor mode using the idioms and macros similar to this minimal example:

(define-minor-mode foo-mode
  "Toggle Foo mode."
  :init-value nil
  :lighter " Foo"
  :group 'foo
  (if foo-mode
      (do-enable-foo)
    (do-disable-foo))
  )

(defun do-enable-foo ()
  "Enable foo minor mode"
  (message "Enabling foo...")
  (if test-something
      (message "Foo enabled after disabling was canceled!")
    (message "Foo enabled from scratch"))
  )

(defun do-disable-foo ()
  "Disable foo minor mode"
  (message "Disabling foo...")
  (if (not certain-situation)
      (message "... done.") ; finish disabling foo
    ;; else forms:
    (message "Need to cancel disabling foo!")
    (foo-mode 1)) ; turning foo mode on again
  )

During the toggling off of the minor mode, a 'certain-situation may arise when I have to cancel toggling off. Currently, I am thinking since I am using the define-minor-mode macro, that I cannot bail out but just have to programmatically turn the mode on again using (foo-mode 1) as seen in the code.

If I go this route, I will have to handle this differently in the enabling function do-enable-foo -- so my first question is how to detect this case using the placeholder 'test-something in the code above?

Or, is there a cleaner way to achieve the cancel, for example, by signaling an error instead of (foo-mode 1) to prevent the mode toggle from going through?


Solution

  • I ended up using Stefan's suggestion in the following way using the variable to signal to the minor mode definition that the mode was enabled as a result of cancelling the disable process (actually as a result of a user query). I didn't dare to use the idea of simply setting the mode variable to t but I cannot find the documentation anymore that cautioned against it. It might be worthwhile to see if using (setq foo-mode t) actually lets me eliminate the new variable canceled-foo-off.

    (defvar canceled-foo-off nil "Set to `true' if user canceled toggling off foo.")
    (make-variable-buffer-local 'canceled-foo-off)
    
    (define-minor-mode foo-mode
      ...
      (if foo-mode
          (if canceled-foo-off
            (setq canceled-foo-off nil) ; Mode was turned back on from cancelling 
          (do-enable-foo)) ; Mode was turned on from scratch
        (do-disable-foo))
      )
    
    (defun do-disable-foo ()
      "Disable foo minor mode"
      (if (not certain-situation)
          ...
        ;; else forms:
        (setq canceled-foo-off t) ; make sure mode starting procedure is not run!
        (foo-mode 1)) ; turning foo mode on again
      )