Skip to content

Extend haskell-build-type to look for .nix files #1787

Open
@doyougnu

Description

@doyougnu

This is not a bug but a missed edge case, the problem is:

  1. I run nixos and use nix for haskell projects
  2. because of (1) I do not have cabal, stack or ghc globally installed
  3. So I have flake.nix and shell.nix and 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:

  1. the current implementation of haskell-build-type assumes I have stack or cabal globally installed.
  2. However, the user could not have these globally installed and instead choose to provide them in a nix shell. In this scenario haskell-build-type does 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:

  1. add .nix files to the cond expression in haskell-build-type, or
  2. detect if haskell-process-wrapper-function is set, if so run executable-find "foo"` through that.

I think 2 likely makes more sense.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions