某个目录可以为其下所有文件指定通用的局部变量值;Emacs 会利用这些值, 在访问该目录下任意文件的缓冲区中,为这些变量创建缓冲区局部绑定 (buffer-local bindings)。当目录中的文件归属于某个 项目(project)、因此需要共享相同的局部变量时,这一功能非常实用。
指定目录局部变量有两种不同方法:一是将其写入一个特殊文件, 二是为该目录定义一个项目类(project class)。
该常量定义了 Emacs 用于查找目录局部变量的文件名。 此文件的默认名称为 .dir-locals.el12。若某个目录下存在该名称的文件,Emacs 会将其中的配置应用到 该目录及其所有子目录下的任意文件(你也可以选择排除子目录,详见下文)。 如果部分子目录自身也包含 .dir-locals.el 文件,Emacs 会从当前文件所在目录开始, 向上遍历目录树,采用找到的最深层文件中的配置。 该常量也用于派生第二个目录局部变量文件 .dir-locals-2.el 的名称。 若此第二个文件与 .dir-locals.el 位于同一目录, 则 Emacs 会在加载 .dir-locals.el 的同时加载该文件。 这一机制的实用场景是:当 .dir-locals.el 被纳入共享代码仓库的版本控制、 无法用于个人自定义配置时,可通过第二个文件实现个性化设置。 该文件以特殊格式的列表指定局部变量;更多细节可参见 按目录配置的局部变量 in GNU Emacs 手册。
该函数会读取 .dir-locals.el 文件,并将目录局部变量存储到
访问该目录下任意文件的缓冲区所专属的 file-local-variables-alist 中,
但 不会 立即应用这些变量。它还会将目录局部配置存储到
dir-locals-class-alist 中,并在该列表里为找到 .dir-locals.el 文件
的目录定义一个特殊的类。此函数的实现逻辑是调用下文所述的
dir-locals-set-class-variables 和 dir-locals-set-directory-class
两个函数。
该函数会查找目录局部变量,并立即将其应用到当前缓冲区中。
它设计用于在非文件缓冲区(如 Dired 缓冲区)的模式命令中调用,
使这类缓冲区也能遵循目录局部变量的配置。对于非文件缓冲区,
Emacs 会在 default-directory(默认目录)及其上级目录中
查找目录局部变量。
该函数为指定的 class(一个符号)定义一组变量配置。你可在后续将该类
分配给一个或多个目录,Emacs 会将这些变量配置应用到这些目录下的所有文件。
variables 中的列表可以是以下两种形式之一:(major-mode . alist)
或 (directory . list)。
对于第一种形式:若文件对应的缓冲区启用了从 major-mode 派生的模式,
则关联的 alist 中的所有变量都会被应用;alist 应采用
(name . value) 的格式。当 major-mode 取特殊值
nil 时,表示这些配置适用于任意模式。在 alist 中,你可使用一个
特殊的 name:subdirs。若其关联值为 nil,则该关联列表仅
应用于对应目录下的文件,而不作用于其子目录中的文件。
对于 variables 的第二种形式:若 directory 是文件所在目录的 初始子串,则会按照上述规则递归应用 list;list 应符合该函数 对 variables 所接受的两种形式之一。
该函数将 class(类)分配给 directory(目录)及其所有子目录下的所有文件。
此后,为 class 指定的所有变量配置都会应用到 directory 及其子目录下
被访问的任意文件。class 必须已通过 dir-locals-set-class-variables
函数完成定义。
Emacs 从 .dir-locals.el 文件加载目录变量时,会在内部调用此函数。
这种情况下,可选参数 mtime 存储的是文件修改时间(由 file-attributes
函数返回)。Emacs 会通过该时间检查已存储的局部变量是否仍有效。
若你是直接分配类(而非通过文件),则该参数应设为 nil。
该关联列表(alist)存储类符号及其对应的变量配置。
它会由 dir-locals-set-class-variables 函数更新。
该关联列表(alist)存储目录名称、其分配的类名,以及对应的目录局部变量文件的
修改时间(若存在该文件)。dir-locals-set-directory-class 函数会更新此列表。
该缓冲区局部变量存储目录局部变量配置的关联列表(alist)。
该关联列表的每个元素格式为 (var . value),其中 var 是
局部变量的符号,value 是其对应值(此结构与 file-local-variables-alist
完全一致,see 文件局部变量)。当 Emacs 访问文件时,
会将所有目录局部变量收集到该列表中,随后 hack-local-variables 函数会逐个
应用这些变量(相关细节同样可参见 文件局部变量)。
这个特殊钩子(hook)存储的函数用于为指定缓冲区收集待使用的目录局部变量。 默认情况下,该钩子仅包含一个函数,即遵循本节所述其他配置规则的函数。 但可通过该钩子扩展对更多目录局部变量来源的支持,例如适配其他文本编辑器 所使用的目录局部变量机制。
该钩子上的函数会在以下时机被调用:无参数调用,且执行上下文为待应用目录局部变量
的目标缓冲区;调用时机为缓冲区的主模式(major-mode)函数运行完毕后。
因此这些函数可借助 major-mode(主模式)或 buffer-file-name(缓冲区文件名)
等信息来源,确定应应用的变量。
它应返回一个格式为 (directory . alist) 的点对单元(cons cell),
或一组此类点对单元组成的列表。返回值为 nil 表示未找到任何目录局部变量。
directory 应为字符串类型:即这些变量所适用的目录名称。
alist 是适用于当前缓冲区的变量及其值的列表,其中每个元素的格式均为
(varname . value)。
这些函数返回的多个 alist 会被合并;若出现配置冲突,目录层级中 更深层目录的配置优先级高于更上层目录的配置。最后需要注意的是, 由于该钩子会在每次访问文件时运行,务必保证这些函数的执行效率, 这通常需要借助某种缓存机制来实现。