2024 年 Clojure 状态调查中分享您的想法!

欢迎!请参阅 关于 页面以了解更多关于如何使用本站的信息。

+4 投票
Clojure
已关闭

请注意,这对于 clojure.java.shell 和 clojure.java.browse 都很重要,并且这将启用 ClojureScript 浏览器 REPL 在使用 xdg-open 的平台正确地启动浏览器。目前 ClojureScript 快速入门说明在许多系统上基本上是无效的。大多数 ClojureScript 的首次用户不会享受像这样(或者也许我比大多数人更固执 :))的调试。

在某些平台上,clojure.java.browse/browse-url 使用 xdg-open 通过 clojure.java.shell/sh 来执行 cmd 线。作为一个正常的 **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} 中创建了一个本地副本,添加了一个(launch)函数到 clojure.java.shell,它忽略输入/输出流但返回退出代码,并将 browse-url 修改为使用 launch。好多了!浏览器和 REPL,正如 Quick Start 说明中所承诺的那样。

个人笔记:虽然我刚开始尝试 ClojureScript,但我已经使用 Clojure 好几年了

已审阅: Alex Miller

带有以下注释关闭: 在 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主版本加上clj-2493.patch

0 投票
评论者:jafingerhut

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

我认为不应该由我来包含 {:added "1.11"},特别是因为在此之前它还没有被添加。我应该添加元数据并构建一个新的补丁——要么是更新要么是替换吗?
0 投票

评论者: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时,也遇到了完全相同的问题。

在遵循clojurescript的“快速入门”(https://script.clojure.org/guides/quick-start)指南时,clj命令会启动浏览器,并显示“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打开网页时工作,但这仅仅是因为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之前使用ProcessBuilder的.redirectError和.redirectOutput将java.lang.ProcessBuilder$Redirect/DISCARD重定向。
...