Différents styles d'indentation pour différents projets


29

Je travaille sur de nombreux projets C différents avec des styles d'indentation uniques. Comment puis-je demander à Emacs de faire des paramètres d'indentation par projet sans polluer les arborescences de projet en amont avec des .dir-locals.elfichiers? Je veux faire correspondre les projets en utilisant leurs chemins d'accès sur le disque.


2
Que diriez-vous d'utiliser EditorConfig au lieu de .dir-locals.el. Peut-être que des collègues aimeraient cette idée?
welldan97

Réponses:


21

.dir-locals.el est ma méthode préférée lorsque cela est possible, d'autant plus qu'elle s'applique à tous les utilisateurs d'Emacs travaillant sur ce projet.

Pour les projets hostiles aux utilisateurs d'Emacs ou qui ne veulent pas de .dir-locals.elfichiers, ou si vous souhaitez avoir des préférences personnelles (sans doute pas de retrait) qui ne devraient pas s'appliquer à d'autres personnes, si vous utilisez un système de contrôle de version distribué, une option est de toujours travailler sur des branches personnelles qui ont votre .dir-locals.el. Je ne connais pas de moyen d'utiliser un DCVS qui rend cela indolore, cependant.

Une autre option consiste à ne pas archiver les .dir-locals.elfichiers. Par exemple, avec git, ajoutez-le à .git/info/exclude. C'est douloureux lorsque vous avez plusieurs extractions d'un projet, bien sûr.

Ce que j'ai fait là où .dir-locals.elil n'y avait pas d'option, c'est d'ajouter un crochet qui recherche les buffer-file-namevaleurs connues.

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

(Attention: code tapé directement dans mon navigateur car je n'ai pas accès à mon vrai code pour le moment.)


2
Ajouter .dir-locals.elà .git/info/excludesemble être une bonne option.
shosti

Quel est le problème avec l'ajout à .gitignorela racine d'un projet?
Squidly

@ Rien, mais certains projets ne veulent pas de fichiers spécifiques à l'éditeur.
Gilles 'SO- arrête d'être méchant'

Pour les utilisateurs de git, vous pouvez ajouter .dir-locals.elà votre gitignore global à ~/.config/git/ignore.
Jeremy Heiler

7

Vous ne pouvez pas convaincre des projets en amont comme llvm et linux d'enregistrer un fichier .dir-locals.el.

Une solution élaborée au problème:

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

Utilisé comme suit:

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

J'ai également une macro similaire pour les autres modes linguistiques.


6

la distribution de .dir-locals.el dans différents projets est difficile à maintenir.

Ma façon est assez simple, mettez tout le code dans un ~ / .custom.el.

Fondamentalement, le code sera exécuté dans prog-mode-hook (ou votre-quoi-major-mode-hook) et fera les choses suivantes:

  • analyser si le chemin complet du fichier contient le nom du projet spécifique
  • si la valeur est vraie, effectuez la configuration de ce projet (y compris la modification du retrait).

J'utilise cette méthode avec succès depuis un an.

Voici le code (appelez my-setup-develop-environment dans 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)

2

La façon normale de le faire est d'utiliser .dir-locals. C'est pourquoi ils ont été introduits en premier lieu. Pourquoi pas? À ma connaissance, la plupart des outils liés au projet ont tendance à conserver leurs configurations dans le répertoire racine du projet: git, svn, Eclipse et bien d'autres…

N'oubliez pas d'ajouter le fichier à .gitignoreou similaire.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.