Emacs shell脚本模式钩子

7
由于某些原因,我的Shell脚本模式钩子不起作用。例如,在我的.emacs文件中:
``` (add-hook 'shell-script-mode-hook (lambda () (rainbow-delimiters-mode 1))) ```
可以设置变量,但是不能为打开的脚本文件加载模式。这里有什么正确的钩子方法?
我使用默认的Shell脚本模式(modeline显示例如`Shell-script[bash]`)。我需要为每个Shell类型(sh、bash、zsh)单独钩住吗?如果是,请告诉我如何操作。
谢谢!
编辑3: 问题出在textmate-mode与sh-mode中的skeleton-pair-insert冲突(我尝试通过在sh-mode中禁用textmate来避免冲突,但这让sh-mood-hook陷入了混乱。我已彻底删除了textmate-mode,并现在在全局使用标准的skeleton-pair方法。
我将接受phils的答案 - 没有他,我可能无法自行调试出这个问题。
编辑2: 感谢phils,我认为他的评论让我们更接近解决方案。虽然这不是rainbow-delimiters的问题。我删除了除了你的hello消息之外的所有sh-mode-hook,并重新启动了Emacs。当我打开.sh文件时,我得到这个:
``` Setting up indent for shell type bash setting up indent stuff Indentation variables are now local. Indentation setup for shell type bash File mode specification error: (void-function nil) ```
请注意,没有“hello”消息。 sh-mode-hook的值为:
``` (nil (lambda nil (message "hello"))) ```
我认为问题出在第一个nil值上,尽管我不见得它会在任何地方设置。
如果我评估这个:
``` (setq sh-mode-hook t) (add-hook 'sh-mode-hook (lambda () (message "hello"))) ```
我看到了hello消息,但是重新启动之后(我将这些行放在.emacs中),它又消失了(nil再次在钩子的顶部)。
有什么办法让设置时处于活动状态的钩子吗?
编辑1: 我也尝试了以下操作:
``` (add-hook 'sh-mode-hook (lambda () (rainbow-delimiters-mode 1))) ```
结果相同,但不确定是否相关...
2个回答

14

shell-script-modesh-mode 的别名。我没有进行过确认,但我认为只有“真正”的函数名称的钩子变量被评估,所以我认为应该使用 sh-mode-hook

无论如何,你的语法没有问题,所以可能是 (rainbow-delimiters-mode 1) 的使用有问题。例如,你应该能够观察到以下代码可以正确地工作:

(add-hook 'sh-mode-hook (lambda () (message "hello")))

顺便说一下,对于钩子函数,我建议根本不要使用匿名函数,因为如果钩子函数有名称,更新它将会更容易(在变量中删除旧的 lambda 表达式,然后添加一个更新后的表达式只是令人讨厌而已)。


谢谢,这有助于缩小问题范围。如果您有时间,请查看原始问题的EDIT2,因为它变得很长。如果我们找到解决方案,我会尽力整理事情以备后用。 - user673592
也许你可以使用 M-x rgrep 命令在 .el 文件中搜索 sh-mode-hook,看看是否有其他东西正在干扰它。听起来好像在你的 add-hook 之后,还有其他东西执行了类似于 (add-hook 'sh-mode-hook nil) 的操作。 - phils
顺便提一下,我对您使用的(setq sh-mode-hook t)而不是(setq sh-mode-hook nil)感到困惑。它似乎没有引起问题,但它的作用是什么? - phils
我已经在整个配置文件中注释掉了所有的sh-mode-hook(除了hello消息)。然而,我刚刚意识到AutoComplete和yasnippets被加载到了sh-mode中 - 也许它们会破坏hook... (setq sh-mode-hook t)只是在注意到nil值后我尝试的一些绝望的方法。 - user673592
在Emacs Lisp中,nil() 是相同的东西,因此(setq sh-mode-hook nil)将变量设置为空列表(而不是包含值nil的列表,这就是你看到的)。我很惊讶add-hook可以在具有值t(即不是列表)的变量上工作,但我看到它可以愉快地创建一个列表。 - phils
好的,结果是一个 TextMate 冲突。感谢您的支持,我通过这种方式学到了关于 elisp 的重要知识。如果有人曾经遇到类似的问题,我已经更新了问题并提供了最终解决方案。 - user673592

-1
尝试移除“:”。
(add-hook 'shell-script-mode-hook (lambda () (rainbow-delimiters-mode 1)))

不幸的是,这并没有帮助...相同的结构适用于python-mode-hook等。 - user673592
1
两种形式都可以使用。唯一的区别在于'(lambda)表达式将不会被编译。(lambda)实际上是自引用的,而且(现在)等同于(function (lambda)),因此通常最好不要对lambda表达式进行引用。 - phils

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