nix-shell-command might need to do more complicated processing? (suggested flycheck config fails on elisp files)
cumber opened this issue · 2 comments
The readme suggests this configuration for flycheck wrappers to find nix shells:
(setq flycheck-command-wrapper-function
(lambda (command) (apply 'nix-shell-command (nix-current-sandbox) command))
flycheck-executable-find
(lambda (cmd) (nix-executable-find (nix-current-sandbox) cmd)))
This has been working great for my Haskell development. But when I edit an elisp file (such as ~/.emacs.d/init.el) I get this error:
Suspicious state from syntax checker emacs-lisp-checkdoc: Flycheck checker emacs-lisp-checkdoc returned non-zero exit code 1, but its output contained no errors: /run/current-system/sw/bin/bash: -c: line 0: syntax error near unexpected token `('
The command its running appears to be this:
"bash" "-c" "source /tmp/nix-sandbox-rc-8480dqC; /nix/store/1v2ral91bd58w3rawxb1p4a6dwdmz1fd-emacs-25.3/bin/.emacs-wrapped -Q --batch --eval (progn (setq-default sentence-end-double-space t)) --eval (progn (defvar jka-compr-inhibit) (unwind-protect (let ((jka-compr-inhibit t)) (when (equal (car command-line-args-left) "--") (setq command-line-args-left (cdr command-line-args-left))) (unless (require 'elisp-mode nil 'no-error) (require 'lisp-mode)) (require 'checkdoc) (let ((source (car command-line-args-left)) (process-default-directory default-directory)) (with-temp-buffer (insert-file-contents source 'visit) (setq buffer-file-name source) (setq default-directory process-default-directory) (with-demoted-errors "Error in checkdoc: %S" (delay-mode-hooks (emacs-lisp-mode)) (setq delayed-mode-hooks nil) (checkdoc-current-buffer t) (with-current-buffer checkdoc-diagnostic-buffer (princ (buffer-substring-no-properties (point-min) (point-max))) (kill-buffer)))))) (setq command-line-args-left nil))) -- /tmp/flycheck8480q0I/foo.el"
The problem being that quotes have been added around all the outer strings, but since we're calling bash -c the last string is another bash command, and the arguments inside that command aren't quoted properly.
I think what's going on is that nix-shell-command
is taking a list of shell parameters in command
, and in order to embed them into a bash command that sources the sandbox environment it's pasting them in a string. That works provided all the arguments are "simple" enough, but the emacs-lisp checker wants to invoke emacs with a bunch of lisp code as --eval
arguments; all the parentheses and single quotes in the lisp arguments are being interpreted as bash syntax.
While it's not for elisp, I did following to fix the flycheck for YAML files:
(setq-default
flycheck-yaml-ruby-executable '("ruby" "-ryaml" "-e"
"'begin;
YAML.load(STDIN);
rescue Exception => e;
STDERR.puts %(stdin:#{e});
end'"))
Maybe something similar could work for you?
I think this ought to work:
(setq flycheck-command-wrapper-function
(lambda (cmd)
(list "bash" "-c" (format "source %s; %s"
(nix-sandbox-rc (nix-current-sandbox))
(mapconcat 'shell-quote-argument cmd " ")))))
Or this, I guess:
(setq flycheck-command-wrapper-function
(lambda (cmd)
(apply 'nix-shell-command (nix-current-sandbox)
(list (mapconcat 'shell-quote-argument cmd " ")))))
Or just replace the definition of nix-shell-command
:
(defun nix-shell-command (sandbox &rest args)
"Assemble a command from ARGS that can be executed in the specified SANDBOX."
(list "bash" "-c" (format "source %s; %s" (nix-sandbox-rc sandbox)
(mapconcat 'shell-quote-argument args " "))))