【问题标题】:How can I apply a hook to multiple Emacs modes at once?如何一次将钩子应用于多个 Emacs 模式?
【发布时间】:2011-09-13 07:23:25
【问题描述】:

我正在阅读article about well-formatted Git commits,我想知道如何将一些规则应用于 Magit 日志模式。

似乎同时使用了3种主要模式:MagitLogEdit

那么,当这些模式一起使用时,我怎样才能让这些模式自动硬换行为 72 个字符?

【问题讨论】:

  • 标题具有误导性。问题的正文与标题不同。

标签: emacs elisp


【解决方案1】:

在回答最初陈述的问题时,如果您有一个函数可以添加到众多钩子变量中,您可以这样做:

(defun my-add-to-multiple-hooks (function hooks)
  (mapc (lambda (hook)
          (add-hook hook function))
        hooks))

(defun my-turn-on-auto-fill ()
  (setq fill-column 72)
  (turn-on-auto-fill))

(my-add-to-multiple-hooks
 'my-turn-on-auto-fill
 '(text-mode-hook
   magit-log-edit-mode-hook
   change-log-mode-hook))

也许不是最好的例子,但对于我希望在编程模式中启用的一些常见行为,我有类似的东西,其中还有很多要列出。

【讨论】:

    【解决方案2】:

    Emacs 模式有“基本模式”,也就是 bade 模式。例如python-mode 扩展了prog-mode,它本身扩展了fundamental-mode。所有模式都扩展fundamental-mode。所以要钩住python-mode加上c-mode而不是text-mode,你可以钩住prog-mode

    【讨论】:

      【解决方案3】:

      Emacs 缓冲区中只能有一种主要模式(除非您使用的是something like MMM or MuMaMo)。在您的情况下,一种主要模式是magit-log-edit-mode,其名称由三个单词组成(“Magit Log Edit”)。你可以添加任何你喜欢的钩子:

      (defun my-turn-on-auto-fill ()
        (setq fill-column 72)
        (turn-on-auto-fill))
      
      (add-hook 'magit-log-edit-mode-hook 'my-turn-on-auto-fill)
      

      【讨论】:

      • 完美,谢谢!作为一个切线,我对主要模式感到困惑——每个模式在点击时都会弹出一个单独的“上下文菜单”。无论哪种方式,您的解决方案都能完美运行。
      • 我强烈建议不要将lambda-expression 添加到钩子中。一个原因是,当研究它的内容时,真的很难看到一个钩子包含什么。另一个原因是,当你修改你的钩子时,新版本和每个旧版本都存在(除非你小心地删除旧版本),这可能会导致有趣的效果。
      • @Lindydancer 我完全同意,但这只是为了演示目的。反正改成单独的函数了。
      • 这并没有回答本文标题中所述的问题。
      【解决方案4】:

      一般来说,您可以定义自己的函数,比如my-common-hook,并将其添加到所有主要模式中,例如:

      (defun my-common-hook ()
         ... do stuff ...
         )
      (add-hook 'one-mode-hook 'my-common-hook)
      (add-hook 'another-mode-hook 'my-common-hook)
      (add-hook 'a-third-mode-hook 'my-common-hook)
      

      【讨论】:

        【解决方案5】:

        现在才看到这个,但这就是我所做的。最终结果是我想做以下事情: (hook-up-modes my-lisps 'standard-lisp-environment).

        为此,我定义了以下defvars。

        (defvar my-lisps  "clojure lisp emacs-lisp cider-repl")
        (defun standard-lisp-environment ()
          (paredit-mode 1)
          (rainbow-delimiters-mode 1)
          (eldoc-mode 1))
        

        我想让 lisp 将 -mode-hook 附加到我使用的 lisp 上,所以我有以下内容:

        (defun append-suffix (suffix phrases)
          "take SUFFIX and append it to each of the PHRASES."
          (mapcar #'(lambda (phrase) (concat phrase suffix)) phrases))
        

        这样 ("clojure" "lisp") => ("clojure-mode-hook" "lisp-mode-hook")。

        现在我们可以很容易地拥有这些,我们需要它们的阅读器符号,我们很容易从

        (defun symbols-from-strings (strings)
          "Given a list of strings, get their symbol values"
          (mapcar #'intern strings))
        

        最后我们得到了类似的表格:

        (defun multiple-mode-add-hook (modes hook)
          "Given a list of x-mode-hook symbols in MODE, add the HOOK to them."
          (mapc (lambda (mode) (add-hook mode hook)) modes))
        

        这些都在对它们有意义的类型上运行,字符串列表,符号列表'blah-mode-hook等。所以现在我们需要一个可以使用的面向用户的漂亮函数。

        (defun hook-up-modes (strings hook)
          (let ((modes (symbols-from-strings
                        (append-suffix "-mode-hook" (split-string strings)))))
            (multiple-mode-add-hook modes hook)))
        

        现在这应该很清晰了:我们从一个以空格分隔的字符串列表创建我们的模式,并将钩子应用于它。此外,由于我已经定义了一个标准 lisp 环境,所以我所有的 lisp 行为都相似,如果我愿意,我可以在以后轻松移除钩子。那么真正起作用的代码就是超级简单的短语 (hook-up-modes my-lisps 'standard-lisp-environment).

        【讨论】:

        • 从字符串而不是列表开始是很奇怪的。符号列表将是一个更常见的起点。在处理时,您可以使用symbol-name 来获取相当于连接的字符串。
        猜你喜欢
        • 2011-01-07
        • 2023-03-19
        • 2022-01-12
        • 2020-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-10
        相关资源
        最近更新 更多