Diferentes estilos de indentação para diferentes projetos

29

Trabalho em muitos projetos C diferentes, com estilos únicos de recuo. Como faço para o Emacs fazer configurações de recuo por projeto sem poluir as árvores do projeto upstream com .dir-locals.elarquivos? Eu quero combinar os projetos usando seus caminhos no disco.

artagnon
fonte
2
Que tal usar o EditorConfig em vez de .dir-locals.el. Pode haver colegas de trabalho que gostariam dessa idéia?
precisa saber é o seguinte

Respostas:

21

.dir-locals.el é o meu método preferido quando é possível, especialmente se aplica a todos os usuários do Emacs que trabalham nesse projeto.

Para projetos hostis aos usuários do Emacs ou que não desejam .dir-locals.elarquivos, ou se você deseja ter preferências pessoais (presumivelmente não identações) que não se apliquem a outras pessoas, se você usar um sistema de controle de versão distribuído, uma opção é para sempre trabalhar em ramos pessoais que tenham o seu .dir-locals.el. No entanto, não sei como usar um DCVS que torne isso indolor.

Outra opção é não fazer o check-in dos .dir-locals.elarquivos. Por exemplo, com git, adicione-o a .git/info/exclude. Isso é doloroso quando você tem muitos checkouts de um projeto, é claro.

O que eu fiz onde .dir-locals.elnão havia uma opção é adicionar um gancho que compara os buffer-file-namevalores conhecidos.

(defvar guessed-project nil)
(make-variable-buffer-local 'guessed-project)
(defun guess-project-from-file-name ()
  (save-match-data
    (setq guessed-project
          (cond
           ((string-match "/linux-kernel/" buffer-file-name)
            'linux-kernel)
           ((string-match "/gnu/" buffer-file-name)
            'gnu)
           ; etc.
          ))))
(defun c-my-project-hook ()
  (guess-project-from-file-name)
  (case guessed-project
    ((gnu) (c-sty-style 'gnu))
    ((linux-kernel) (c-sty-style 'linux))
  ))
(add-hook 'c-mode-hook 'c-my-project-hook)

(Aviso: código digitado diretamente no meu navegador, pois não tenho acesso ao meu código real no momento.)

Gilles 'SO- parar de ser mau'
fonte
2
Adicionando .dir-locals.ela .git/info/excludeparece ser uma boa opção.
shosti 23/09/14
O que há de errado em adicioná-lo à .gitignoreraiz de um projeto?
Squidly 27/10/14
@ Nada, mas alguns projetos não querem arquivos específicos do editor lá.
Gilles 'SO- stop be evil'
Para usuários git, você pode adicionar .dir-locals.elao seu gitignore global em ~/.config/git/ignore.
precisa
7

Você não pode convencer projetos upstream como llvm e linux a fazer check-in em .dir-locals.el.

Uma solução elaborada para o problema:

(defmacro define-new-c-style (name derived-from style-alist match-path)
  `(progn
     (c-add-style ,name
                  '(,derived-from ,@style-alist))
     (add-hook 'c-mode-hook
               (lambda ()
                 (let ((filename (buffer-file-name)))
                   (when (and filename
                              (string-match (expand-file-name ,match-path) filename))
                     (c-set-style ,name)))))))

Utilizado da seguinte forma:

(define-new-c-style "llvm" "gnu" ((fill-column . 80)
                                  (c++-indent-level . 2)
                                  (c-offsets-alist . ((innamespace 0))))
  "~/src/llvm")

(define-new-c-style "emacs" "gnu" nil "~/src/emacs")

Eu tenho uma macro semelhante para outros modos de idioma também.

artagnon
fonte
6

É difícil manter a distribuição .dir-locals.el em diferentes projetos.

Meu jeito é bem simples, coloque todo o código em um ~ / .custom.el.

Basicamente, o código será executado no gancho no modo prog (ou no seu gancho no modo principal) e faça o seguinte:

  • analisar se o caminho completo do arquivo contém o nome do projeto específico
  • se true, faça a configuração para esse projeto (incluindo ajustar o recuo).

Uso esse método há um ano.

Aqui está o código (chame my-setup-develop-environment em prog-mode-hook):

(defun my-project-name-contains-substring (REGEX)
  (let ((dir (if (buffer-file-name)
                 (file-name-directory (buffer-file-name))
               "")))
    (string-match-p REGEX dir)))

(defun my-office-code-style ()
  (interactive)
  (message "Office code style!")
  ;; web development
  (setq coffee-tab-width 4)
  (setq javascript-indent-level 4)
  (setq js-indent-level 4)
  (setq js2-basic-offset 4)
  (setq web-mode-indent-style 4)
  (setq web-mode-markup-indent-offset 4)
  (setq web-mode-css-indent-offset 4)
  (setq web-mode-code-indent-offset 4)
  )

(defun my-personal-code-style ()
  (interactive)
  (message "My personal code style!")
  (setq coffee-tab-width 4)
  (setq javascript-indent-level 2)
  (setq js-indent-level 2)
  (setq js2-basic-offset 2)
  (setq web-mode-indent-style 2)
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-css-indent-offset 2)
  (setq web-mode-code-indent-offset 2)
  )

(defun my-setup-develop-environment ()
  (interactive)
  (cond
   ;; company's project for ttag
   ((my-project-name-contains-substring "commerical-proj1")
    (my-office-code-style))
   ((my-project-name-contains-substring "hobby-proj1")
    (my-personal-code-style))
  )
)
(add-hook 'prog-mode-hook 'my-setup-develop-environment)
Chen Bin
fonte
2

A maneira normal de fazer isso é usando .dir-locals. É por isso que eles foram introduzidos em primeiro lugar. Por que não? Que eu saiba, a maioria das ferramentas relacionadas ao projeto tendem a manter suas configurações no diretório raiz do projeto: git, svn, Eclipse e muitos outros…

Só não se esqueça de adicionar o arquivo .gitignoreou similar.

Vlad
fonte
2

Eu uso palpite-style.el .

É muito bom adivinhar o estilo de recuo preferido de um arquivo.

NateEag
fonte