使用Merlin打印文件的模块签名

时间:2017-08-26 23:11:01

标签: ocaml bucklescript merlin

使用Merlin 2.5.4,在我的项目中打印OCaml文件签名的正确方法是什么?例如,假设我有:

(* foo.ml *)
let x = 1

我想得到:

val x : int

正确的命令(或命令序列)是什么?

我尝试过的事情:

我暂时将文件包装在子模块中:module Foo = struct let x = 1 end,然后运行:

$ ocamlmerlin
["type","expression","Foo","at",{"line":1,"col":7}]

但我明白了:

["error",{"start":{"line":1,"col":0},"end":{"line":1,"col":3},"type":"type","sub":[],"valid":true,"message":"Error: Unbound constructor Foo"}]

这是有道理的,因为我实际上还没有提到我查询的文件,查询(https://github.com/ocaml/merlin/blob/master/doc/dev/OLD-PROTOCOL.md#type-checking)也不允许我这样做。

E 我应该提一下,我使用的是BuckleScript,而不是ocamlc,而ocamlc -i只有在我不仅指定我的模块而且指定了所有模块时才有效依赖;我正在寻找能够自动管理这些依赖关系的东西。

1 个答案:

答案 0 :(得分:2)

让Merlin输出模块的推断签名的一种方法是向它提供一系列命令(如https://github.com/ocaml/merlin/blob/master/doc/dev/OLD-PROTOCOL.md#type-checking中的协议所述),该命令首先定义模块然后询问其签名。我们可以准备一个包含这一系列命令的临时文件,并将其作为标准输入提供给Merlin。

棘手的部分是:用正确的命令包装输入;转义输入文件中的双引号字符,这样它们就不会与Merlin的输入格式混合;并解开输出以放弃Merlin的协议格式。以下是关键命令:

it=~/tmp/it

echo '["tell","start","end","module It = struct' >$it
sed 's/"/\\"/g' ${1%i} >>$it
echo ' end let () = ()"]' >>$it
echo '["type","expression","It","at","end"]' >>$it

ocamlmerlin <$it | sed -e '/^\["return",true\]$/d' -e 's/^\["return","sig *//' -e 's/ *end"\]$//' -e 's/\\"/"/g' -e 's/\\n/\
/g' | sed -e '/^ *$/d' -e 's/^  //'

注意事项:

  • 以上假设在命令路径中使用touchsed以及ocamlmerlin的Unix-y系统
  • Merlin不会在其输出中保留OCaml属性([@...]
  • 仅适用于OCaml语法,但可以适应原因语法

可以在https://gist.github.com/yawaramin/b86557ae81cbd019fcb9e071abe594de找到更完整的脚本。