15
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

RubyKaigi 2023で行ったLTの解説

Posted at

はじめに

RubyKaigiとの連動企画ということで、先日行ったRubyKaigi 2023でのLTのセルフ解説をしたいと思います。

題材

rspec-current.vimという、カーソルの位置に応じたsubjectcontextの内容を返すRSpec用VimプラグインをRubyで書きました。LTではこのプラグインの解説をメインに行いました。

実装の解説

プラグインの名前こそ.vimですが、中身はほぼ全てがRubyで書かれています。特にRubyVM::AbstractSyntaxTreeクラスを使うところが肝で、ASTを取得することでそこから構文要素(例えばsubject { described_class.call }における"described_class.call"に当たる部分)を取り出すことができます。この際、Ruby3.2で追加されたkeep_tokens: trueオプションを利用する必要がありました。

トーク中で流したnode.children.last.children.last.tokens.map { _1[2] }.joinの部分ですが、最初のnodeがsubjectを包むITERノード、そのchildren.lastSCOPEノード、そのさらにchildren.lastCALLノード、そこにtokensメソッドを呼ぶことで各要素が配列の配列として返ってきます。各要素はその3番目の要素がトークンの文字列であるような配列であるので、_1[2]でそれを取得してjoinすると元のソースコードに近い文字列を得ることができます。このへんの詳細は金子さんの記事を参照するとわかりやすいです。

簡単なの?

発表の中でこのプラグインのようなものを作ることは"Easy"だと言いましたが、実際はどうなのでしょうか。たしかに、実装としてはASTをいじる以外に難しいことはやってはいません。

ただし、実装している最中はASTを手探りするしかありませんでした。各ノードの構造についてはドキュメントが一切なく(意図的なものだと思います)、そのためまずはRubyだけのVimとは無関係なファイルを用意してそこで色々実験して、得られた知見をVimプラグインに適用する形で実装を進めました。

rubyevalを用いる方法も、一度気づいてしまえばなんてことはないのですが、最初はRubyからVimに値を返す方法がわかっていませんでした。このへんはVimプラグインを書いたことがないということが大きいですね。

15
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?