2015年を振り返る

2015年の自分向けまとめです.

まとめ

目標は達成できたかどうか分からないといけないと思っているので,2015年の趣味での目標は 「とりあえず10万行書くか」 だったんですが,測るのが面倒なので途中から「3000 contributions する」 になりました.(自分の場合は1コミット大体40行ぐらいが多いので,3000 あればまあ10万行行っとるやろという魂胆です)GitHub は仕事で使ってないので,GitHub のプロフィールページを見れば一発で達成状況が分かるという寸法です.

結果はというと…

f:id:rhysd:20151231211127p:plain

でどうにかギリギリ達成できました.来年はもっとパワフルに開発できる年にしたいです.

そんなわけで今年も割と色々書いた気がします.せっかくなので振り返ってみます.

前半

今年の前半は言語処理系まわりを色々触ってました.既存の言語の処理系を実装してみるのも間違いなく楽しいですが,自分で言語のデザインを考えてみるのもプログラミング自体を処理系の側の視点から見ることができてかなり楽しいです.もちろん実装も面白いです.

Dachs

犬言語.一応まだ死んでないつもりです.

Ruby テイストな構文ですがクラスのインスタンスに対するメソッド呼び出しは UFCS による構文糖衣で,全て関数です.関数型言語周りの機能と親和性を良くしたいなというのが狙いだったりします.変数はデフォルトで const で,const な変数のみ参照で渡せるようになっています.基本的に型はほとんど書かず頑張って推定(deduction)します.

今年の前半までは継続してつくっていて,今年は generic function type とかコピーやキャストの挙動を定義できるようにしたり,しょぼいモジュールの初期実装を入れたり,Boehm GC を乗っけたりしました.

ただ,やはりパーサのビルド時間がつらいのでそこをどうにかしないといけない感じです.犬言語では AST のノードの定義に boost::variant を使っていて,末端のノードは普通の struct ですが,例えば式のノードは using Expr = boost::variant<Literal, BinaryExpr, CallExpr, ...> のような実装になっています.これと Boost.Spirit V2 が合わさって型がめちゃくちゃ巨大になるのが一番の原因な気がしてます.別言語に乗り換えを試みるのも悪くなさそうです.

特に焦ることもないので,どういう言語機能があるとどうして自分のコーディングが楽しくなるのかとかそういったことを考えながら引き続き楽しんでやっていきたいです.

Crisp

Make a Lisp をベースにした Lisp の方言の処理系です.Crystal で書きました.動的言語の言語機能のアイデアを試すのに使えたらなーと思ってつくったので,特に実用は考えてませんが,Crystal と何かうまく連携できると良いなぁと思ってます.(が,現状思っているだけです…)

Make a Lisp で Lisp 処理系を学んでつくる (with Crystal)

後半

今年の後半はほぼ Electron アプリを JavaScript とか TypeScript で書いていた気がします.JavaScript はこれまでその場しのぎのコードをちょっと書いたことぐらいしかなかったですが,せっかくなので ES2015 ネイティブ(!)で勉強しました.TypeScript も JavaScript でありがちなケアレスミスを拾ってくれたり程良い感じがして結構気に入ってます.

NyaoVim

NyaoVim logo

Web Component で UI を拡張できる NeoVim フロントエンドです.以前は拡張するのが難しかった UI を HTML/CSS, JavaScript, Node.js, Electron API などを使って拡張する仕組みが用意されています.Neovim 本体も <neovim-editor> というコンポーネントの1つとして実装されています. まだなかなか基本機能が安定しなかったりしますが,継続して開発していきたいと考えています.

サンプルプラグインもいくつか書いてみました.

僕は基本的にはコマンドライン大好きなので Vimコマンドラインで使ってます.僕にとって GUIVimコマンドラインVim とは用途が違っていて,GUI のエディタはもっと強力な UI の表現力を持っていても良いのかなと思ったのが最初でした.

