2015-10-11 2 views
2

Я новичок в emacs. Как определить и использовать новую переменную в .dir-locals.el?Определите новую переменную в .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)))) 

ответ

2

Вы можете использовать специальное ключевое слово 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)))) 

, потому что при установке clang-args удается в setq формы, два определения переменного ниже назначить символclang-args к company-clang-arguments и flycheck-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)))))) 

Первый, по моему мнению, более читабельен, а второй, пожалуй, более удобен в обслуживании, потому что изменения значений должны быть сделаны только в одном месте.

+0

Большое вам спасибо! –

+1

В общем, будьте осторожны с тем, что вы 'setq'ing через' eval' таким образом. Если переменная уже (или автоматически) буферично-локальная, то 'setq' будет устанавливать глобальное значение (как обычно), поэтому примеры (1) и (2) не обязательно эквивалентны. Последние версии Emacs предоставляют 'setq-local' (что более удобно, чем более старый метод для установки локального значения buffer, когда переменная не является уже/автоматически так), и я был бы склонен использовать его в таких ситуациях независимо от того, для лучшей ясности. – phils

2

Хотя setq является правильной команда для установки переменных в Elisp коды .dir-locals.el представляет собой специальный файл, который требует определений переменных в определенном формате.

Чтобы использовать переменные в ваших настройках, см. this answer к соответствующему вопросу.

От GNU Emacs Manual:

Файл .dir-locals.el должен провести специально сконструированный список, который отображает основные имена режимов (символы) в alists (см Association Lists в Emacs Lisp Reference Manual). Каждая запись 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 должны применяться только в текущем каталоге, а не в каких-либо подкаталогах. Наконец, он указывает другое имя файла ChangeLog для любого файла в подкаталоге src/imported.

Вместо того, чтобы редактировать файл .dir-locals.el вручную, вы можете использовать команду M-x add-dir-local-variable. В этом запросе указывается имя режима или подкаталога, а также переменная и значение и добавляется запись, определяющая локальную переменную каталога. M-x delete-dir-local-variable удаляет запись. M-x copy-file-locals-to-dir-locals копирует файлы-локальные переменные в текущем файле в .dir-locals.el.

+0

спасибо. В моем случае, аргументы company-clang и flycheck-clang-args имеют одинаковое значение, я хочу создать для этого новую переменную, но как? –

+0

Я добавил ссылку на связанный с этим вопрос, который касается использования переменных в '.dir-locals.el'. – Thomas