Różne style wcięć dla różnych projektów

29

Pracuję nad wieloma różnymi projektami C z unikalnymi stylami wcięć. Jak zmusić Emacsa do wprowadzenia ustawień wcięcia dla poszczególnych projektów bez zanieczyszczania .dir-locals.elplików projektu wcześniejszymi plikami? Chcę dopasować projekty przy użyciu ich ścieżek na dysku.

artagnon
źródło
2
Co powiesz na użycie EditorConfig zamiast .dir-locals.el. Może współpracownicy chcieliby ten pomysł?
welldan97

Odpowiedzi:

21

.dir-locals.el jest moją preferowaną metodą, gdy jest to możliwe, zwłaszcza, że ​​dotyczy wszystkich użytkowników Emacsa pracujących nad tym projektem.

W przypadku projektów, które są wrogie dla użytkowników Emacsa lub w inny sposób nie chcą .dir-locals.elplików, lub jeśli chcesz mieć osobiste preferencje (prawdopodobnie nie wcięcia), które nie powinny mieć zastosowania do innych osób, jeśli używasz rozproszonego systemu kontroli wersji, opcja jest aby zawsze pracować na osobistych oddziałach, które mają twoje .dir-locals.el. Jednak nie znam sposobu na użycie DCVS, który sprawia, że ​​jest to bezbolesne.

Inną opcją jest nie rejestrowanie .dir-locals.elplików. Na przykład za pomocą git dodaj go do .git/info/exclude. Oczywiście jest to bolesne, gdy masz wiele realizacji projektu.

To, co zrobiłem tam, gdzie .dir-locals.elnie było opcji, to dodanie haka, który sprawdza buffer-file-nameznane wartości.

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

(Ostrzeżenie: kod wpisany bezpośrednio w mojej przeglądarce, ponieważ nie mam teraz dostępu do mojego prawdziwego kodu).

Gilles „SO- przestań być zły”
źródło
2
Dodanie .dir-locals.eldo .git/info/excludewydaje się dobrą opcją.
shosti
Co jest złego w dodawaniu go do .gitignorekatalogu głównego projektu?
Squidly
@ Nic, ale niektóre projekty nie chcą tam plików specyficznych dla edytora.
Gilles „SO- przestań być zły”
Dla użytkowników git możesz dodać .dir-locals.eldo swojego globalnego gitignore na stronie ~/.config/git/ignore.
Jeremy Heiler
7

Nie możesz przekonać projektów typu upstream, takich jak llvm i linux, do sprawdzenia w .dir-locals.el.

Opracowane rozwiązanie problemu:

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

Używany w następujący sposób:

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

Mam podobne makro dla innych trybów językowych.

artagnon
źródło
6

rozpowszechnianie .dir-locals.el w różnych projektach jest trudne do utrzymania.

Moja droga jest dość prosta, umieść cały kod w jednym ~ / .custom.el.

Zasadniczo kod będzie uruchamiany w trybie przechwytującym prog-mode (lub w trybie przechwytującym dowolny tryb główny) i wykonuje następujące czynności:

  • przeanalizować, czy pełna ścieżka do pliku zawiera konkretną nazwę projektu
  • jeśli to prawda, wykonaj konfigurację tego projektu (w tym poprawienie wcięcia).

Od roku z powodzeniem stosuję tę metodę.

Oto kod (wywołaj my-setup-develop-environment w 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
źródło
2

Normalnym sposobem na to jest użycie .dir-locals. Właśnie dlatego zostały wprowadzone w pierwszej kolejności. Dlaczego nie? O ile mi wiadomo, większość narzędzi związanych z projektami zazwyczaj utrzymuje swoje konfiguracje w głównym katalogu projektu: git, svn, Eclipse i wiele innych…

Po prostu nie zapomnij dodać pliku .gitignorelub podobnego.

Vlad
źródło
2

Używam guess-style.el .

Radzi sobie dobrze z odgadnięciem preferowanego stylu wcięcia pliku.

NateEag
źródło