Flycheck com o arquivo relativo eslint executável

21

Muitos projetos em que trabalho instalam o eslint como uma dependência de desenvolvedor, com um conjunto personalizado de plugins eslint. No momento, o flycheck usa a versão do eslint instalada globalmente, em vez da versão do eslint instalada em cada projeto.

Gostaria de fazer o flycheck apontar para node_modules / eslint / bin / eslint.js. O caminho completo deve depender do caminho do arquivo do buffer atual, para que eu possa trabalhar em vários projetos ao mesmo tempo com cada buffer usando um executável eslint potencialmente diferente.

Isso é possível? Alguma sugestão de como eu faria isso?

pcardune
fonte

Respostas:

32

Você pode alterar programaticamente flycheck-javascript-eslint-executable, por exemplo

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

Esse código procura um node_modulesdiretório em qualquer pai do diretório do buffer e configura o Flycheck para usar um executável eslint desse diretório, se houver algum.

lunaryorn
fonte
Eu gostaria que meu emacs-fu fosse tão bom. Obrigado pela resposta!
Pcardune
1
Se você tiver set-flycheck de modo global, então eu recomendo (and eslint (file-executable-p eslint)) que eu estava encontrando erros de outra forma tentando, ou seja, editar meu .emacs arquivo
Jason Dufair
Aqui está o que você pode fazer se você precisa de um gancho inline (e evitar a adição de funções personalizadas): emacs-fu.blogspot.in/2008/12/hooks.html
Shivek Khurana
nota de segurança: abra somente arquivos em pastas / projetos confiáveis; você executará automaticamente qualquer binário de malicions eslint
maxy
2
Eu usaria o caminho "node_modules/.bin/eslint", para o caso de o eslint mudar sua estrutura de diretórios.
Cody Reichert
3

Não tenho reputação suficiente para comentar sobre a solução aceita. Mas fiz uma variação, que funciona bem com pacotes aninhados (por exemplo, usando lerna ). Esse é exatamente o mesmo código, no entanto, ele pesquisa a node_modulespasta pai recursivamente até encontrar um eslintbinário e o usa. Dessa forma, você pode ter um projeto lerna com apenas uma configuração eslint, compartilhada entre todos os subpacotes.

(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)
Soreine
fonte
0

Estou no Windows e isso não estava funcionando para mim, acho que o arquivo executável-p ou talvez os internos do flycheck não conseguiram localizar o arquivo correto. Como quando está funcionando, está apontando para o .cmdarquivo e não para o .jsarquivo.

Eu encontrei um comentário no flycheck-eslint não usa a versão do eslint instalada no projeto JavaScript e sua postagem no blog para usar variáveis ​​de diretório .

No diretório raiz do projeto, crie um arquivo .dir-locals.el

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

Agora, quando visito o arquivo javascript, ele flycheck-verify-setupencontra corretamente o arquivo<dir>/node_modules/.bin/eslint.cmd

Namorado
fonte
0

Minha solução anterior foi uma dor para trabalhar em diferentes projetos.

Modifiquei a resposta aceita para estupidez do Windows de código rígido.

(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))))
Namorado
fonte
0

Aqui está uma solução que combina as respostas de Bae e lunaryorn usando um dir-locals.elarquivo no diretório raiz do projeto (ou, mais especificamente, no diretório que contém a node_modules/pasta em que o eslintbinário mora). Crie o referido dir-locals.elarquivo com o seguinte conteúdo.

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

Aqui, suponho que você esteja usando o js2-modemodo principal do emacs para editar arquivos javascript. Se não for esse o caso, altere essa linha de acordo. A segunda linha do arquivo torna o javascript-eslintverificador de sintaxe o único a ser usado neste projeto. A terceira linha define a variável flycheck-javascript-eslint-executablecomo <root-dir>/node_modules/.bin/eslint. Dessa forma, não modificamos o emacs ' exec-path.

Ricardo
fonte
0

Eu tentei algumas variações diferentes disso e nunca encontrei exatamente o que queria. Finalmente subi de nível o suficiente no Emacs lisp para modificá-lo ao meu gosto. O que minha versão faz é procurar por um eslint local e, se não for encontrado, ele volta a um instalado globalmente:

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