Closed14

NeovimでGleamをやる

ピン留めされたアイテム
こまもか🦊こまもか🦊

2024 5/21追記

mason.nvimがGleamサポートを削除したため、MasonInstallを実行してもGleam本体がインストールされなくなっている。

理由としては、GleamがコンパイラやLSPを含む単一バイナリとして提供されていることで、mason.nvimでインストールされたGleamのバージョンとプロジェクトで使っているGleamのバージョンが合わなくなるという事例が多発したためらしい。
以下参考issue

https://github.com/mason-org/mason-registry/pull/3872

この影響で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が立っているけれどそれ以降の音沙汰が無いので自分の方で試してみたい。

こまもか🦊こまもか🦊

に設定が書いてあったので試してみる
require'lspconfig'.gleam.setup{}
で動く

...動いたは良いものの、肝心の補完はそこまで効いてくれない。強いて言うならLinter。

Changelogにはimportのオートコンプリートをサポートしていると書いてあるのでパッケージの補完は効いてくれる。

こまもか🦊こまもか🦊

とりあえず関数型言語(パターンマッチのある言語って言ったほうが良いかも)が得意なWebサーバーを書いてみる。

依存ライブラリがあるのでパッケージをインストールする

gleam add gleam_http
gleam add elli

ここのサンプルを動かしてみる...動かない

どうやら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っていうパッケージ名が特殊な可能性はありそう。標準ライブラリっぽいし

こまもか🦊こまもか🦊

https://twitter.com/Comamoca_/status/1625915580338552832?s=20

動いた!

やった手順を書いていく

まずインストールしたパッケージ名が間違っていた(紛らわしい...READMEにインストール手順を書くべきだと感じた)
ここを見れば分かるように、インストール時に指定するパッケージ名はgleam_elliだった。なぜelliでも実行できたかというと、内部依存で使われているライブラリがelliだから。普通逆やろ...

その後は普通にサンプルをコピペしたら動いた

ハイライトをかけるために言語指定をPythonにしています
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)
}
このスクラップは2023/05/15にクローズされました