Emacs次要模式编程:如何取消切换关闭程序?

3
我正在编写自己的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
  )

在关闭次要模式时,可能会出现“某种情况”,导致我必须取消切换。目前,我认为由于我正在使用define-minor-mode宏,所以我不能退出,只能在代码中再次编程打开模式,如 (foo-mode 1)。
如果我选择这个方法,我将不得不在启用函数do-enable-foo中以不同的方式处理这个问题 - 所以我的第一个问题是如何使用上述代码中的占位符'test-something'检测这种情况?
或者,是否有更简洁的方法来实现取消,例如通过发出错误信号而不是(foo-mode 1)来防止模式切换进行?
3个回答

2
如果你想要取消“关闭”而不是调用 (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)))

我对变量的想法进行了一些变化,并在下面发表了它。 - Linda

0

我会非常担心阻止用户关闭一个次要模式。我的意思是,如果这个次要模式出现故障或者不正常行为,你就让他们使用有问题的Emacs,只能通过强制关闭才能解决。你考虑到了哪些情况呢?

相反的情况——在某些情况下拒绝启用一个模式——已经发生过了——paredit-mode是一个很好的例子。它在define-minor-mode的主体中抛出错误。


这是一个好建议,但它并不是问题的答案。请将其移动到评论中。 - Chris

0

我最终采用了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
  )

1
为什么你想要使用 setq 而不是 let - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接