ペンギン村 Tech Blog

技術をこよなく愛するエンジニア集団が在住するペンギン村から、世界へ役立つ(かもしれない)技術情報を発信する技術系ブログです。某アラレちゃんが済む村とは一切関係ありません。んちゃ!

Mac での Crystal 1.0.0 の開発環境の構築(VSCode)

Crystal 本体

Homebrew でインストールできる。

$ brew update
$ brew install crystal

バージョンを確認してみる。

$ crystal --version
Crystal 1.0.0 (2021-03-22)

LLVM: 9.0.1
Default target: x86_64-apple-macosx

参考: Install On macOS - The Crystal Programming Language

VSCode 拡張:Crystal Language

以下のリンクからインストール。

marketplace.visualstudio.com

設定(Cmd + , )から crystal で絞り込んで、以下の3つをチェック。(いずれも不安定な機能とのことだが、個人的にはあったほうが少し嬉しい)

f:id:yu_dotnet2004:20210423135733p:plain

なお、Language Server として crystallinescry が開発されているが、現状ではどちらも不安定なので個人的にはあまりオススメしない。

参考: Home · crystal-lang-tools/vscode-crystal-lang Wiki · GitHub

静的解析ツール:ameba

Ruby における RuboCop のような静的解析ツール。

github.com

Homebrew でインストールできる。

$ brew tap veelenga/tap
$ brew install ameba

プロジェクトルートで ameba を実行すれば静的解析を実行できる。 f:id:yu_dotnet2004:20210423135800p:plain

VSCode 拡張として crystal-ameba も用意されているので、インストールしておくと非常に便利。

marketplace.visualstudio.com

f:id:yu_dotnet2004:20210423135815p:plain

VSCode 拡張:Auto Add Brackets in String Interpolation

Crystal は Ruby と同様に "Hello, #{name}" といったシンタックスで文字列インターポレーションが行えるが、以下の拡張を入れておくと # だけ入力すれば #{} になるので便利。

marketplace.visualstudio.com

お好みで。

VSCode 拡張:Auto Comment Blocks

Crystal では # でコメントを記述できるが、以下の拡張を入れておくと Shift + Enter したときにコメント行を自動的に続けてくれるので、ドキュメンテーションコメントを記述する際に便利。

marketplace.visualstudio.com

Settings.json に以下の設定を追加すれば Crystal でも動作するようになる。

{
    "auto-comment-blocks.hashStyleBlocks": [
        "crystal"
    ]
}

お好みで。

標準で入ってるツール

Crystal 本体(と VSCode 拡張)をインストールしていれば以下が使える。

フォーマッター:crystal tool format

VSCode 上で Option + Shift + F でフォーマットできる。

保存時に自動的にフォーマットしたい場合は、VSCode の設定画面から以下をチェックしておく。 f:id:yu_dotnet2004:20210423135837p:plain

なお、コマンドラインから実行する場合は crystal tool format

$ crystal tool format
Format ./src/assert-diff/expectations.cr
...

CI などで、きちんとフォーマット済みか確認したい場合は --check オプションを渡す。

$ crystal tool format --check
formatting './src/assert-diff/expectations.cr' produced changes

テスト:crystal spec

RSpec ライクな記述ができる Spec が同梱されている。

プロジェクトルート上で crystal spec を実行すれば全テストが実行される。 f:id:yu_dotnet2004:20210423135850p:plain

なおテストの一覧を見たい場合には --verbose オプションを付けて実行すれば OK。 f:id:yu_dotnet2004:20210423135905p:plain

ドキュメント生成:crystal doc

プロジェクトルートで crystal doc を実行することで、標準 API ドキュメント と同じ形式の API ドキュメントが生成できる。

$ crystal doc
$ open ./docs/index.html # ブラウザで開く

f:id:yu_dotnet2004:20210423135917p:plain

なお、crystal init でプロジェクトを生成した場合、docs.gitignore で無視されているので、GitHub Pages で公開したい場合には外す。

# .gitignore
# /docs/

ただ、そうすると VSCode 上で docs フォルダ内も検索対象になって面倒なので、.vscode/settings.json を以下の内容で作成しておくと無視されるようになる。

{
    "search.exclude": {
        "docs": true,
    },
}

完全に認識させないようにするなら、代わりにfiles.exclude を利用すれば OK。(私はこちらを利用している)

パッケージマネージャ:shards

標準でパッケージマネージャとして shards が提供されている。

crystal-lang.org

$ shards --help
shards [<options>...] [<command>]

...

ここでは詳細については割愛。

Playground

crystal play でローカルサーバが立ち上がる。

$ crystal play
Listening on http://127.0.0.1:8080

f:id:yu_dotnet2004:20210423135935p:plain

