Emacs次模式编程:取消切换程序?

时间:2015-05-15 12:52:50

标签: emacs elisp minor-mode

我使用类似于这个最小例子的习语和宏来编写我自己的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 个答案:

答案 0 :(得分:1)

如果您想取消“关闭”,而不是致电user_size - 1,则可以(foo-mode 1)

如果出于某种原因你真的想以递归方式调用(setq foo-mode t)来重新启用该模式,那么你可以通过以下方式进行:

(foo-mode 1)

答案 1 :(得分:0)

我会非常害怕阻止用户关闭次要模式。我的意思是,如果次要模式被打破或行为不端,你就会留下一个必须被杀死的破坏的Emacs。你想要的条件是什么?

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

答案 2 :(得分: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
  )