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