请分享您的看法,参与2024年Clojure调查!

欢迎!请看到关于页面了解更多关于此 sitio 的工作方式的信息。

+4
Clojure
已关闭

请注意,这不仅对clojure.java(shell)和clojure.java.browse很重要,而且还将使在x)dopen上使用的平台上的ClojureScript浏览器REPL能够正确启动浏览器。目前,ClojureScript快速入门说明在许多系统上实际上是出错的。大多数ClojureScript的新用户不会喜欢调试这样的东西(或者也许我只是比大多数人更固执:)))。

在某些平台上,clojure.java.browse/browse-url通过xdg-open调用clojure.java.shell/sh来执行cmd命令。作为正确的*Nix实用程序,xdg-open将它的打开文件描述符传递到新进程中。(我不知道x)dopen是否在某处有文档记录,但这很容易演示。)

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添加了一个(启动)函数,该函数忽略I/O流但返回退出代码,并将browse-url修改为使用启动。好多了!浏览器和REPL都与快速入门说明中承诺的一样。

个人笔记:尽管我刚刚开始实验ClojureScript,但我已经使用Clojure几年的时间了。

由: Alex Miller

以以下说明关闭: 在1.11.0-alpha4中发布

7 答案

0
by

评论者:jdjohnston

clj-2493.patch 附加于2019年3月21日

0
by

评论者:jafingerhut

我已经在我的本地机器上Clojure 1.10.0的clj REPL中测试了(clojure.java.browse/browse-url "https://github.com"),它确实没有给出另一个REPL提示,除非关闭浏览器。我于2012年对这一功能进行了最后的更改,以添加xdg-open功能,我相当肯定当时并没有这样做,但也许xdg-open的行为已经改变。从2012年以来,包含了clojure.java.browse/browse-url和clojure.java.shell/sh的文件没有改变。

以下是我的良好测试结果系统

Ubuntu 16.04.6桌面Linux,至2019年3月21日的最新更新
OpenJDK 1.8.0_191安装在openjdk-8-jre-headless和openjdk-8-jdk-headless Ubuntu包中
2019年3月21日的最新Clojure master版本加上clj-2493.patch

0
by
_评论者:jafingerhut_

这些更改导致在构建Clojure时测试失败,我认为是因为新的启动函数在文档字符串之后没有{:added "1.11"}元数据。
0
by
_评论者:jdjohnston_

我认为这不是我的位置来包括{:added "1.11"},特别是因为它_还没有_在这个时间点被添加。我是否应该添加元数据并构建一个新的补丁 - 或者更新或替换?
0
by

评论者:alexmiller

应用补丁时存在两个尾随空格错误 - 当前补丁的第43行和第49行。如果您能将这些清理一下将很好。

关于元数据,可以选择在1.11版本中添加元数据,并在描述中留下关于此的备注,或者不添加元数据,但在描述中注明测试将无法通过,直到添加为止。无论哪种情况,当到达进行发布筛选的点时,我都会进行处理。

0

评论者:jdjohnston

2019年3月21日的第二个补丁 - 替换第一个补丁
- 删除了尾随空格
- 出于接受预期添加了元数据 :)

0
参考资料:https://clojure.atlassian.net/browse/CLJ-2493 (由jdjohnston报告)
我也在debian stretch上遇到了这个完全相同的问题,openjdk版本1.8.0_222,通过linux-install-1.10.1.469.sh脚本安装了clojure。

在遵循clj命令使用cljularscript的“快速入门”指南时,会启动浏览器并显示“Hello World!”文本,但不会显示REPL提示。我尝试多次按Enter键,但都没有效果。在我这个情况下,关闭浏览器会报错并退出clojure。

我尝试更改默认浏览器(试用过Firefox和Chromium),结果都一样。

在克隆clojure仓库、应用此补丁和使用修补后的clojure构建/运行后,我终于能够打开浏览器窗口,在REPL中显示文本,并显示REPL提示。最后胜利了! :-D

这一切都是为了说,感谢补丁,它也对我有效。
感谢反馈,此内容正在队列中等待考虑添加到Clojure 1.11中。
查看 1.11.0-alpha4 版本,

新的 clojure.java.shell/launch 可能看起来在打开网页浏览器时可以正常工作,但仅仅是因为 xdg-open 和封装的浏览器通常几乎不写入标准流。

根据 Javadoc (https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/lang/Process.html), "由于一些本地平台只为标准输入和输出流提供有限缓冲区大小,未能及时写入输入流或读取输出流可能会引起进程阻塞,甚至死锁。"

例如,

    (require '[clojure.java.shell :as shell]))

    ;; 使用 'sh' 执行 - 不挂起
    (time (:exit (shell/sh "bash" "-c" "sleep 1; z=0; while [ $z -lt 25000 ] ; do echo $z; z=$((z+1)) ; done")) }}

    ;; 使用 'launch' 执行 - 挂起
    (shell/launch "bash" "-c" "sleep 1; z=0; while [ $z -lt 25000 ] ; do echo $z; z=$((z+1)) ; done"))
       
绕过这个问题的方法之一,一般来说(我不清楚在特定情况下与 xdg-open 和浏览器一起使用时是如何工作的)是使用 ProcessBuilder,并在调用 .start 之前将 .redirectError 和 .redirectOutput 设置为 java.lang.ProcessBuilder$Redirect/DISCARD。
...