Программирование второстепенного режима 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.