Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define new variable in .dir-locals.el

Tags:

emacs

elisp

I am new to emacs. How do I define and use new variable in .dir-locals.el?

This is my .dir-locals.el and it didn't work.

(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))))

This works

((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")))))

According to the examples from How do I set buffer local variable from Eval: in .dir-local.el?, I tried other methods but fail.

((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"))))))

and

((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))))
like image 428
Trịnh Anh Ngọc Avatar asked Oct 11 '15 08:10

Trịnh Anh Ngọc


1 Answers

You can use the special keyword eval to execute arbitrary lisp code, such as e.g., defining a temporary variable. However, you then cannot use that variable in subsequent alist-style variable declarations. That is, the following doesn't work:

((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))))

because while setting clang-args succeeds in the setq form, the two variable definitions below assign the symbol clang-args to company-clang-arguments and flycheck-clang-args respectively, not the value of the variable clang-args previously defined. There are two options that do work, though:

1) Using the same string literals twice:

((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) Doing the actual variable assignment also inside the eval form:

((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))))))

The first one is more readable in my opinion while the second one is perhaps more maintainable because changes to the values only have to be made in one location.


Addendum: note the comment below by phils: his suggestion is to replace set with setq-local in the second option. This would result in the following:

((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))))))
like image 85
Thomas Avatar answered Sep 22 '22 00:09

Thomas