diff --git a/haskell-process.el b/haskell-process.el index 402de0a98..8b35ab731 100644 --- a/haskell-process.el +++ b/haskell-process.el @@ -78,6 +78,19 @@ :group 'haskell-interactive :type '(choice string (repeat string))) +(defcustom haskell-process-path-nix-shell + "nix-shell" + "The path for starting nix-shell." + :group 'haskell-interactive + :type '(choice string (repeat string))) + +(defcustom haskell-process-args-nix-shell + '("shell.nix") + "Any arguments for starting nix-shell." + :group 'haskell-interactive + :type '(choice string (repeat string))) + + (defcustom haskell-process-args-ghci '("-ferror-spans") "Any arguments for starting ghci." @@ -106,7 +119,8 @@ See `haskell-process-do-cabal' for more details." (defcustom haskell-process-type 'auto "The inferior Haskell process type to use." - :type '(choice (const auto) (const ghci) (const cabal-repl) (const cabal-dev) (const cabal-ghci)) + :type '(choice (const auto) (const ghci) (const cabal-repl) (const cabal-dev) (const cabal-ghci) + (const nix-shell-ghci) (const nix-shell-cabal-repl)) :group 'haskell-interactive) (defcustom haskell-process-log @@ -507,7 +521,9 @@ for various things, but is optional." "Add /dist/build/autogen/ to the ghci search path. This allows modules such as 'Path_...', generated by cabal, to be loaded by ghci." - (unless (eq 'cabal-repl (haskell-process-type)) ;; redundant with "cabal repl" + (unless (or (eq 'cabal-repl haskell-process-type) ;; redundant with "cabal repl" + (eq 'nix-shell-ghci haskell-process-type) + (eq 'nix-shell-cabal-repl haskell-process-type)) (let* ((session (haskell-session)) (cabal-dir (haskell-session-cabal-dir session)) @@ -519,13 +535,17 @@ to be loaded by ghci." (defun haskell-process-type () "Return `haskell-process-type', or a guess if that variable is 'auto." (if (eq 'auto haskell-process-type) - (if (locate-dominating-file - default-directory - (lambda (d) - (or (file-directory-p (expand-file-name ".cabal-sandbox" d)) - (cl-find-if (lambda (f) (string-match-p "\\.cabal\\'" f)) (directory-files d))))) - 'cabal-repl - 'ghci) + (let ((nix-shell-found (locate-dominating-file default-directory "shell.nix")) + (cabal-sandbox-found (locate-dominating-file + default-directory + (lambda (d) + (or (file-directory-p (expand-file-name ".cabal-sandbox" d)) + (cl-find-if (lambda (f) (string-match-p "\\.cabal\\'" f)) + (directory-files d))))))) + (cond ((and cabal-sandbox-found nix-shell-found) 'nix-shell-cabal-repl) + (cabal-sandbox-found 'cabal-repl) + (nix-shell-found 'nix-shell-ghci) + (t 'ghci))) haskell-process-type)) (defun haskell-process-do-cabal (command) @@ -542,13 +562,25 @@ to be loaded by ghci." (cadr state) (format haskell-process-do-cabal-format-string (haskell-session-cabal-dir (car state)) - (format "%s %s" - (cl-ecase (haskell-process-type) + (format "%s %s %s" + (cl-ecase haskell-process-type ('ghci haskell-process-path-cabal) ('cabal-repl haskell-process-path-cabal) ('cabal-ghci haskell-process-path-cabal) - ('cabal-dev haskell-process-path-cabal-dev)) - (cl-caddr state))))) + ('cabal-dev haskell-process-path-cabal-dev) + ('nix-shell-ghci (concat haskell-process-path-nix-shell + " " + haskell-process-args-nix-shell + " --command '")) + ('nix-shell-cabal-repl (concat haskell-process-path-nix-shell + " " + haskell-process-args-nix-shell + " --command '"))) + (cl-caddr state) + (cl-case haskell-process-type + ('nix-shell-ghci "'") + ('nix-shell-cabal-repl "'") + (t "")))))) :live (lambda (state buffer) @@ -590,7 +622,9 @@ to be loaded by ghci." ('ghci haskell-process-path-cabal) ('cabal-repl haskell-process-path-cabal) ('cabal-ghci haskell-process-path-cabal) - ('cabal-dev haskell-process-path-cabal-dev)) + ('cabal-dev haskell-process-path-cabal-dev) + ('nix-shell-ghci haskell-process-path-nix-shell) + ('nix-shell-cabal-repl haskell-process-path-nix-shell)) :app-icon haskell-process-logo ))))))))) @@ -1017,58 +1051,60 @@ now." (haskell-process-set-session process session) (haskell-process-set-cmd process nil) (haskell-process-set (haskell-session-process session) 'is-restarting nil) - (let ((default-directory (haskell-session-cabal-dir session))) - (haskell-session-pwd session) - (haskell-process-set-process - process - (cl-ecase (haskell-process-type) - ('ghci - (haskell-process-log - (propertize (format "Starting inferior GHCi process %s ..." - haskell-process-path-ghci) - 'face font-lock-comment-face)) - (apply #'start-process - (append (list (haskell-session-name session) - nil - haskell-process-path-ghci) - haskell-process-args-ghci))) - ('cabal-repl - (haskell-process-log - (propertize - (format "Starting inferior `cabal repl' process using %s ..." - haskell-process-path-cabal) - 'face font-lock-comment-face)) - - (apply #'start-process - (append (list (haskell-session-name session) - nil - haskell-process-path-cabal) - '("repl") haskell-process-args-cabal-repl - (let ((target (haskell-session-target session))) - (if target (list target) nil))))) - ('cabal-ghci - (haskell-process-log - (propertize - (format "Starting inferior cabal-ghci process using %s ..." - haskell-process-path-cabal-ghci) - 'face font-lock-comment-face)) - (start-process (haskell-session-name session) - nil - haskell-process-path-cabal-ghci)) - ('cabal-dev - (let ((dir (concat (haskell-session-cabal-dir session) - "/cabal-dev"))) - (haskell-process-log - (propertize (format "Starting inferior cabal-dev process %s -s %s ..." - haskell-process-path-cabal-dev - dir) - 'face font-lock-comment-face)) - (start-process (haskell-session-name session) - nil - haskell-process-path-cabal-dev - "ghci" - "-s" - dir)))))) + (let ((default-directory (haskell-session-cabal-dir session)) + (targetl (let ((target (haskell-session-target session))) + (if target (list target) nil)))) + (cl-flet* ((prog-args (prognm args) + (append (list (haskell-session-name session) + nil + prognm) + args)) + (my-start-process (prognm args) + (apply #'start-process (prog-args prognm args))) + (my-log (s) + (haskell-process-log + (propertize s 'face font-lock-comment-face)))) + (haskell-session-pwd session) + (haskell-process-set-process + process + (cl-ecase haskell-process-type + ('ghci + (my-log (format "Starting inferior GHCi process %s ..." + haskell-process-path-ghci)) + (my-start-process haskell-process-path-ghci haskell-process-args-ghci)) + ('cabal-repl + (my-log (format "Starting inferior `cabal repl' process using %s ..." + haskell-process-path-cabal)) + + (my-start-process haskell-process-path-cabal + (append '("repl") haskell-process-args-cabal-repl targetl))) + ('cabal-ghci + (my-log (format "Starting inferior cabal-ghci process using %s ..." + haskell-process-path-cabal-ghci)) + (my-start-process haskell-process-path-cabal-ghci nil)) + ('cabal-dev + (let ((dir (concat (haskell-session-cabal-dir session) + "/cabal-dev"))) + (my-log (format "Starting inferior cabal-dev process %s -s %s ..." + haskell-process-path-cabal-dev + dir)) + (my-start-process haskell-process-path-cabal-dev + (list "ghci" "-s" dir)))) + ('nix-shell-ghci + (let ((args (append haskell-process-args-nix-shell + '("--command") + (list haskell-process-path-ghci) + (let ((target (haskell-session-target session))) + (if target (list target) nil))))) + (my-log (format "Starting inferior nix-shell (ghci) process using %s..." + (mapconcat 'identity args "' '"))) + (my-start-process haskell-process-path-nix-shell args))) + ('nix-shell-cabal-repl + (let ((args (append haskell-process-args-nix-shell + '("--command" "cabal repl")))) + (my-log (format "Starting inferior nix-shell (cabal repl) process using %s..." + (mapconcat 'identity args "' '"))) + (my-start-process haskell-process-path-nix-shell args))))))) (progn (set-process-sentinel (haskell-process-process process) 'haskell-process-sentinel) (set-process-filter (haskell-process-process process) 'haskell-process-filter)) (haskell-process-send-startup process)