在WSL中配置VSCode+OCaml环境

失踪人口归来XD

Linux子系统出现以后让我们可以做很多奇怪的事情了,比如在Windows上跑一些原来不能跑的东西,虽然是一个类似模拟层的实现,但是有总比没有好。

然后我们以搭建OCaml环境为例测试一下传说中的互操作。

VSCode

首先我们知道VSCode这类编辑器(包括但不限于vim,Emacs,Atom,etc, 不引战)本身并没有语义补全的能力,而是依靠插件(自带的插件也是插件)或调用外部程序提供语义补全,比如提供C/C++补全的clang,提供Python补全的python以及我们的主角merlin

1
2
3
4
5
{
...
"ocaml.merlinPath": "ocamlmerlin",
...
}

假设我们的环境变量PATH中有一个叫做ocamlmerlin的二进制,在需要调用补全的时候,VSCode就会使用类似child_process.exec一类的函数来启动外部进程获取补全,大概是这个画风

1
ocamlmerlin -a -b --c balabala

如果ocamlmerlin不在PATH中也没关系,写全就可以了

1
2
3
4
5
{
...
"ocaml.merlinPath": "/path/to/ocamlmerlin",
...
}

画风是这样的

1
/path/to/ocamlmerlin -a -b --c balabala

bash

我们知道,进入Linux子系统的方法就是直接在命令行里敲bash
但是如果只要运行一个程序呢?

1
2
# bash -c "echo 'hello world'"
hello world

对就是这样

1
2
bash -c "ocamlmerlin -a -b --c balabala"
$$%^&*#(@

Wrapper

现在我们的问题在于,如何让VSCodeOCaml插件把参数交给bash,以及如何将bash返回的字符串交给VSCode呢?
我的选择是,加一层wrapper,拼接字符串,以及处理输出。

1
2
3
4
5
6
7
8
9
10
11
12
int main(int argc, char *argv[]) {
std::stringstream cmd{""};
std::string resp{" "};
cmd << "bash -c \"/path/to/ocamlmerlin";
for (int i = 1; i < argc; i++) {
cmd << resp << argv[i];
}
cmd << "\"";
system(cmd.str().c_str());
return 0;
}

万幸,system函数所启动的进程与调用它的进程共享stdoutstderr,从而免去了输出的处理。
由经典的鸭子理论(“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子”),我们编译出来的程序就可以当作Windows下的ocamlmerlin使用了。

效果

如图

img1
img2


本博的原创作品作品采用知识共享署名 2.5 中国大陆许可协议 进行许可,欢迎转载,但转载请注明出处,并保持转载后文章内容的完整。
本文链接:http://fallenwood.github.io/2017/05/06/ocaml-on-wsl/