NeovimでGleamをやる
2024 5/21追記
mason.nvimがGleamサポートを削除したため、MasonInstall
を実行してもGleam本体がインストールされなくなっている。
理由としては、GleamがコンパイラやLSPを含む単一バイナリとして提供されていることで、mason.nvimでインストールされたGleamのバージョンとプロジェクトで使っているGleamのバージョンが合わなくなるという事例が多発したためらしい。
以下参考issue
この影響でmason.nvimとmason-lspconfig.nvimからGleamサポートが削除されたため、GleamのLSPを使うためにはlspconfig.nvimを使って設定を書かなくてはいけない。
以下は自分の設定。暫定的なものなので改善の余地がありそう。
local nvim_lsp = require("lspconfig")
if (vim.fs.dirname(vim.fs.find({ "gleam.toml" }, { upward = true })[1])) then
nvim_lsp.gleam.setup({})
end
Erlang周りを調べてたらGleamという言語を見つけたので試してみる
主な特徴として
- ErlangとJsにコンパイル出来る(Erlang VMで動く)
- Rustで書かれている
- 静的型付けかつ関数型言語
が挙げられる。まだバージョンが浅い(今現在0.2とかそのあたり)事も頭に入れたほうが良さそう
まずは環境を整える。一応JSバックエンドならWebでも実行できる。Vimで書きたいのとErlangバックエンドを使ってみたいのでローカルで実行する。
Github Releaseから最新のバージョンを落とす
パスが通ってればgleam
コマンドが実行できる。表示がわかりやすいのでヘルプをざっと読んでみるのもオススメ
次にプロジェクトを作成する
gleam new プロジェクト名
で作成できる。注意点として
- 半角英数字とアンダーバーしか使えない
-
gleam_*
は公式ライブラリが使うので使えない(いつも試し書きする時は言語名_exでプロジェクトを作っているのでハマった) -
.
でカレントに作る裏ワザ?が使えない(よく使ってるのでちょっと不便)
実行完了するとメッセージが表示されるので、その通りにコマンドを実行するとテストが実行される。
またgleam run
を実行するとHello World相当のものが実行される。このあたりもRustっぽい
エディタのプラグインについて
Vimを使ってるのでVimプラグインをインストールする。Vimに対応してるくらいなので他のエディタにも対応してると思う。手元にVSCodeが無いのでVSCodeについては差し控える。
Vimプラグインを適当にインストールしたらLSPを導入する。公式ブログが紹介してるので存在はありそう。issueを見るあたりかなり不安定そう(言語自体のバージョンが浅いのでしょうがない)なので注意。
GleamのLSPはgleam lsp
で起動できるらしい。ただ手元で実行したら速攻クラッシュしたので動作が謎。VimのLSPクライアントはMasonを使っているのでそれでなんとか起動させたい。
issueが立っているけれどそれ以降の音沙汰が無いので自分の方で試してみたい。
Githubで検索したら良い感じの検索が出てきた
に設定が書いてあったので試してみる
require'lspconfig'.gleam.setup{}
で動く
...動いたは良いものの、肝心の補完はそこまで効いてくれない。強いて言うならLinter。
Changelogにはimportのオートコンプリートをサポートしていると書いてあるのでパッケージの補完は効いてくれる。
とりあえず関数型言語(パターンマッチのある言語って言ったほうが良いかも)が得意なWebサーバーを書いてみる。
依存ライブラリがあるのでパッケージをインストールする
gleam add gleam_http
gleam add elli
ここのサンプルを動かしてみる...動かない
どうやらelliとやらが色々変更されているらしい。
elliのリポジトリ
gleamのhttpライブラリと分離してるっぽいけどほんとにgleam/http/elli
で読み込めるのか...?
GleamのPythonチートシート
Imports are relative to the root src folder.
Modules in the same directory will need to reference the entire path from src for the target module, even if the target module is in the same folder.
インポートは、ルートの src フォルダーに相対的です。
同じディレクトリ内のモジュールは、ターゲット モジュールが同じフォルダー内にある場合でも、ターゲット モジュールの src からのパス全体を参照する必要があります。
うん...?これはどういうことだ...?
import nasa/rocket_ship
とか書いてあるけど、これはNamed Importってやつらしい。でもsrcの周囲にhttpなんてないしなぁ...
gleam
っていうパッケージ名が特殊な可能性はありそう。標準ライブラリっぽいし
動いた!
やった手順を書いていく
まずインストールしたパッケージ名が間違っていた(紛らわしい...READMEにインストール手順を書くべきだと感じた)
ここを見れば分かるように、インストール時に指定するパッケージ名はgleam_elli
だった。なぜelliでも実行できたかというと、内部依存で使われているライブラリがelli
だから。普通逆やろ...
その後は普通にサンプルをコピペしたら動いた
import gleam/http/elli
import gleam/http/response.{Response}
import gleam/http/request.{Request}
import gleam/bit_builder.{BitBuilder}
// Define a HTTP service
//
pub fn my_service(_request: Request(t)) -> Response(BitBuilder) {
let body = bit_builder.from_string("Hello, world!")
response.new(200)
|> response.prepend_header("made-with", "Gleam")
|> response.set_body(body)
}
pub fn main() {
elli.become(my_service, on_port: 3000)
}
続編的な感じでElixirをやる