请教怎样用 .dir-locals.el 来设置一个目录下的文件的 major mode 为 conf-mode?

大家好,我有一个存放各种配置文件的目录 myconf, 我在该目录下创建了一个 .dir-locals.el 文件试图将这个目录下所有配置文件打开的 major mode 设置为 conf-mode.

参考了一下 StackOverflow How to set default major mode in directory-local file?

我在.dir-locals.el添加了下面的代码:

 ((nil . ((mode . conf))))

也试着修改成

((nil . ((eval . (conf-mode)))))

可是上面两种方式都会出错,随意打开一个myconf 下面的文件,Emacs 都会给出下面的错误:

File local-variables error: (error Variable binding depth exceeds max-specpdl-size) [2 times]

请教一下大家应该如何解决这个问题呢? 我把上面代码中的 conf或者conf-mode改成 cc-mode是可以将 major-mode 设置成 c-mode的。是 conf-mode 这个 major-mode 比较特殊吗?

1 个赞

大概emacs把目录里的某些文件解释成了conf-mode,你又设置了解析所有文件为conf-mode,然后就死循环了。

((nil . ((eval . (progn
                   (add-to-list 'auto-mode-alist
                                (cons (regexp-quote default-directory) 'conf-mode)))))))

有个比较hack的办法

Update 又试了下,发现 M-x add-dir-local-variable 有一样的问题,所以下面的结论不成立。


add-dir-local-variable,而不是手写,以免出现格式问题:

M-x add-dir-local-variable nil mode conf

Emacs 会帮你写入

((nil (mode . conf)))

这跟你的 ((nil . ((mode . conf)))) 在一个 Lisp 表达式的角度是 equal 的,但或许当前 Emacs 版本不支持你的写法?

File Local Variable 也是如此,应该用 M-x add-file-local-variable-prop-lineadd-file-local-variable,而不是手写。

感觉是个 Bug。

从 Emacs 26.1 中开始出问题的,之前的都没问题,而 Emacs 26.1 的 NEWS 没有说明有这样的不兼容行为,如果我的猜测属实,建议提交个 Bug。

貌似的确如此,譬如 conf-mode 是一个普通函数,而不是像一般的 Major Mode 使用 define-derived-mode 定义的,我试了下 conf-unix 是 OK 的。


顺便一提 ((nil (mode . conf-unix))) 作为 Directory Local Variable 杀伤力太大,把 Dired、Helm 等都给破坏了。

1 个赞

刚刚开启了 debug-on-error ,确实是存在你说的死循环的问题。这个 hack 也可以用,谢谢!

谢谢!看了不少您的回帖,学习到了很多。如果您方便的话,请帮忙提交这个 Bug 吧。

这个我也观察到了,所以给每个配置文件的开头加上了一行 # -*- mode: conf -*- 来设置 major mode, 不折腾 .dir-locals.el 了。:joy::joy::joy:

我的头两个回帖是错的,所以应该没这个 Bug。真正的问题应该是用 conf-unix 之类的而不是 conf

没错,用nil设置mode杀伤力太大,用eval设置auto-mode-list比较好。

我想到的是在find-file-hook里面检查目录,再conf-mode,但是这样可能会在conf mode之前多加载一个文件本来对应的major mode,不如cireu的办法好。


为什么?这个解释没看懂