Gaya lekukan yang berbeda untuk proyek yang berbeda

29

Saya mengerjakan banyak proyek C berbeda dengan gaya lekukan yang unik. Bagaimana cara saya membuat Emacs melakukan pengaturan indentasi per proyek tanpa mencemari pohon proyek hulu dengan .dir-locals.elfile? Saya ingin mencocokkan proyek menggunakan jalur mereka pada disk.

artagnon
sumber
2
Bagaimana kalau menggunakan EditorConfig alih-alih .dir-locals.el. Mungkin rekan kerja akan menyukai ide ini?
welldan97

Jawaban:

21

.dir-locals.el adalah metode pilihan saya bila memungkinkan, terutama karena ini berlaku untuk semua pengguna Emacs yang mengerjakan proyek itu.

Untuk proyek yang memusuhi pengguna Emacs atau tidak ingin .dir-locals.elfile, atau jika Anda ingin memiliki preferensi pribadi (mungkin bukan lekukan) yang seharusnya tidak berlaku untuk orang lain, jika Anda menggunakan sistem kontrol versi terdistribusi, sebuah opsi adalah untuk selalu bekerja di cabang pribadi yang Anda miliki .dir-locals.el. Saya tidak tahu cara menggunakan DCVS yang membuat ini tidak menyakitkan.

Pilihan lain adalah tidak memeriksa .dir-locals.elfile. Misalnya, dengan git, tambahkan ke .git/info/exclude. Itu menyakitkan ketika Anda memiliki banyak checkout proyek, tentu saja.

Apa yang telah saya lakukan di tempat .dir-locals.elyang bukan merupakan opsi adalah menambahkan sebuah kait yang menghadap ke buffer-file-namenilai yang diketahui.

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

(Peringatan: kode yang diketik langsung ke browser saya karena saya tidak memiliki akses ke kode asli saya saat ini.)

Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Menambahkan .dir-locals.elke .git/info/excludetampaknya seperti pilihan yang baik.
shosti
Apa yang salah dengan menambahkannya ke .gitignoredalam root proyek?
Squidly
@Tidak Ada, tetapi beberapa proyek tidak ingin file khusus editor di sana.
Gilles 'SANGAT berhenti menjadi jahat'
Untuk pengguna git, Anda dapat menambahkan .dir-locals.elke global gitignore Anda di ~/.config/git/ignore.
Jeremy Heiler
7

Anda tidak dapat meyakinkan proyek-proyek hulu seperti llvm dan linux untuk check-in a .dir-locals.el.

Solusi rumit untuk masalah ini:

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

Digunakan sebagai berikut:

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

Saya memiliki makro serupa untuk mode bahasa lainnya juga.

artagnon
sumber
6

mendistribusikan .dir-locals.el dalam berbagai proyek sulit dipertahankan.

Caraku cukup sederhana, letakkan semua kode dalam satu ~ / .custom.el.

Pada dasarnya, kode akan dijalankan di prog-mode-hook (atau your-any-major-mode-hook) dan melakukan hal-hal berikut:

  • menganalisis apakah path lengkap file memang mengandung nama proyek tertentu
  • jika benar maka lakukan pengaturan untuk proyek itu (termasuk mengubah indentasi).

Saya telah berhasil menggunakan metode ini selama satu tahun.

Berikut ini kodenya (panggil my-setup-develop-environment di 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
sumber
2

Cara normal untuk melakukannya adalah menggunakan .dir-locals. Inilah sebabnya mengapa mereka diperkenalkan di tempat pertama. Kenapa tidak? Sepengetahuan saya, sebagian besar alat yang berhubungan dengan proyek cenderung menyimpan konfigurasi mereka di direktori proyek root: git, svn, Eclipse dan banyak lainnya ...

Hanya saja, jangan lupa menambahkan file .gitignoreatau sejenisnya.

Vlad
sumber
2

Saya menggunakan guess-style.el .

Itu cukup baik menebak gaya lekukan file yang disukai

NateEag
sumber