また,このフロントエンド実装は Proof of Concept な側面があると思っていて,例えば補完のインターフェースとして(既存の一覧表示ではなく)もっと良いアイデアが思いついた時に,それを簡単に試す事ができます.(例えば Vim 側で補完の候補一覧だけ生成して UI 側に渡し,UI 側でユーザからの入力を受け付けて結果を Neovim 側に戻すなど).実際に動く形で自分のアイデアが簡単に実装できるというのは大きいんじゃないかなと思っていて,僕自身も色々試してみたいと思ってます.

Web Components と Electron でつくる Neovim フロントエンドの未来

Shiba

shiba logo

マークダウンプレビューアプリです.管理しているパス(ディレクトリ/ファイル)のファイル保存を検知して自動でプレビューを更新します.Electron + Polymer でつくりましたが,色々実装が良くないところもあるのでぼちぼち作り直したいと思ってます.

  • タブを付けて複数パスを監視できるようにする
  • Markdown -> HTML の変換のパフォーマンスアップ
  • コンポーネント追加でプレビュー拡張(例えば新しいフォーマットをプレビューの対象に加えられるようにしたりとか)

Electron と Polymer と TypeScript でリッチなマークダウンプレビュアー Shiba つくった

Trendy

Trendy logo

GitHub のトレンドリポジトリのページを監視して新規リポジトリを通知したり管理したりできます.メニューバーにアイコンを置いて,通知があるときはアイコンの色を変えることで通知します.メニューバーからアクセスできるので,気になった時にさっと見ることができます.

GitHub のトレンドリポジトリを見逃さない,Trendy をつくりました

Tilectron

Tilectron logo

ウィンドウ分割可能なブラウザです.タイル型のウィンドウ管理で広いディスプレイを活用しつつ,スクロールやカーソル移動などすべての操作をキーボードのみでやることが目的です.すでにポインタ動かしたりクリックを入力したりとかは技術的にはできるのはわかってるんですが,なかなか手を付けられていない状態です…

ぼちぼち進めて行きたい.

発表

東京 Node 学園祭,VimConf 2015,Effective Modern C++ 読書会で発表させてもらいました.

  • 東京 Node 学園祭

東京Node学園祭 2015 で Electron について話した

  • VimConf 2015

vimconf でブラウザ上で Vim を使う方法を発表してきた

  • Effective Modern C++読書会

原著を一通り読んで合計 4 items 分ぐらい発表させてもらいました.C++11 や C++14 時代に必須な内容もあったりでおすすめできる内容でした.邦訳も出ました.

その他つくったものリスト

その他にも色々つくったりした気がします.結構つくって忘れているものもあるので,「こんなのもあったなー」と思い出すのもかねてリストアップ.(完全につくりかけは除く)

Web Components と Electron でつくる Neovim フロントエンドの未来

この記事は Vim Advent Calendar 2015 の20日目の記事です.

まずはこちらのスクリーンショットをご覧ください.

markdown example screenshot

image popup example screenshot

mini browser example screenshot

エディタの UI やカーソル移動は Vim っぽいですが,markdown ライブプレビューやカーソル位置での画像ポップアップ,組み込みブラウザなど謎の UI が見て取れます.本記事ではこれについてボトムアップで必要な知識から順を追って紹介します.

長い……三行で

目次

  1. Web Components とは
  2. Neovim の フロントエンド向け msgpack-rpc API
  3. Neovim の UI を Web Component としてラップする
  4. Electron アプリに組み込んでみた例
  5. UI 拡張可能な Neovim フロントエンド NyaoVim
  6. 実装の経緯
  7. まとめ
  8. おまけ

Web Components とは

HTML 標準として Web Components という新機能が策定されています. Custom Element, Template, Shadow DOM, HTML import といくつかの機能に分かれていますが,<div></div> といった慣れ親しんだ要素に加え,<foo-bar></foo-bar> といったカスタム要素をつくることができるようになります.CSS は本来グローバルですが,カスタム要素内で定義されている CSSコンポーネント内のみに適用され外に染み出しません.また,従来の DOM 要素のようにプロパティや対応する class にメソッドを生やしたりしてカスタマイズ可能にしたりできます. 具体的なカスタム要素のつくり方やもっと正しい説明が知りたい方は下記の html5rocks の記事などが役に立ちます.

