我想用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如何做到这一点?我试过谷歌搜索,甚至快速查看其源代码,但无法找到如何实现。我认为它必须涉及一些终端控制序列?
答案 0 :(得分:4)
Erlang shell比其他语言更复杂,因为它必须与具有许多进程的分布式系统一起使用。 Fred Hebert撰写了关于Erlang shell的文章,名为&#34; As bad as anything else&#34;。
基本上,当您致电io:format
时,它会向其组长发送消息。在&#34; Learn you some Erlang/Building OTP applications&#34; (再次由弗雷德),有一个关于组长和io protocol的说明。
正如@rightfold在评论中提到的那样,io_protocol
涉及发送消息。这意味着,它们按顺序写入控制台。在其他语言中,如果您有更多进程同时写入,则可以将部分消息交错,但不能在Erlang中。该协议还涉及等待回复。例如,请检查io:execute_request
on github。
user_drv
负责将消息写入实际的tty
,并使用ncurses
将消息放在其所需的位置,以便它可以在您开始编写的命令之前插入消息,这留下了干净的历史。