Rustでvim plugin(with deno)
(記事の内容としては、Vimの話に見せかけてほぼwasmとdenoとrustを組み合わせるだけの話です。むしろそちらで詰まってしまった人の方が有用に感じられるかもしれません。)
demo is here
はじめに
最近Vim/Neovim両対応のプラグインの基盤として denops.vim
というものが実装されつつあります。
僕がこのプロジェクトに期待している理由の一つが、denoを利用しているためwasmを読みこみできるという点です。
このプロジェクトは「deno(Typescript)でかける」ことを一つのセールスポイントにしていますが、
個人的には「denoだけでなくwasmを経由して好きな言語でプラグインを書き、denoを簡単な処理や根元のIFにすることもできる」というのが
これを見た時の最初の感想でした。
最近はcoc.nvim
というプラグインにより「vscodeのプラグインをvimに移植」ということが流行っていますが、
同様に「vscode,denops両対応」や「vim,shell両対応のツール」といったものを、よりシンプルに実装できるのではないかと期待しています。
(個人的にはvimlの関数やベストプラクティスの知識がほぼないので、その辺りの一部をrustやtsに投げられるのも良さそうです。結局vimlも合わせて勉強しないといけないのは変わりないですが。)
ということで、幾つか引っ掛かりポイントに足を取られながらも無事に"rust->wasm->deno->vim
と処理を繋ぐことが出来たのでここに共有したいと思います。
rust to wasm
rust -> wasmのコンパイルにはwasm-packを使うことが多いのですが、こちらはdenoにまだ対応していないのでssvmupを使おうかかなり悩みました。
結果的にssvmupのコンパイルでもdenoでの読み込みに手間取ったこと、ssvmupはwasm-bindgen
のバージョンが固定になっていることなどからwasm-packでゴリ押す方を選択しました。
wasm-packのbuildをdenoに読み込ませる方法
denoではnodejsとの違いからtutorial
の方法がそのまま使えません。
主に問題になるのは、
- denoはAPIがbrowser API互換なのでweb向けのbuildをする必要がある.(https://github.com/rustwasm/wasm-pack/issues/672#issuecomment-652296745) (1敗)
- alartも
console.log
として定義します。
- alartも
- denoはlocal file のfetchに非対応なのでその部分(localのwasmを読み込む部分)を取りかえる必要がある. (1敗)
あたりでしょうか。
それぞれwasm-packの引数、wasmのattribute, 雑なsedで変換することでdenoで読み込めるものになります。
-
wasm-pack build
の引数に--target web
を追加+ wasm-pack build - wasm-pack build --target web
-
#[wasm_bindgen(js_namespace = console, js_name = log)]
のattributeでstdoutに出力src/main.rs+ #[wasm_bindgen(js_namespace = console, js_name = log)] fn alart(s: &str);
-
fetch(input)
をnew WebAssembly.Module(await Deno.readFile(new URL(input).pathname));
で置換pkg/index.ts+ input = fetch(input); - new WebAssembly.Module(await Deno.readFile(new URL(input).pathname));
成果物
こちらをdenops
同様にvimのruntimepath
に追加し
cargo run --manifest-path=utils/denops-builder/Cargo.toml
でbuildする事でvimから:DenopsRustEcho
を実行できるようになります。
上手くいかない場合は
- cargo, sed, wasm-pack が利用可能か
- build時のcargoコマンドを実行する際のcurrent dir
- (runtimepathに追加した階層、project rootにあたるところで実行してください。普通にgit cloneしたところにcdしていただければ大丈夫です。)
- rustのバージョンは最新か(stableで動くはずですが、それでも駄目ならnightlyをつかってみてください。)
- denopsの他のプラグインは動作しているか, runtimepathは正しいか(2敗)
を確認してみてください。
ちなみにvimmerではない方もbuildまでは出来ますので、「denoでrustのwasmを使いたいけど上手くいかないよー」といった方も試してみていただければと思います。
Discussion
先客がいました、もっと早くみつけていれば楽だった...
diffのプラマイが逆です(後で直します)
後で試してみようと思います!
所でですが一箇所browserがbrouserになっているようです。
ありがとうございます!助かります!
他にもちょいちょいガバっている所があるのでぼちぼち修整します……