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

30

我已经全局激活了光标居中模式,就像这样:

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

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

有另一个问题涉及相同的问题,但是涉及另一种次要模式。不幸的是,答案只提供了针对这个具体的次要模式(global-smart-tab-mode)的解决方法,而这种方法不适用于centered-cursor-mode。

我尝试了这个hook,但没有效果。变量没有改变。

(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))))
2个回答

21

使用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将全局模式变量设置为缓冲区本地并将其设为nil。

一个快速的hack是检查2全局化次要模式定义的turn-on参数(在本例中是centered-cursor-mode本身3),并编写一些around advice,以防止对相关模式执行该操作。

(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)

我们可以使用一个简单可重复的模式,立即在启用缓冲区局部次要模式后再次禁用它。通过使用APPEND参数添加到add-hookafter-change-major-mode-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 创建的“全局”次要模式混淆。虽然“全球化”的次要模式仍涉及到全局次要模式,但在实践中工作方式非常不同,因此最好将它们称为“全球化”,而不是“全局”。

2 C-hf define-globalized-minor-mode RET 显示 turn-on 是第三个参数,在模式定义中我们可以通过 M-x find-function RET global-centered-cursor-mode RET 进行检查。

3 采用这种方法,事实上将阻止您从slime-repl-mode或shell-mode缓冲区启用此次要模式,而具有单独 turn-on 函数的全球化次要模式仍然可以以其非全局形式调用,如果您想要这样做的话。

4 https://dev59.com/GXfZa4cB1Zd3GeqPV8zl#19295380


14

我创建了一个新的全局次要模式,并且在某些模式下不会被激活。 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 的定义并进行必要的更改。


当您从一个主要模式切换到另一个主要模式时,似乎它无法正常工作。 - xuhdev

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