Программирование второстепенного режима Emacs: отменить процедуру выключения?

Я программирую свой собственный второстепенный режим Emacs, используя идиомы и макросы, подобные этому минимальному примеру:

(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
  )

Во время выключения второстепенного режима, 'certain-situation может возникнуть, когда мне придется отменить выключение. В настоящее время я думаю, так как я использую define-minor-mode макрос, который я не могу выручить, но просто должен программно включить режим снова, используя (foo-mode 1) как видно из кода.

Если я пойду по этому пути, мне придется по-другому с этим справиться do-enable-foo - поэтому мой первый вопрос - как обнаружить этот случай, используя заполнитель 'test-something в коде выше?

Или есть более чистый способ добиться отмены, например, сигнализируя об ошибке вместо (foo-mode 1) предотвратить переключение режима?

3 ответа

Решение

Я закончил тем, что использовал предложение Стефана следующим образом, используя переменную, чтобы сигнализировать второстепенному определению режима, что режим был включен в результате отмены процесса отключения (фактически в результате пользовательского запроса). Я не осмелился использовать идею простой установки переменной режима в t но я больше не могу найти документацию, которая предупреждает об этом. Возможно, стоит посмотреть, используете ли (setq foo-mode t) на самом деле позволяет мне устранить новую переменную 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
  )

Если вы хотите отменить "выключить", а не позвонить (foo-mode 1)можно просто (setq foo-mode t),

Если по какой-то причине вы действительно хотите позвонить (foo-mode 1) рекурсивно (повторно) включить режим, затем вы можете сделать это следующим образом:

(defvar foo-mode--reenabling nil)
....
(defun do-enable-foo ()
  (if foo-mode--reenabling
      ...
    ...))
...
(defun do-disable-foo ()
  ...
  (let ((foo-mode--reenabling t))
    (foo-mode 1)))

Я был бы очень напуган тем, чтобы запретить пользователю отключать второстепенный режим. Я имею в виду, что если второстепенный режим нарушен или ведет себя плохо, вы оставляете их со сломанным Emacs, который должен быть убит. В каком состоянии вы размышляете?

Противоположная ситуация - режим, который не включается при определенных обстоятельствах, - уже случается - хороший пример - режим paredit. Он просто выдает ошибку в теле define-minor-mode.

Другие вопросы по тегам