【问题标题】:Define new variable in .dir-locals.el在 .dir-locals.el 中定义新变量
【发布时间】:2019-03-07 14:10:28
【问题描述】:

我是 emacs 的新手。如何在 .dir-locals.el 中定义和使用新变量?

这是我的 .dir-locals.el,但它不起作用。

(setq clang_args '("-isystem/usr/include/glib-2.0"
                   "-isystem/usr/lib/glib-2.0/include"))
((c-mode . ((company-clang-arguments . clang_args)
            (flycheck-clang-args . clang_args))))

这行得通

((c-mode . ((company-clang-arguments . ("-isystem/usr/include/glib-2.0"
                                        "-isystem/usr/lib/glib-2.0/include"))
            (flycheck-clang-args . ("-isystem/usr/include/glib-2.0"
                                    "-isystem/usr/lib/glib-2.0/include")))))

根据How do I set buffer local variable from Eval: in .dir-local.el?的例子,我尝试了其他方法,但都失败了。

((c-mode . ((eval . (setq company-clang-arguments ("-isystem/usr/include/glib-2.0"
                                                   "-isystem/usr/lib/glib-2.0/include"))
            (eval . (setq flycheck-clang-args ("-isystem/usr/include/glib-2.0"
                                               "-isystem/usr/lib/glib-2.0/include"))))))

((c-mode . ((eval . (setq clang_args ("-isystem/usr/include/glib-2.0"
                                      "-isystem/usr/lib/glib-2.0/include"))
            (company-clang-arguments . clang_args)
            (flycheck-clang-args . clang_args))))

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    您可以使用特殊关键字 eval 执行任意 lisp 代码,例如定义临时变量。但是,您不能在随后的 alist 样式变量声明中使用该变量。也就是说,以下内容不起作用:

    ((c-mode . ((eval . (setq clang-args ("-isystem/usr/include/glib-2.0"
                                          "-isystem/usr/lib/glib-2.0/include"))
                (company-clang-arguments . clang-args)
                (flycheck-clang-args . clang-args))))
    

    因为在setq 形式中设置clang-args 成功时,下面的两个变量定义将符号 clang-args 分别分配给company-clang-argumentsflycheck-clang-args,而不是变量 clang-args 之前定义的。 不过,有两个选项确实有效:

    1) 两次使用相同的字符串字面量:

    ((c-mode . ((company-clang-arguments . ("-isystem/usr/include/glib-2.0"
                                            "-isystem/usr/lib/glib-2.0/include"))
                (flycheck-clang-args . ("-isystem/usr/include/glib-2.0"
                                        "-isystem/usr/lib/glib-2.0/include")))))
    

    2) 在eval 表单内进行实际的变量赋值:

    ((c-mode . ((eval . (let ((clang-args '("-isystem/usr/include/glib-2.0"
                                            "-isystem/usr/lib/glib-2.0/include")))
                          (setq company-clang-arguments clang-args
                                flycheck-clang-args clang-args))))))
    

    在我看来,第一个更具可读性,而第二个可能更易于维护,因为只需在一个位置更改值即可。


    附录:注意下面phils 的评论:他的建议是在第二个选项中将set 替换为setq-local。这将导致以下结果:

    ((c-mode . ((eval . (let ((clang-args '("-isystem/usr/include/glib-2.0"
                                            "-isystem/usr/lib/glib-2.0/include")))
                          (setq-local company-clang-arguments clang-args
                                      flycheck-clang-args clang-args))))))
    

    【讨论】:

    • 通常以这种方式通过eval 警惕您setqing 的内容。除非变量已经(或自动)是缓冲区局部变量,否则setq 将设置全局值(正常),因此示例 (1) 和 (2) 不一定等效。最新版本的 Emacs 提供了setq-local(当变量尚未/自动如此时,这比设置缓冲区本地值的旧方法更方便),我倾向于在这种情况下使用它,为了更好清晰度。
    【解决方案2】:

    setq 是在 elisp 代码中设置变量的正确命令,.dir-locals.el 是一个特殊文件,需要以特定格式定义变量。

    要在您的设置中使用变量,请参阅this answer 的相关问题。

    来自GNU Emacs Manual

    .dir-locals.el 文件应该包含一个特殊构造的列表,它将主要模式名称(符号)映射到 alist(请参阅 Emacs Lisp 参考手册中的Association Lists)。当启用指定的主要模式时,每个 alist 条目都包含一个变量名称和分配给该变量的目录本地值。可以指定nil,而不是模式名称,这意味着alist适用于任何模式;或者您可以指定子目录名称(字符串),在这种情况下,alist 将应用于该子目录中的所有文件。

    这是.dir-locals.el 文件的示例:

    ((nil . ((indent-tabs-mode . t)
             (fill-column . 80)))
     (c-mode . ((c-file-style . "BSD")
                (subdirs . nil)))
     ("src/imported"
      . ((nil . ((change-log-default-name
                  . "ChangeLog.local"))))))
    

    这将为目录树中的任何文件设置indent-tabs-mode 和填充列,并为任何 C 源文件设置缩进样式。特殊的 subdirs 元素不是变量,而是一个特殊的关键字,表示 C 模式设置仅适用于当前目录,而不适用于任何子目录。最后,它为 src/imported 子目录中的任何文件指定不同的 ChangeLog 文件名。

    您可以使用命令M-x add-dir-local-variable,而不是手动编辑.dir-locals.el 文件。这会提示输入模式或子目录名称、变量和值,并添加定义本地目录变量的条目。 M-x delete-dir-local-variable 删除一个条目。 M-x copy-file-locals-to-dir-locals 将当前文件中的文件局部变量复制到.dir-locals.el中。

    【讨论】:

    • 谢谢。就我而言,company-clang-arguments 和 flycheck-clang-args 具有相同的值,我想为此创建一个新变量,但是如何?
    • 我添加了一个相关问题的链接,该问题涉及在.dir-locals.el 中使用变量。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 2019-05-27
    • 1970-01-01
    • 2017-04-15
    • 1970-01-01
    相关资源
    最近更新 更多