请注意,这不仅对clojure.java.shell(以及隐含的clojure.java.browse)很重要,这还将使ClojureScript浏览器的REPL正确地在xdg-open使用的平台上启动。目前,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 审查