请注意,这不仅对 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),它忽略了输入/输出流但返回退出代码,并修改了 browse-url 以使用 launch。好多了!浏览器和 REPL,就像快速入门说明中所承诺的那样。
个人笔记:虽然我刚刚开始尝试 ClojureScript,但我已经使用 Clojure 几年了。
由以下人员预审: Alex Miller