haskell-mode
haskell-mode copied to clipboard
Extend haskell-build-type to look for .nix files
This is not a bug but a missed edge case, the problem is:
- I run nixos and use nix for haskell projects
- because of (1) I do not have cabal, stack or ghc globally installed
- So I have
flake.nixandshell.nixand friends in root directories of project.
Now the traditional way to run inferior-haskell-process is with haskell-process-wrapper like so (this uses the nix-sandbox emacs package):
(setq default-nix-wrapper
(lambda (args)
(append
(append (list "nix-shell" "--command")
(list (mapconcat 'identity args " ")))
(list (nix-current-sandbox))))
(setq haskell-process-wrapper-function
(lambda (args)
(apply 'nix-shell-command (nix-current-sandbox) args)))
However, this doesn't work because haskell-build-type in haskell-customize.el looks for a cabal cabal.project stack file and an executable on path:
(defun haskell-build-type ()
"Looks for cabal and stack spec files.
When found, returns a pair (TAG . DIR)
where TAG is 'cabal-project, 'cabal-sandbox. 'cabal, or 'stack;
and DIR is the directory containing cabal or stack file.
When none found, DIR is nil, and TAG is 'ghc"
;; REVIEW maybe just 'cabal is enough.
(let ((cabal-project (locate-dominating-file default-directory "cabal.project"))
(cabal-sandbox (locate-dominating-file default-directory "cabal.sandbox.config"))
(stack (locate-dominating-file default-directory "stack.yaml"))
(cabal (locate-dominating-file
default-directory
(lambda (d)
(cl-find-if
(lambda (f) (string-match-p ".\\.cabal\\'" f))
(directory-files d))))))
(cond
((and cabal-project (executable-find "cabal"))
(cons 'cabal-project cabal-project))
((and cabal-sandbox (executable-find "cabal"))
(cons 'cabal-sandbox cabal-sandbox))
((and stack (executable-find "stack"))
(cons 'stack stack))
((and cabal (executable-find "cabal")) ;; <---------------------------------------------- right here
(cons 'cabal cabal))
((executable-find "ghc") (cons 'ghc nil))
(t (error "Could not find any installation of GHC.")))))
This means that when I try run-haskell or haskell-process-load-file I get Could not find any installation of GHC even though ghc cabal and friends are accessible from my nix shell.
So to summarize:
- the current implementation of
haskell-build-typeassumes I havestackorcabalglobally installed. - However, the user could not have these globally installed and instead choose to provide them in a nix shell. In this scenario
haskell-build-typedoes not realize this and prematurely errors out, even though if it ran inside the nix shell everything would be fine.
So I think there are two paths forward:
- add
.nixfiles to thecondexpression inhaskell-build-type, or - detect if
haskell-process-wrapper-function is set, if so runexecutable-find "foo"` through that.
I think 2 likely makes more sense.