自动禁用特定主要模式的全局次要模式

Posted

技术标签:

【中文标题】自动禁用特定主要模式的全局次要模式【英文标题】:automatically disable a global minor mode for a specific major mode 【发布时间】:2011-10-13 19:55:14 【问题描述】:

我已在全球范围内激活了居中光标模式,如下所示:

(require 'centered-cursor-mode)
(global-centered-cursor-mode 1)

它工作正常,但有一些主要模式我想自动禁用它。例如 slime-repl 和 shell。

还有另一个问题处理相同的问题,但另一个次要模式。不幸的是,答案只为这种特定的次要模式(global-smart-tab-mode)提供了解决方法,它不适用于 centered-cursor-mode。

我试过这个钩子,但没有效果。变量没有改变。

(eval-after-load "slime"
  (progn
    (add-hook 'slime-repl-mode-hook (lambda ()
                                      (set (make-local-variable 'centered-cursor-mode) nil)))
    (slime-setup '(slime-repl slime-autodoc))))

【问题讨论】:

【参考方案1】:

使用define-globalized-minor-mode1 宏创建的全局次要模式有点棘手。您的代码似乎没有做任何事情的原因是全球化模式利用after-change-major-mode-hook 来激活它们控制的缓冲区本地次要模式;并且该钩子在主模式自己的钩子4之后立即运行

个别模式可能会实现指定某种黑名单的自定义方式或在某些情况下阻止启用该模式的其他方法,因此通常值得查看软件包的相关M-x customize-group 选项以查看如果存在此类设施。但是,目前我还没有为任何全球化的次要模式实现这一目标的一种干净的通用方法。

遗憾的是,该宏定义的 MODE-enable-in-buffers 函数没有执行与全局模式函数执行的相同的 (with-current-buffer buf (if ,global-mode ...)) 检查。如果是这样,您可以简单地使用 slime-repl-mode-hook 使全局模式变量 buffer-local 和 nil。

快速破解方法是检查2turn-on 参数对于全球化次要模式定义的含义(在本例中为 centered-cursor-mode 本身3),以及写一些周围的建议,以阻止对有问题的模式进行评估。

(defadvice centered-cursor-mode (around my-centered-cursor-mode-turn-on-maybe)
  (unless (memq major-mode
                (list 'slime-repl-mode 'shell-mode))
    ad-do-it))
(ad-activate 'centered-cursor-mode)

我们可以做的事情(使用简单的可重复使用模式)是在启用缓冲区本地次要模式后立即再次禁用它。 after-change-major-mode-hook 函数与 APPEND 参数添加到 add-hook 将在全球化次要模式起作用后可靠地运行,因此我们可以执行以下操作:

(add-hook 'term-mode-hook 'my-inhibit-global-linum-mode)

(defun my-inhibit-global-linum-mode ()
  "Counter-act `global-linum-mode'."
  (add-hook 'after-change-major-mode-hook
            (lambda () (linum-mode 0))
            :append :local))

1 或其别名define-global-minor-mode 我觉得应该避免使用,因为可能会与使用define-minor-mode 创建的“全局”次要模式混淆。 “全球化”次要模式虽然仍然涉及全局次要模式,但在实践中的工作方式非常不同,因此最好将它们称为“全球化”而不是“全局”。

2Chf define-globalized-minor-mode RET 表明turn-on 是第三个参数,我们使用 Mx find-function RET global-centered-cursor-mode RET 检查模式定义。

3 使用这种方法,这一事实将阻止您使用 slime-repl-mode 或 shell-mode 缓冲区启用此次要模式,而具有单独转折的全球化次要模式-如果您愿意,仍然可以以非全局形式调用 on 函数。

4https://***.com/a/19295380/324105

【讨论】:

【参考方案2】:

我创建了一个新的全局次要模式,在某些模式下不会被激活。 lambda 是在每个新缓冲区中调用以激活次要模式的函数。这是进行例外处理的正确位置。

(require 'centered-cursor-mode)

(define-global-minor-mode my-global-centered-cursor-mode centered-cursor-mode
  (lambda ()
    (when (not (memq major-mode
                     (list 'slime-repl-mode 'shell-mode)))
      (centered-cursor-mode))))

(my-global-centered-cursor-mode 1)

它应该适用于所有其他全局次要模式。只需复制定义 global-xxx-mode 并做出正确的例外。

【讨论】:

当你从一种主要模式切换到另一种时,它似乎不起作用

以上是关于自动禁用特定主要模式的全局次要模式的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Emacs 中的次要模式键盘映射中删除键?

前端设计模式

前端设计模式

在 Emacs 中全局覆盖键绑定

在每个文件(不是文件类型)的基础上禁用自动填充模式

设计模式:对象生成(单例工厂抽象工厂)