Flycheck dengan file relatif tidak dapat dieksekusi

21

Banyak proyek yang saya kerjakan untuk menginstal eslint sebagai dependensi dev, dengan satu set kustom eslint plugins. Saat ini, flycheck menggunakan versi eslint yang terinstal secara global daripada versi eslint yang dipasang pada setiap proyek.

Saya ingin membuat flycheck point ke node_modules / eslint / bin / eslint.js sebagai gantinya. Path lengkap harus bergantung pada path file buffer saat ini sehingga saya dapat bekerja pada beberapa proyek pada saat yang sama dengan masing-masing buffer menggunakan eslint yang berpotensi berbeda yang dapat dieksekusi.

Apakah ini mungkin? Ada saran untuk bagaimana saya akan melakukan ini?

pcardune
sumber

Jawaban:

32

Anda dapat mengubah pemrograman flycheck-javascript-eslint-executable, misalnya

(defun my/use-eslint-from-node-modules ()
  (let* ((root (locate-dominating-file
                (or (buffer-file-name) default-directory)
                "node_modules"))
         (eslint
          (and root
               (expand-file-name "node_modules/.bin/eslint"
                                 root))))
    (when (and eslint (file-executable-p eslint))
      (setq-local flycheck-javascript-eslint-executable eslint))))

(add-hook 'flycheck-mode-hook #'my/use-eslint-from-node-modules)

Kode ini mencari node_modulesdirektori di induk dari direktori buffer dan mengkonfigurasi Flycheck untuk menggunakan eslint yang dapat dieksekusi dari direktori itu jika ada.

lunaryorn
sumber
Saya berharap emacs-fu saya sebagus ini. Terima kasih atas jawabannya!
pcardune
1
Jika Anda memiliki global-flycheck-mode set, maka saya sarankan (and eslint (file-executable-p eslint)) saya mengalami kesalahan jika tidak mencoba, yaitu mengedit file
.emacs
Inilah yang dapat Anda lakukan jika Anda memerlukan pengait sebaris (dan menghindari menambahkan fungsi khusus): emacs-fu.blogspot.in/2008/12/hooks.html
Shivek Khurana
catatan keamanan: hanya buka file di folder / proyek tepercaya; Anda akan otomatis mengeksekusi malicions eslint biner
maxy
2
Saya akan menggunakan path "node_modules/.bin/eslint", kalau-kalau eslint pernah mengubah struktur direktori mereka.
Cody Reichert
3

Saya tidak memiliki reputasi yang cukup untuk mengomentari solusi yang diterima. Tapi saya membuat variasi, yang berfungsi baik dengan paket bersarang (misalnya menggunakan lerna ). Ini adalah kode yang sama persis, namun mencari node_modulesfolder induk secara rekursif sampai menemukan eslintbiner, dan menggunakannya. Dengan cara ini, Anda dapat memiliki proyek lerna hanya memiliki satu konfigurasi eslint, dibagi antara semua sub-paket.

(defun my/use-eslint-from-node-modules ()
  (let ((root (locate-dominating-file
               (or (buffer-file-name) default-directory)
               (lambda (dir)
                 (let ((eslint (expand-file-name "node_modules/eslint/bin/eslint.js" dir)))
                  (and eslint (file-executable-p eslint)))))))
    (when root
      (let ((eslint (expand-file-name "node_modules/eslint/bin/eslint.js" root)))
        (setq-local flycheck-javascript-eslint-executable eslint)))))
(add-hook 'flycheck-mode-hook #'my/use-eslint-from-node-modules)
Sorein
sumber
0

Saya menggunakan windows dan ini tidak berfungsi untuk saya, saya pikir file-executable-p atau mungkin internal flycheck gagal menemukan file yang benar. Seperti ketika bekerja itu menunjuk ke .cmdfile dan bukan .jsfile.

Saya menemukan komentar di flycheck-eslint tidak menggunakan versi eslint yang diinstal dalam proyek JavaScript dan posting blog mereka untuk menggunakan variabel direktori sebagai gantinya.

Di direktori root proyek buat file .dir-locals.el

((nil . ((eval . (progn
                   (add-to-list 'exec-path (concat (locate-dominating-file default-directory ".dir-locals.el") "node_modules/.bin/")))))))

Sekarang ketika saya mengunjungi file javascript flycheck-verify-setupdengan benar menemukan file<dir>/node_modules/.bin/eslint.cmd

Bae
sumber
0

Solusi saya sebelumnya adalah menyusahkan untuk bekerja di berbagai proyek.

Saya telah memodifikasi jawaban yang diterima untuk kebodohan windows kode keras.

(defun my/use-eslint-from-node-modules ()
  (let* ((root (locate-dominating-file
                (or (buffer-file-name) default-directory)
                "node_modules"))
         (eslint (and root
                      (expand-file-name "node_modules/.bin/eslint.cmd"
                                        root))))
    (when (and eslint (file-exists-p eslint))
      (setq-local flycheck-javascript-eslint-executable eslint))))
Bae
sumber
0

Berikut adalah solusi yang menggabungkan jawaban Bae dan lunaryorn menggunakan dir-locals.elfile di direktori root proyek (atau, lebih khusus, di direktori yang berisi node_modules/folder tempat eslinttinggal biner). Buat dir-locals.elfile tersebut dengan konten berikut.

((js2-mode
   (flycheck-checker . javascript-eslint)
   (eval . (setq-local flycheck-javascript-eslint-executable
             (concat (locate-dominating-file default-directory
                       ".dir-locals.el") "node_modules/.bin/eslint")))))

Di sini saya berasumsi Anda menggunakan js2-modemode utama emacs untuk mengedit file javascript. Jika bukan itu masalahnya, ubah baris itu sesuai. Baris kedua file membuat javascript-eslintpemeriksa sintaks satu-satunya yang digunakan dalam proyek ini. Baris ketiga mengatur variabel flycheck-javascript-eslint-executablemenjadi <root-dir>/node_modules/.bin/eslint. Dengan cara ini kami tidak mengubah emacs ' exec-path.

Ricardo
sumber
0

Saya sudah mencoba beberapa variasi berbeda dan tidak pernah menemukan apa yang saya inginkan. Saya akhirnya naik level cukup di Emacs lisp untuk memodifikasinya sesuai dengan keinginan saya. Apa yang dilakukan versi saya adalah mencari eslint lokal dan jika tidak ditemukan, ia akan kembali ke yang diinstal secara global:

(defun configure-web-mode-flycheck-checkers ()
    ;; See if there is a node_modules directory
    (let* ((root (locate-dominating-file
                  (or (buffer-file-name) default-directory)
                  "node_modules"))
           (eslint (or (and root
                            ;; Try the locally installed eslint
                            (expand-file-name "node_modules/eslint/bin/eslint.js" root))

                       ;; Try the global installed eslint
                       (concat (string-trim (shell-command-to-string "npm config get prefix")) "/bin/eslint"))))

      (when (and eslint (file-executable-p eslint))
        (setq-local flycheck-javascript-eslint-executable eslint)))

    (if eslint
        (flycheck-select-checker 'javascript-eslint)))
Ricky Nelson
sumber