请注意,这不仅对 clojure.java.shell 很重要,而且对 clojure.java.browse 也同样重要,而且这还将使 ClojureScript 浏览器 REPL 能够在 xdg-open 使用的平台上正确启动。目前,ClojureScript 快速入门指南在许多系统中实际上是损坏的。大多数 ClojureScript 的新用户不会喜欢调试这样的东西(或者我只是比大多数人更固执:))。
在某些平台上,clojure.java.browse/browse-url 调用 clojure.java.shell/sh 来执行使用 xdg-open 启动网页浏览器的命令行。作为良好的 **Nix 工具,xdg-open 将其打开的文件描述符传递给新的进程。(我不知道这在 xdg-open 的某个地方是否有文档说明,但这很容易证明。)
clojure.java.shell/sh 总是读取执行的进程的 STDOUT 和 STDERR 流。当目的是收集子进程的输出时,这当然是一件好事。然而,在用 xdg-open 启动浏览器时,直到浏览器退出,流才关闭。对于 clojure.java.browse/browse-url 的调用者来说,这个函数看起来“永不”返回。
我们需要的是 clojure.java.shell/sh 的一个变体(或 sh 的选项)来忽略输出流,并且仅返回退出代码。我们使用子进程完全是为了其副作用。这与使用 doseq 替代 map 部分类似,但我们确实需要子进程的退出代码。
为了使 ClojureScript 浏览器 REPL 工作正常,我创建了 clojure.java.{browse,shell} 的本地副本,向 clojure.java.shell 中添加了一个名为 (launch) 的函数,它忽略了输入输出流但返回退出代码,并将 browse-url 修改为使用 launch。好多了!浏览器和 REPL 都按快速入门指南中的承诺工作。
个人笔记:虽然我刚开始尝试 ClojureScript,但我已经用 Clojure 使用了好几年。
由: Alex Miller