我是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' ++ ")\'"
Run Code Online (Sandbox Code Playgroud)
当我运行调用此命令的程序时stack test,我得到以下结果(穿插单元测试结果):
/bin/sh: emacs: command not found
Exception: callCommand: emacs --eval '(ediff-files "/run/user/1000/ast1780695788709393584.expected" "/run/user/1000/ast4917054031918502651.received")'
Run Code Online (Sandbox Code Playgroud)
当我运行无法从我的shell运行上面的命令时,它运行完美.如何从NixOS中的Haskell运行进程,就像我直接调用它们一样,以便它们可以访问与我的用户相同的命令和配置?
你的 shell 和环境变量都callCommand使用PATH,所以看起来堆栈正在改变这一点。事实证明,stack 默认使用纯 nix shell,但您还想访问您的用户环境,这是“不纯的”。
引用堆栈文档
默认情况下,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解决方案。