Custom Elements; HTML に新しい要素を定義する

まだ仕様が fix されていない機能ですが,GooglePolymer など Web Component をラップして使いやすくしたライブラリがすでにいくつかあり,再利用可能なコンポーネントが提供されています.

Neovim の UI msgpack-rpc API

Neovim には msgpack-rpc で呼び出せる API があり,プラグインを別プロセスで動かして Neovim 本体と通信する remote plugin などで使われています.ウィンドウ・タブ・バッファの情報を収集したり Neovim に指定文字列を入力したり,コマンドを実行したり Vim script を eval したり色々できますが,その中に1つ vim_ui_attach という特別なものがあります.

vim_ui_attach を呼ぶと,それ以降 Neovim 側から呼び出し元側のプロセスに UI の描画イベントが通知されるようになります.それぞれの通知はイベント名とその引数を持っています.

イベント名 説明
put 引数で渡されたテキストをカーソル位置以降に描画する
cursor_goto 引数で指定された (line, col) にカーソルを移動する
highlight_set 描画する文字や背景の色をセットする
clear 画面全体をクリアする
eol_clear カーソル位置から行末までクリアする
scroll 引数で与えられた行数だけ縦にスクロールする
set_scroll_region スクロールする範囲をセットする
resize 画面のサイズ(行数,桁数)を変更する
update_fg foreground color を引数で与えられた色にセットする
update_bg background color を引数で与えられた色にセットする
mode_change 現在のモードを引数で指定されたモードに変更する(normal, insert など)
busy_start 入力を受け付けない状態を開始する
busy_stop 入力を受け付けない状態を終了する
mouse_on マウスを有効にする
mouse_off マウスを無効にする
bell ベル音を鳴らす
visual_bell ビジュアルベルを表示する
set_title ウィンドウタイトルを引数で指定された文字列にセットする
set_icon ウィンドウアイコンを引数で指定されたパスの画像にセットする

見ての通り,かなりステートフルな通知が飛んでくるので,カーソル位置などの状態を保持しつつ来たイベントを順番に処理して描画していけば Neovim の画面を描画することができます.

Neovim では nvim --embed で起動することでヘッドレスで実行し,エディタの描画を別の UI プロセスに任せるフロントエンド-バックエンド型のアーキテクチャをサポートしていて,すでに neovim-qtneovim-dot-app などの Neovim フロントエンドが存在します.

Neovim の UI を <canvas> に描画して WebComponent としてラップする

上記で説明した msgpack-rpc を介した UI 描画イベント通知の API を使って HTML の <canvas> 上に Neovim のフロントエンド部分を描画し,それを Web Component としてラップしてみました.

github.com

HTML 上に描画するという選択をしたのは,近年 NW.jsElectron といったデスクトップアプリフレームワークが出てきていて,容易に Neovim エディタをこれらで作成したアプリに組み込めるようになるからです. また,WebSocket などで通信して描画情報を受け取ればリモートにある Neovim を手元のブラウザに描画して処理するなども可能です.

今回はローカルで実行できるようにしたいので,外部プロセスとして Neovim を実行し標準入出力で通信します.ブラウザ内では外部プロセスを起こせないので,Node.js の child_process モジュールで子プロセスを管理します.このことから分かる通り,今回のアプローチでは一般的なウェブサービスに組み込むことはできませんが,Electron アプリなどの Node.js が統合された環境では利用できます.

ユーザからの入力や Neovim プロセスからの通知などのデータフローをうまく扱いつつ,カーソル位置などの状態を適切に更新するために Flux というアーキテクチャを使います.

flux architecture

