请注意,这不仅对 clojure.java.shell 和 clojure.java.browse 重要,而且还能确保在 xdg-open 被使用的平台上 ClojureScript 浏览器 REPL 可以正确地启动。目前 ClojureScript 快速入门说明在很多系统上基本上是损坏的。大多数 ClojureScript 的初次用户不会喜欢调试这类问题(或者也许我比大多数人都固执吧 :))。
在一些平台上,clojure.java.browse/browse-url 调用 clojure.java.shell/sh 来执行一个 cmdline,使用 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)的函数,它忽略 I/O 流但返回退出代码,并修改了 browse-url 以使用 launch。好多了!浏览器和 REPL,正如快速入门说明中所承诺的那样。
个人笔记:虽然我刚刚开始实验 ClojureScript,但我已经使用 Clojure 好几年了。
由以下人员审核: Alex Miller