2

我想用 Erlang 以外的另一种语言实现 REPL,并且对交互式erl(Eshell)提示符的这个特性非常感兴趣:

1> spawn(fun() -> timer:sleep(5000), io:format("~p~n", ["later"]) end).
<0.34.0>
2> i can ty

所以我在这里所做的是产生一些最终写入终端的后台进程。与此同时,我i can ty刚刚输入了五秒钟,"later"并被插入到正上方2>,结果是:

1> spawn(fun() -> timer:sleep(5000), io:format("~p~n", ["later"]) end).
<0.34.0>
"later"      
2> i can type...

在其他语言中,例如 Bash 或 Node.js,这宁愿会导致类似的结果:

2> i can ty"later"
pe...

Erlang 是如何做到这一点的?我试过用谷歌搜索,甚至快速浏览了它的源代码,但不知道它是如何完成的。我认为它必须涉及一些终端控制序列?

4

1 回答 1

4

Erlang shell 比其他语言更复杂,因为它必须与具有许多进程的分布式系统一起工作。Fred Hebert 写了一篇关于 Erlang shell 的文章,名为“ As bad as anything else ”。

基本上,当您调用 时io:format,它会向其组长发送一条消息。在“ Learn you some Erlang/Building OTP applications ”(再次由 Fred 撰写)中,有一条关于组长和io 协议的说明。

正如@rightfold 在他的评论中提到的那样,io_protocol涉及发送消息。这意味着,它们按顺序写入控制台。在其他语言中,如果您有更多进程同时写入,则可以将部分消息交错,但在 Erlang 中则不行。该协议还涉及等待​​回复。例如,检查io:execute_request github

user_drv负责将消息写入实际tty并用于将消息ncurses放在所需的位置,因此它可以在您开始编写的命令之前插入消息,从而留下干净的历史记录。

于 2014-10-05T07:10:44.970 回答