Emacs 次要模式编程:取消切换程序?
Emacs minor mode programming: cancel toggle-off procedure?
我正在使用类似于这个最小示例的习惯用法和宏来编写自己的 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)
来防止模式切换通过?
我会非常害怕阻止用户关闭次要模式。我的意思是,如果次要模式坏了,或者行为不端,你就会给他们留下一个必须杀死的坏 Emacs。您考虑的条件是什么?
相反的情况——在某些情况下拒绝开启的模式——已经发生了——paredit-mode 就是一个很好的例子。它只是在 define-minor-mode 主体中抛出一个错误。
如果您想取消 "turn off",而不是调用 (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)))
我最终按照以下方式使用了 Stefan 的建议,使用变量向次要模式定义发出信号,表明由于取消禁用过程(实际上是用户查询的结果)而启用了该模式。我不敢使用简单地将模式变量设置为 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
)
我正在使用类似于这个最小示例的习惯用法和宏来编写自己的 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)
来防止模式切换通过?
我会非常害怕阻止用户关闭次要模式。我的意思是,如果次要模式坏了,或者行为不端,你就会给他们留下一个必须杀死的坏 Emacs。您考虑的条件是什么?
相反的情况——在某些情况下拒绝开启的模式——已经发生了——paredit-mode 就是一个很好的例子。它只是在 define-minor-mode 主体中抛出一个错误。
如果您想取消 "turn off",而不是调用 (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)))
我最终按照以下方式使用了 Stefan 的建议,使用变量向次要模式定义发出信号,表明由于取消禁用过程(实际上是用户查询的结果)而启用了该模式。我不敢使用简单地将模式变量设置为 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
)