(https://facebook.github.io/flux/docs/overview.html#content より引用)

ユーザからの入力や Neovim プロセスからのイベント通知といった状態を変更する処理を Action として定義し,ディスパッチャを通してのみアクションを発行できるようにします.発行されたアクションは store を変更し,store を listen していた view が store の状態変更を受けて描画処理をします.これによってデータの流れる方向を単方向にします. つまり,GUI ではよくある publisher / subscriber な実装パターンです.

data flow

今回はこんな感じになりました. 緑色の部分が JavaScript(実際に書いたのは TypeScript ですが)で書かれていて,view を描画する Screen,Neovim プロセスとやりとりする ProcessHandler(ここは双方向にならざるを得ない),処理に対応する Action 群,状態を一括管理する Store のそれぞれのクラスで構成されています. ユーザからの入力は Action として発行され,Store を通じてそれを subscribe している ProcessHandler に送られて最終的に Neovim プロセスに届きます.また逆に Neovim プロセスからの通知は ProcessHandler が一旦受けた後アクションとして発行され,Store を通じてそれを subscribe している Screen が描画情報を反映します.

Flux は React.js と一緒に語られることが多いですが,特にそういった制約は無く,今回は Screen<canvas>fillRect()fillText() といった canvas API で描画するだけのオブジェクトです.また,Store は単一のデカイ EventEmitter として実装されています. 最終的に上記のクラスをすべて持った editor オブジェクトのプロパティに上記クラスのオブジェクトを全て持って,editor オブジェクトを通してすべてのオブジェクトにアクセスできるようにしておきます. 少し一般的な flux なウェブアプリと違うのは,store がコンポーネントローカルなところでしょうか.これはコンポーネント複数設置される可能性などを考えてこうなっています.

今回はこの Neovim フロントエンド実装を Web Component として定義したいので neovim-editor という Polymer element を作成 します.コンポーネントのカスタマイズ(e.g. Neovim に渡す引数)はコンポーネントのプロパティとして設定できるようにします.上記の editor オブジェクトをコンポーネントのプロパティとして持つことで,<neovim-component> 要素を通じて Screen, ProcessHandler, Store といったすべての情報に JavaScript 経由でアクセスできます

なお,試していませんが,おそらく Atom editor や VisualStudio Code といった Electron 上につくられたエディタのプラグインとしても使えるのではないかと思います(エディタの中にエディタを組込むのがどれくらい嬉しいかは別問題ですが…)

Electron アプリに組み込んでみた例

というわけで本記事冒頭でお見せした3枚のスクリーンショットは全て <neovim-component> に別のコンポーネントを組み合わせた例でした.neovim-component リポジトリ ではいくつかの例を Electron アプリとして公開しています.

https://github.com/rhysd/neovim-component/tree/master/example

各 example のディレクトリ内の README に従えば実行できるはずです.各 example は 100〜300行程度で書かれています.

例えば Neovim と markdown プレビューを合体させた markdown エディタの例 では marked を使ってつくった <markdown-viewer> コンポーネント(markdown テキストをセットすると HTML で描画してくれる)を下記のように配置しています.

<body>
  <neovim-editor id="neovim" font="Ricty,monospace" width="800" height="1000"></neovim-editor>
  <markdown-viewer id="mdviewer"></markdown-viewer>
</body>

あとは Neovim 側から TextChanged および TextChangedI でバッファのテキストが変更されるたびにバッファのテキストを rpcnotify() 関数で通知し,それを受けて <markdown-viewer> コンポーネントにテキストを渡す処理を JavaScript で書いてやるだけです.これによって入力をリアルタイムにプレビューに反映できます.

上記の例では,vim_command msgpack-rpc API を使って直接 Neovim 側の autocmd を定義しています.

UI 拡張可能な Neovim フロントエンド NyaoVim

実は今回は 高度に UI 拡張可能な Neovim フロントエンドをつくる のが目的で neovim-component は飽くまでこれをつくるパーツに過ぎません.

というわけで,Web Component を使って HTML, CSS, JavaScript,Node.js, Electron API,Neovim msgpack-rpc API を使って UI を拡張できる Neovim フロントエンド NyaoVim をつくっています.

NyaoVim

github.com

Vim が何でないのかが書かれている :help design-not@ja には次のような記述があります.

Vim をシェルや IDEコンポーネントとして使おう

NyaoVim では Neovim フロントエンドを1つのコンポーネントとして,アプリ内に複数の Web Component を置き,他の Web Component と連携する形で UI を拡張する仕組みを提供します.

NyaoVim が目指すゴールは下記の通りです.

  • NyaoVim 本体は(gVim のような)最小限の Neovim の UI と Web Component によってユーザが自由に UI を拡張できる仕組みのみを提供します.ユーザはそれを使って自分の好きなコンポーネントを作成・インストールして拡張します.
  • UI 拡張は Neovim プラグインとして提供できるようにし,新たなプラグインマネージャを必要としないように設計します.これによって vim-plug など Vim プラグインマネージャを使って UI 用のプラグインも管理できます.
  • Neovim(もしくは Vim)本来のエディタとしての機能性(高い応答性など)を損なわないように実装します.
  • Linux, OS X, Windows 対応のクロスプラットフォーム(現時点では Windows をサポートできる段階にまだきていないですが…)

structure

ためしてみる

NyaoVim はまだつくりはじめた段階で,つい一昨日 UI プラグインをロードできる実装を入れたところです.<neovim-component> も含めてまだ実用できるレベルになっていませんが,version 0.0.2 として npm パッケージとして公開しています.

$ npm install -g nyaovim
$ nyaovim

実行するとシンプルな Neovim の GUI エディタが立ち上がります.

サンプルプラグインとして nyaovim-popup-tooltip を作成したので,これを入れてみましょう.

https://github.com/rhysd/nyaovim-popup-tooltip

UI プラグインnyaovim-plugin というディレクトリを runtimepath に含んだ普通の Neovim プラグインなので,他のプラグイン同様にプラグインマネージャでインストールできます.例えば neobundle.vim を使う場合は下記のように init.vim に書いて :NeoBundleInstall します.

NeoBundle 'rhysd/nyaovim-popup-tooltip'

一度でも nyaovim を実行していると ~/.config/nyaovim/nyaovimrc.html が生成されているはずです.このHTMLファイルが NyaoVim の設定ファイルです.nyaovim-popup-tooltip/nyaovim-plugin/popup-tooltip.html で提供されている <popup-tooltip> を下記のように追加します.

<dom-module id="nyaovim-app">
  <template>
    <style>
      /* CSS configurations here */
    </style>

    <!-- Component tags here -->
    <neovim-editor id="nyaovim-editor" argv$="[[argv]]" font-size="14" font="Ricty,monospace"></neovim-editor>
    <popup-tooltip editor="[[editor]]"></popup-tooltip>
  </template>
</dom-module>

<script src="file:///path/to/nyaovim-app.js"></script>

HTML ファイルを設定ファイルとして使うことで,ユーザは自由にエディタ内のコンポーネントCSS でレイアウトでき,コンポーネントのプロパティを使ってカスタマイズすることができ,追加の処理を JavaScript で記述できます.

ここで editor="[[editor]]" というプロパティが目をひくかもしれませんが,これは Polymer が提供しているデータバインディングで,<neovim-editor> コンポーネントの紹介時に説明した editor オブジェクトがプラグイン側に渡ってきています.NyaoVim の UI プラグインとしては Polymer を必須にしているわけではないので,ここではふーん程度にスルーしてください.

準備ができたら nyaovim でエディタを立ち上げて何かドキュメントを開いてみましょう.http リンクでもローカルファイルへのリンクでも良いので,画像へのリンクの上にカーソルを持って行って gi を入力してみてください.

全てがうまくいっていれば下記のようにポップアップでカーソル下の画像がプレビューできます.

nyaovim-popup-tooltip screenshot

NyaoVim の README には UI プラグインの作り方も(ざっくりと)書きましたが,長くなりすぎるのでここでは紹介を避けます.気になる方がいらっしゃればリンク先を読んでみてください.

実装の経緯

元々 Lime textCUIGUI の両方をサポートするためにフロントエンド(表示側)とバックエンド(コア)を完全に分けた設計をしていてそういうアーキテクチャに興味があったので,Neovim でも似たようなことができると知り調査を始めました.

今年は Electron アプリをつくったりしていたので Electron で実装するかというのをざっくり決めて公式の node client を試したところうまく動かず,API 的にもコールバック祭になってしまいそうだったのでまずは node client を fork しました.

動的に生成される Neovim msgpack-rpc API 向けのメソッドをコールバックから bluebird の Promise を返すように書き換え,TypeScript がリポジトリ直下に置いている index.d.ts を見てくれるようになったのでそれに対応し,いくつかバグを修正しました.API をガラッと変えてしまったため,本家への PR はリジェクトされて fork を使い続けることにしました.

これで準備が整ったので NyaoVim のプロトタイプを書き始めました.最初は ReactRedux を使って DOM で Neovim の UI を描画していました.React で最小限の範囲だけ差分描画すれば問題ないかなと思っていたのですが,例えば <C-e> などで画面全体をスクロールしたりすると DOM が全書き換えになってしまい描画がもっさりしてしまう問題に当たってしまいました.

ここで react-canvasreact-pixi を使うという手もありましたが今後もメンテされ続けるかがかなり怪しかったため,素直に <canvas> に直接描画するためにスクラッチから実装しなおしました.

この時に Web Component として実装して他の UI として組み立てるというアイデアを思いつき,<neovim-editor> を実装した後は NyaoVim のプロトタイプを全て捨てて新しく実装しました(というか実装中です).

まとめ

Vim は 'Vim is a text editor' というフレーズが示すように編集に関係ない機能を受け付けない方針で開発されてきたため,グラフィカルな表現は苦手な面がありました.僕もその方針はとても気に入っているのですが,やはりグラフィカルな補助がほしくなるときもあります(例えばドキュメントとか最近は大体 HTML で出力されますし).

そんなわけで今回僕は Web 周りの技術を使ってユーザが自由に拡張できる UI プラグイン機構を neovim-component をつくって Neovim フロントエンド NyaoVim をつくりました.HTML/CSS でつくれる UI なら何でもつくれますし,膨大な npm パッケージも使えるので,良ければぜひ有用なパッケージとか有用じゃないパッケージとかつくって遊んでみてください.

おまけ

omake

github.com

Crystal でのプログラミングを支援するツール達

この記事は Crystal Advent Calendar 2015 の13日目の記事です.

Ruby の構文が好きなので Crystal もぼちぼち触っていて,標準ライブラリに Random::MT19937 とか Array#transpose を実装したり,Lisp 実装してみたりコマンドラインからドキュメント開くやつつくったりしています.

また,Vim 上で Crystal のコードを書くために vim-crystal というファイルタイププラグインをつくっていて,これから紹介するいくつかのツールも統合されています.

Crystal はつくりかけの言語であり,まだまだ言語機能的にも変更があったり足りないところがあったりしますが,つくりかけながらもプラグラミングをサポートする機能やツールがいくつかあります.今回はそれらを紹介します.

紹介するツール

Crystal Tool

Crystal Tool は Crystal コンパイラが公式にサポートしているツール群です.コンパイラの一部として実装されているので,下記のコマンドで概要が表示されます.

$ crystal tool

実装者は implementationscontext@bcardiff さん,それ以外は @asterite さんです.

format

crystal tool format はコードを整形するフォーマッタです.Crystal で推奨されているコードスタイルでコードを整形できます.最初は公式でフォーマッタが実装される予定は無かったのですが,方針が変わり 0.9.0 で実装されました.

引数を何も指定しないとカレントディレクトリ下の Crystal コードを,ディレクトリを指定するとそのディレクトリ下の Crystal コードを,ファイルを指定するとそのファイルをそれぞれ整形します.

~/Dev/github.com/rhysd/Crisp % crystal tool format
Format ./foo.cr
Format ./spec/helper.cr
Format ./src/crisp/core.cr
Format ./src/crisp/env.cr
Format ./src/crisp/error.cr
Format ./src/crisp/evaluator.cr
Format ./src/crisp/expr.cr
Format ./src/crisp/interpreter.cr
Format ./src/crisp/printer.cr
Format ./src/crisp/reader.cr

どんな感じで整形されるのかは,試しに自分のプロジェクトに整形をかけてみた diff を gist に貼ったので,そちらを見てみてください.

Go 言語の gofmt のように,Crystal のコードを書く時はこれでコードを整形することが推奨されています.vim-crystal では Vim のコマンドで直接カレントバッファを整形したり,保存時に整形したりできます.

implementations, context

crystal tool implementations は,メソッド呼び出しから呼び出し元がどこで定義されているかを解析します.

また,crystal tool context は Crystal コードの特定の箇所におけるコンテキスト(式や変数およびその型)を表示してくれます.

Open Class などの機能がある Crystal ではコード全体を見ないと特定箇所のコンテキストが定まらないので,これらのツールはプロジェクト全体のファイルをターゲットとして実行する必要があります.また,-c でファイル内の位置を指定する必要があります.出力は -f で指定でき,人間に優しい text フォーマットとプログラムに優しい json フォーマットが選べます. ユーザが直接使うものというよりは Crystal 用のツールやエディタプラグインが使うもので,atom-crystal-tools, vim-crystal では既にサポートされています.

Crystal は型推論やテンプレートを使って極力型を書かなくて良いようになっているので,こういったツールで式が実際にどのような型になっているのかや,どこのどのメソッドを呼び出しているのかなどを確認できます.

手前味噌ですが,vim-crystal ではこのようにカーソル下の呼び出し元にジャンプしたり,カーソル下のコンテキストが表示できたりします.

screenshort screenshot

hierarchy

crystal tool hierarchy は,指定したファイルのクラス階層を表示してくれるツールです.これによって,実際にメソッドのテンプレートがどのようなメソッドを生成しているかや,ジェネリックなクラスがどのようなクラス (struct) を生成しているかを見ることができます.Crystal のコードを書いている時だけでなく,Crystal コンパイラ本体のデバッグをしている時にも便利です.

試しに手元のプロジェクトで crystal tool hierarchy を実行してみた 出力結果を gist に貼ってみました

なお,vim-crystal では :CrystalHierarchy でカレントバッファに対して直接実行できます.

crdoc

github.com

crdocコマンドラインから Crystal のドキュメントを開くためのコマンドラインツールで,Crystal で書かれています.

Crystal は元々ドキュメントサーバを立ててブラウザからドキュメントを見られる仕組みがあるのですが,コマンドライン内でコードを書いているときはシェルから直接ドキュメントを開けると良いなと思いつくりました.

main usage

release ページ から落としてきたバイナリなり,ビルドしたバイナリなりを PATH の通ったディレクトリに置くとすぐ使えます.初回時にキャッシュを生成するためにリポジトリを clone してくるので,少しだけ時間がかかります.

基本的には crdoc search 検索ワード で検索し,複数の候補が見つかった場合は選択肢が表示されますので,番号で指定すると対応するドキュメントが開きます.

また,pecopercol のようなフィルタリングツールも意識していて,例えば OS X だと下記のようなコマンドでドキュメントをインタラクティブに絞り込んで選択できます.

$ open "$(crdoc list --path | peco)"
$ open "$(crdoc list --path | percol)"

peco example

この他にも rake の Crystal 版である crake など,色々なツールが Crystal で書かれています.

Playground

最近の多くの言語にあるように,実は Crystal にもブラウザ上で言語を試せる Playground があります.Crystal collaborator の @jhass さん作です.

carc.in

常にリリースされた最新の Crystal が利用できるようになっており,バグ報告やコードの共有などで使われています. Crystal は LinuxOS X では簡単にインストールできますが,それ以外の対応できていないプラットフォームでは playground で Crystal を試すことが出来ます.

f:id:rhysd:20151212182246p:plain

まとめ

Crystal のコードを書く上で便利なツールを紹介しました.これ以外にも依存管理をやってくれる shards など便利なツールがたくさんあるので,ガンガン活用していきたいです.