2024 Clojure 运行状况调查 中分享你的想法!

欢迎!请查看关于页面,了解如何使用本网站更多信息。

+4
Clojure
关闭

请注意,这不仅对clojure.java.shell和by implication,clojure.java.browse很重要,而且这还将启用ClojureScript浏览器REPL在where xdg-open used的平台上正确启动。目前ClojureScript快速入门指南在很多系统上几乎是损坏的。大多数第一次使用ClojureScript的用户不会喜欢调试这样的东西(或者我只是比大多数人更加固执:))).

在some平台上clojure.java.browse/browse-url调用clojure.java.shell/sh来执行cmdline,使用xdg-open打开网页浏览器。作为Nix工具,xdg-open将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

带有note关闭: 在1.11.0-alpha4中发布

7 答案

0

用户jdjohnston发表的评论:

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

0

用户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的文件Clojure源代码没有改变。

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

Ubuntu 16.04.6 桌面 Linux,截至2019年3月21日的最新更新
从openjdk-8-jre-headless和openjdk-8-jdk-headless Ubuntu软件包中安装的OpenJDK 1.8.0_191
截至2019年3月21日的最新Clojure master以及clj-2493.patch

0
_用户jafingerhut_发表的评论:

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

我认为我无权包含{:added "1.11"},特别是由于它在此时间点还没有被添加。我应该添加元数据并构建一个新的补丁吗-是更新还是替换?
0

用户alexmiller的评论:

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

关于元数据,可以选择在1.11版本中添加元数据,并在描述中注明,或者不添加元数据,但在描述中注明直到添加为止测试将失败。不管哪种方式,我们到达发布筛选阶段时都可以进行修复。

0
by

用户jdjohnston发表的评论:

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

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

在遵循clojurescript的“快速开始”指南( https://script.clojure.org/guides/quick-start )时,clj命令会启动浏览器,并显示“Hello World!”文本,但永远不会显示REPL提示。我尝试多次按Enter键,但不起作用。在我的情况下,关闭浏览器会出现错误,clojure会退出。

我尝试更改默认浏览器(尝试了Firefox和Chromium),结果相同。

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

这就是一切,感谢补丁,它对我来说也有效。
by
感谢您的反馈 - 这将在Clojure 1.11中进行考虑。
查看 1.11.0-alpha4,

新的 clojure.java.shell/launch 对“xdg-open”打开网页似乎可以工作,但这仅是因为 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 重定向到 java.lang.ProcessBuilder。
...