庄周梦蝶

生活、程序、未来

声明:本博客所有文章,未经允许,禁止转载。谢谢。

Erlang 和 Elixir shell 历史记录设置

| Comments

Erlang 的 erl 和 Elixir 的 iex 都只有当前 session 的历史记录,可以通过 ctrl + r 或者上下方向键来返回历史记录,并执行。但是当 session 一旦退出,重新启动一个 shell session,前一个历史记录就没有了,这个就非常麻烦。

题外:在 clojure 里, lein repl 帮你处理了这个事情,它将历史命令保存在 ~/.lein_history 文件,在不同 session 之间可以随时调取历史记录。如果使用内置的 clojure REPL,也可以使用 rlwrap 来包装,提供历史记录功能。

erlang-history

不过庆幸的是有一个开源项目帮你解决了这个问题—— erlang-history,它的解决方式比较重量级,通过给 Kernel 打补丁的方式(线上环境肯定不推荐),保存历史记录到 erlang dets。安装非常简单:

1
2
3
git clone git@github.com:ferd/erlang-history.git
cd erlang-history
make install

可能会提示你需要 sudo 权限,因为它要替换 Erlang 默认的 kernel.beam。

安装后,默认的 erl 和 iex 命令就拥有历史记录功能了。不过可能你想修改下一些默认配置。erlang-history 提供的选项包括:

1
2
3
4
hist - true | false :是否启用,默认 true
hist_file - string(): 历史记录文件的 dets 文件名,字符串,默认是 ~/.erlang-history.$NODENAME
hist_size - 1..n    : 历史记录大小,数字,默认 500
hist_drop - ["some", "string", ...]: 不想保存的命令列表。

配置 erl

虽然可以通过命令行传入配置参数,不过更推荐的方式还是写一个配置文件,例如放到 ~/erl_hist.config:

1
2
3
4
[{kernel,[
  {hist_size, 1000},
  {hist_drop, ["q().", ":init.stop()", "init:stop()."]}
]}].

我就配置了两个,最大历史记录 1000 条,忽略 3 个命令,两个是 erlang 的退出命令,一个是 Elixir 的 :init.stop() 。虽然一般都不会调用命令来退出,而是连续两个 ctrl + c。

接下来在 ~/.bash_profile 里为 erl 修改个别名:

1
alias erl="erl -config $HOME/erl_hist.config"

让 erl 默认读取配置文件,erlang-history 的配置就生效了。

配置 iex

配置 iex 只是为 iex 加个别名而已,通过 --erl 传入参数:

1
alias iex="iex --erl '+P 4000000 +K true -config $HOME/erl_hist.config'"

我的配置夹藏了一点私货 +P 4000000 +K true,增大最大进程数限制和启用 kernel-poll,方便平常测试学习。

补充 rlwrap 方案

写完博客才想起去尝试下 rlwrap ,修改了我的 clojure repl 配置:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/sh
breakchars="(){}[],^%$#@\"\";:''|\\"
if [ $# -eq 0 ]; then
    exec rlwrap --remember -c -b "$breakchars" \
   -t "Elixir REPL" \
   -p red \
   -H $HOME/.iex_repl_history -s 1000\
   iex
else
    iex $@
fi

放到了我的 bin 目录,保存为 iex1,测试果然也可以,历史记录保存到了 $HOME/.iex_repl_history,但是缺少 tab 按键的自动完成功能。需要收集一个符号文件,通过 -f 提供给 rlwrap,改天再探索下。

声明:本博客所有文章,未经允许,禁止转载。谢谢。

elixir, erlang

« 死之杂感 Refactor Clojure (1) -- 使用 thread 宏替代嵌套调用 »

Comments