请注意,这不仅对 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