画面右側の値をクリックすることで、繰り返し実行された内容の確認もできる。

f:id:yu_dotnet2004:20210423135954p:plain

REPL

公式では REPL は提供されていないが、icr という REPL が開発されている。

github.com

f:id:yu_dotnet2004:20210423140013p:plain

入力された内容ごとにソース作成・コンパイル・実行をするという単純なものなので、基本的には Playground を使ったほうが便利かと思われる。

なお、REPL ではないが crystal eval で評価することはできる。

$ crystal eval 'puts Time.local'
2021-04-23 13:13:50 +09:00

CI

公式のドキュメント Continuous Integration - Crystal に詳しく書かれているが、GitHub Actions なら例えば。

on:
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Download source
        uses: actions/checkout@v2

      # Crystal 本体をインストール
      - name: Install Crystal
        uses: oprypin/install-crystal@v1

      # 依存パッケージを解決
      - name: Install shards
        run: shards install

      # フォーマット済みかチェック
      - name: Check formatting
        run: crystal tool format --check

      # テスト実行
      - name: Run tests
        run: crystal spec

おまけ:Hello, world

crystal init でプロジェクトを作成できる。

$ crystal init app hello
    create  /Users/yusuke/Desktop/crystal-work/hello/.gitignore
    create  /Users/yusuke/Desktop/crystal-work/hello/.editorconfig
    create  /Users/yusuke/Desktop/crystal-work/hello/LICENSE
    create  /Users/yusuke/Desktop/crystal-work/hello/README.md
    create  /Users/yusuke/Desktop/crystal-work/hello/.travis.yml
    create  /Users/yusuke/Desktop/crystal-work/hello/shard.yml
    create  /Users/yusuke/Desktop/crystal-work/hello/src/hello.cr
    create  /Users/yusuke/Desktop/crystal-work/hello/spec/spec_helper.cr
    create  /Users/yusuke/Desktop/crystal-work/hello/spec/hello_spec.cr
Initialized empty Git repository in /Users/yusuke/Desktop/crystal-work/hello/.git/

VSCode で開く。

$ code hello

とりあえず初期コミットしておく。

$ git add -A
$ git commit -m "init"

add メソッドの作成・テスト

src/hello.cradd メソッドを作成してみる。 f:id:yu_dotnet2004:20210423140055p:plain

spec/hello_spec.cr を開き、既存のテストコードをコメントアウトした上でテストを作成する。(ここでは意図的に失敗するはずの値を入れている) f:id:yu_dotnet2004:20210423140117p:plain

crystal spec で実行すると、10 を期待したのに結果は 2 だったと想定通りの失敗をした。 f:id:yu_dotnet2004:20210423140131p:plain

期待値を本来の 2 に変更して、再度 crystal spec して成功することを確認。 f:id:yu_dotnet2004:20210423140147p:plain

フォーマッタの確認

フォーマッタの確認として、とりあえずコードのフォーマットをめちゃくちゃにしてみる。

f:id:yu_dotnet2004:20210423140203p:plain

Option + Shift + F で元通り。

f:id:yu_dotnet2004:20210423140214p:plain

ameba の動作チェック

ルールに引っかかるように未使用変数 foo を追加してみると、ちゃんと検出される。

f:id:yu_dotnet2004:20210423140227p:plain

コマンドラインからも問題なし。

f:id:yu_dotnet2004:20210423140242p:plain

ドキュメント生成

試しにドキュメンテーションコメントを書いて、

f:id:yu_dotnet2004:20210423140300p:plain

crystal doc で生成してみる。

$ crystal doc

ブラウザで開くととりあえず生成されている。

$ open ./docs/index.html

f:id:yu_dotnet2004:20210423140314p:plain

Hello モジュールを開いてみると、ちゃんとドキュメンテーションコメントが反映されている。

f:id:yu_dotnet2004:20210423140328p:plain

次のステップ

公式ドキュメントが驚くほど丁寧に書かれているので参考にするとよい。

crystal-lang.org

英語が苦手な人は、日本人の方が書かれた以下も参考になる。

crystal-jp.github.io

メジャーなパッケージ・ツールについては awesome-crystal が参考になる。

github.com

もっと色んなものを探したくなったら、Crystal Shards なども。

crystalshards.xyz

おわりに

というわけで、これから Crystal を始めようかと思っている方向けに Mac / VSCode での開発環境構築の記事を書いてみました。

私も最近 Crystal を書き始めたばかりで、まだベストプラクティスの確立には至っていない段階ですが、何かの参考になれば幸いです。

実際に Crystal を使ってみた感想的なものについては以下の記事もよろしければ。

blog.penginmura.tech

Written by @tobi462.

P.S.

Crystal はいいぞ。