请注意,这不仅对于 clojure.java.shell 和 clojure.java.browse 重要,而且这还将使 ClojureScript 浏览器 REPL 能够在 xdg-open 被使用的平台上正确地启动浏览器。目前,ClojureScript 快速入门指南在许多系统上是基本无效的。大多数ClojureScript初学者不会享受调试这类事情(也许我只是比大多数人更坚持不懈:)))
在某些平台上,clojure.java.browse/browse-url 调用 clojure.java.shell/sh 来执行 cmd 命令,使用 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 审筛