如何从Clojure命令行应用程序中放入一个repl?

时间:2018-11-07 08:34:16

标签: clojure command-line-interface read-eval-print-loop

我正在编写Clojure CLI应用程序,我想允许给它一个命令,该命令会将人们放入clojure.main REPL。

有人知道我该怎么做吗?我的努力没有取得成果。

编辑:

我的CLI接受管道输入,这使我的问题变得更糟。这是我想要工作的示例:

(ns playground.core
  (:gen-class))

(defn -main
  [& args]
  (with-open [r (io/reader *in*)]
    (doseq [line (line-seq r)]
      (println line)))
;; Drop in repl after having read the input and printed its content)

然后我这样称呼它:

cat ./somefile.txt | lein trampoline run

2 个答案:

答案 0 :(得分:0)

您只需从程序中调用clojure.main/repl,它将开始侦听stdin并对其进行“重复” ;-),此时repl将开始

user> (clojure.main/repl)

然后我在终端(+ 1 2 3)中键入

user=> 6
user=> 

所以我在一个repl中有一个repl,以模拟使用您的程序的人键入start repl命令的情况。

为了使人{@ 3}}项目具有人性化的体验,在调用clojure.main / repl时增加了很多内容:

(rebel-readline.core/with-line-reader
  (rebel-readline.clojure.line-reader/create
    (rebel-readline.clojure.service.local/create))
  (clojure.main/repl
     :prompt (fn []) ;; prompt is handled by line-reader
     :read (rebel-readline.clojure.main/create-repl-read)))


由于您的程序实际上具有两个阶段,因此

  1. 从标准输入中永久读取内容,直到标准输入永久关闭为止。
  2. 一旦程序失效或标准输入不再可用,无论哪种情况发生,先从标准输入中读取更多信息。

一旦发送了一些特殊行,您可能想要(或也许已经拥有)一种从with-open开始出现的事情。一旦收到,请完全退出line-seqwith-open。然后启动repl,以便它可以获取输入文件描述符。


一旦使程序获得了对repl的输入,就可以在封闭的shell命令中解决管道问题。 cat带有一个特殊的参数-(两边都有一点破折号,两侧都留有空格),上面写着“停在这里并从键盘上读取,直到按Crtl-d为止”。
~ » cat a-file - | cat
hello im a line from a file
hello
hello

在此示例中,它从文件中读取一行,并将其传递给cat命令(用您的程序替换),然后从键盘上读取单词hello并进行打印(因此您可以看到它在屏幕上两次)

答案 1 :(得分:0)

也许启动无头REPL并有两个单独的步骤可能对您有用?

第1步

启动无头REPL,等待它启动

$ lein repl :headless :host 0.0.0.0 :port 9000
nREPL server started on port 9000 on host 0.0.0.0 - nrepl://0.0.0.0:9000

第2步

在另一个外壳中,使用您的命令将命令发送到REPL:

$ cat test.txt 
(def hello "Hello world!")

$ cat test.txt | lein repl :connect 0.0.0.0:9000
Connecting to nREPL at 0.0.0.0:9000
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

pipetest.core=> (def hello "Hello world!")
#'pipetest.core/hello
pipetest.core=> Bye for now!

第3步

您可以连接到REPL,在上一步状态更改后继续操作,但是现在您可以使用它进行交互了。

$ lein repl :connect 0.0.0.0:9000
Connecting to nREPL at 0.0.0.0:9000
REPL-y 0.3.7, nREPL 0.2.12
Clojure 1.8.0
OpenJDK 64-Bit Server VM 1.8.0_181-8u181-b13-1ubuntu0.18.04.1-b13
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

pipetest.core=> (str hello "!!!")
"Hello world!!!!"