您的位置:首页 > 运维架构 > Shell

Clojure:在REPL上实现一个简单的shell(一)

2011-12-29 16:07 274 查看
REPL是一个Clojure环境,它不能直接调用命令行/shell里面的命令,现在我们想在REPL里面实现一个shell,让它既可以像在shell里面直接对系统(或shell的内置命令)进行调用,也可以做REPL下能做的事情。

上一篇中我们写了一个read程序,这个程序会要求用户输入,并将获得的输入作为一个字符串来返回:

(defn ask
  "Ask for an input."
  ([] (ask "Please Input"))
  ([^String prompt]
    (printf "%s: " prompt)
    (flush)
    (.readLine *in*)))

有了这个函数,我们就可以装模做样地让REPL看起来像一个shell:

(defn shell[]
  (let [prompt "shell->"
        exit-cmd "let me out!"]
    (loop [cmd (ask prompt)]
      (if (= cmd exit-cmd)
        (println "get out!")
        (do 
          (exec cmd)
          (recur (ask prompt)))))))

我们先假设其中的”exec“函数已经存在,定义好了这两个函数之后,直接在REPL里面调用”(shell)"就可以看到类似于以下的画面:
#'user/shell

user=> (shell)

shell->: testing

you said: testing

shell->: I want money

you said: I want money

shell->: oh....

you said: oh....

shell->: let me out!

get out!

nil

user=>

这里的"shell“函数我仅仅是用了println来代替里面的exec,整个函数现在看起来就像个应声虫,也许改名为echo会适当一些——但这都仅仅是因为我们还没实现”exec“函数而已。
当然我们这个shell天生有一个缺陷,就是只能读入一行的输入,这跟REPL不一样,在REPL里面如果被判断为未完成输入的话会一直等待输入结束(例如,必须有匹配的闭括号)。关于这个问题,我们后面也许会探讨出解决方法。
至于exec的实现,请读者自行实现,或者有缘的话,让我们期待下一篇……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shell clojure cmd string input