在NixOS中从Haskell运行shell命令

时间:2018-01-10 08:06:12

标签: haskell nixos

我是NixOS的新手,我正在尝试使用以下函数从Haskell程序调用emacs:

ediff :: String -> String -> String -> IO ()
ediff testName a b = do
  a' <- writeSystemTempFile (testName ++ ".expected") a
  b' <- writeSystemTempFile (testName ++ ".received") b
  let quote s = "\"" ++ s ++ "\""
  callCommand $ "emacs --eval \'(ediff-files " ++ quote a' ++ quote b' ++ ")\'"

当我运行使用stack test调用此命令的程序时,我得到以下结果(穿插单元测试结果):

/bin/sh: emacs: command not found
Exception: callCommand: emacs --eval '(ediff-files "/run/user/1000/ast1780695788709393584.expected" "/run/user/1000/ast4917054031918502651.received")'

当我运行无法从我的shell运行上面的命令时,它运行完美。如何从NixOS中的Haskell运行进程,就像我直接调用它们一样,以便它们可以访问与我的用户相同的命令和配置?

1 个答案:

答案 0 :(得分:3)

你的shell和callCommand都使用PATH环境变量,所以看起来堆栈正在改变它。事实证明,默认情况下,堆栈使用纯粹的nix shell,但您也希望访问用户环境,这是“不纯净的”。

引用stack documenation

  

默认情况下,stack将在纯Nix构建环境(或shell)中运行构建,这意味着如果您没有在stack.yaml文件的packages:部分中指定所有依赖项,则构建应该失败即使这些依赖项安装在系统的其他位置。此行为强制执行构建环境的完整描述,以便于重现性。要覆盖此行为,请将pure:false添加到stack.yaml或将--no-nix-pure选项传递给命令行。

另一个解决方案是将{Emacs添加到nix.dependencies中的stack.yaml(感谢@chepner)。它的好处是,当开发人员运行测试时,某些版本的Emacs将始终可用,但Emacs可能不是他们想要使用的Emacs。您可以使用~/.config/nixpkgs/config.nix之类的东西来解决这个问题,除非他们已经在其他地方配置了他们的Emacs,比如系统配置或家庭经理。我更喜欢简单但不纯的$PATH解决方案。